Skip to main content

jwt_compact/alg/
generic.rs

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