jwt_compact_frame/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) const fn new(inner: Cow<'a, [u8]>) -> Self {
72 Self(inner)
73 }
74
75 /// Creates secret bytes from a borrowed slice.
76 pub const 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.debug_struct("SecretBytes").field("len", &self.0.len()).finish()
89 }
90}
91
92impl Drop for SecretBytes<'_> {
93 fn drop(&mut self) {
94 // if bytes are borrowed, we don't need to perform any special cleaning.
95 if let Cow::Owned(bytes) = &mut self.0 {
96 Zeroize::zeroize(bytes);
97 }
98 }
99}
100
101impl ops::Deref for SecretBytes<'_> {
102 type Target = [u8];
103
104 fn deref(&self) -> &Self::Target {
105 &self.0
106 }
107}
108
109impl AsRef<[u8]> for SecretBytes<'_> {
110 fn as_ref(&self) -> &[u8] {
111 self
112 }
113}
114
115impl PartialEq for SecretBytes<'_> {
116 fn eq(&self, other: &Self) -> bool {
117 subtle::ConstantTimeEq::ct_eq(self.as_ref(), other.as_ref()).into()
118 }
119}