jwt_compact/alg/
generic.rs

1//! Generic traits providing uniform interfaces for a certain cryptosystem
2//! across different backends.
3
4use alloc::{borrow::Cow, vec::Vec};
5use core::{fmt, ops};
6
7use zeroize::Zeroize;
8
9use crate::Algorithm;
10
11/// Verifying key for a specific signature cryptosystem. In the case of public-key cryptosystems,
12/// this is a public key.
13///
14/// This trait provides a uniform interface for different backends / implementations
15/// of the same cryptosystem.
16pub trait VerifyingKey<T>: Sized
17where
18    T: Algorithm<VerifyingKey = Self>,
19{
20    /// Creates a key from `raw` bytes. Returns an error if the bytes do not represent
21    /// a valid key.
22    fn from_slice(raw: &[u8]) -> anyhow::Result<Self>;
23
24    /// Returns the key as raw bytes.
25    ///
26    /// Implementations should return `Cow::Borrowed` whenever possible (that is, if the bytes
27    /// are actually stored within the implementing data structure).
28    fn as_bytes(&self) -> Cow<'_, [u8]>;
29}
30
31/// Signing key for a specific signature cryptosystem. In the case of public-key cryptosystems,
32/// this is a private key.
33///
34/// This trait provides a uniform interface for different backends / implementations
35/// of the same cryptosystem.
36pub trait SigningKey<T>: Sized
37where
38    T: Algorithm<SigningKey = Self>,
39{
40    /// Creates a key from `raw` bytes. Returns an error if the bytes do not represent
41    /// a valid key.
42    fn from_slice(raw: &[u8]) -> anyhow::Result<Self>;
43
44    /// Converts a signing key to a verification key.
45    fn to_verifying_key(&self) -> T::VerifyingKey;
46
47    /// Returns the key as raw bytes.
48    ///
49    /// Implementations should return `Cow::Borrowed` whenever possible (that is, if the bytes
50    /// are actually stored within the implementing data structure).
51    fn as_bytes(&self) -> SecretBytes<'_>;
52}
53
54/// Generic container for secret bytes, which can be either owned or borrowed.
55/// If owned, bytes are zeroized on drop.
56///
57/// Comparisons on `SecretBytes` are constant-time, but other operations (e.g., deserialization)
58/// may be var-time.
59///
60/// # Serialization
61///
62/// Represented in human-readable formats (JSON, TOML, YAML, etc.) as a base64-url encoded string
63/// with no padding. For other formats (e.g., CBOR), `SecretBytes` will be serialized directly
64/// as a byte sequence.
65#[derive(Clone)]
66pub struct SecretBytes<'a>(Cow<'a, [u8]>);
67
68impl<'a> SecretBytes<'a> {
69    pub(crate) fn new(inner: Cow<'a, [u8]>) -> Self {
70        Self(inner)
71    }
72
73    /// Creates secret bytes from a borrowed slice.
74    pub fn borrowed(bytes: &'a [u8]) -> Self {
75        Self(Cow::Borrowed(bytes))
76    }
77
78    /// Creates secret bytes from an owned `Vec`.
79    pub fn owned(bytes: Vec<u8>) -> Self {
80        Self(Cow::Owned(bytes))
81    }
82
83    #[cfg(feature = "rsa")]
84    pub(crate) fn owned_slice(bytes: alloc::boxed::Box<[u8]>) -> Self {
85        Self(Cow::Owned(bytes.into()))
86    }
87}
88
89impl fmt::Debug for SecretBytes<'_> {
90    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
91        formatter
92            .debug_struct("SecretBytes")
93            .field("len", &self.0.len())
94            .finish()
95    }
96}
97
98impl Drop for SecretBytes<'_> {
99    fn drop(&mut self) {
100        // if bytes are borrowed, we don't need to perform any special cleaning.
101        if let Cow::Owned(bytes) = &mut self.0 {
102            Zeroize::zeroize(bytes);
103        }
104    }
105}
106
107impl ops::Deref for SecretBytes<'_> {
108    type Target = [u8];
109
110    fn deref(&self) -> &Self::Target {
111        &self.0
112    }
113}
114
115impl AsRef<[u8]> for SecretBytes<'_> {
116    fn as_ref(&self) -> &[u8] {
117        self
118    }
119}
120
121impl PartialEq for SecretBytes<'_> {
122    fn eq(&self, other: &Self) -> bool {
123        subtle::ConstantTimeEq::ct_eq(self.as_ref(), other.as_ref()).into()
124    }
125}