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