use zeroize::Zeroize;
use core::{fmt, ops};
use crate::{
alloc::{Cow, Vec},
Algorithm,
};
pub trait VerifyingKey<T>: Sized
where
T: Algorithm<VerifyingKey = Self>,
{
fn from_slice(raw: &[u8]) -> anyhow::Result<Self>;
fn as_bytes(&self) -> Cow<'_, [u8]>;
}
pub trait SigningKey<T>: Sized
where
T: Algorithm<SigningKey = Self>,
{
fn from_slice(raw: &[u8]) -> anyhow::Result<Self>;
fn to_verifying_key(&self) -> T::VerifyingKey;
fn as_bytes(&self) -> SecretBytes<'_>;
}
#[derive(Clone)]
pub struct SecretBytes<'a>(Cow<'a, [u8]>);
impl<'a> SecretBytes<'a> {
pub(crate) fn new(inner: Cow<'a, [u8]>) -> Self {
Self(inner)
}
pub fn borrowed(bytes: &'a [u8]) -> Self {
Self(Cow::Borrowed(bytes))
}
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 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()
}
}