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}