jwt_compact/alg/generic.rs
1//! Generic traits providing uniform interfaces for a certain cryptosystem
2//! across different backends.
3
4use core::{fmt, ops};
5
6use zeroize::Zeroize;
7
8use crate::{
9 Algorithm,
10 alloc::{Cow, Vec},
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 #[cfg(feature = "rsa")]
86 pub(crate) fn owned_slice(bytes: crate::alloc::Box<[u8]>) -> Self {
87 Self(Cow::Owned(bytes.into()))
88 }
89}
90
91impl fmt::Debug for SecretBytes<'_> {
92 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
93 formatter
94 .debug_struct("SecretBytes")
95 .field("len", &self.0.len())
96 .finish()
97 }
98}
99
100impl Drop for SecretBytes<'_> {
101 fn drop(&mut self) {
102 // if bytes are borrowed, we don't need to perform any special cleaning.
103 if let Cow::Owned(bytes) = &mut self.0 {
104 Zeroize::zeroize(bytes);
105 }
106 }
107}
108
109impl ops::Deref for SecretBytes<'_> {
110 type Target = [u8];
111
112 fn deref(&self) -> &Self::Target {
113 &self.0
114 }
115}
116
117impl AsRef<[u8]> for SecretBytes<'_> {
118 fn as_ref(&self) -> &[u8] {
119 self
120 }
121}
122
123impl PartialEq for SecretBytes<'_> {
124 fn eq(&self, other: &Self) -> bool {
125 subtle::ConstantTimeEq::ct_eq(self.as_ref(), other.as_ref()).into()
126 }
127}