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}