use alloc::vec::Vec;
use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::CryptoError;
#[derive(Zeroize, ZeroizeOnDrop)]
pub struct SecretKey<const N: usize> {
bytes: [u8; N],
}
impl<const N: usize> SecretKey<N> {
#[must_use]
pub fn new(bytes: [u8; N]) -> Self {
Self { bytes }
}
#[must_use = "result must be checked"]
pub fn from_slice(slice: &[u8]) -> Result<Self, CryptoError> {
let bytes: [u8; N] = slice.try_into().map_err(|_| CryptoError::InvalidKey)?;
Ok(Self { bytes })
}
#[must_use]
pub fn as_bytes(&self) -> &[u8; N] {
&self.bytes
}
}
impl<const N: usize> core::fmt::Debug for SecretKey<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "SecretKey<{N}>(***)")
}
}
impl<const N: usize> Clone for SecretKey<N> {
fn clone(&self) -> Self {
Self { bytes: self.bytes }
}
}
#[derive(Zeroize, ZeroizeOnDrop)]
pub struct SecretVec {
bytes: Vec<u8>,
}
impl SecretVec {
#[must_use]
pub fn new(bytes: Vec<u8>) -> Self {
Self { bytes }
}
#[must_use]
pub fn from_slice(slice: &[u8]) -> Self {
Self {
bytes: slice.to_vec(),
}
}
#[must_use]
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
#[must_use]
pub fn len(&self) -> usize {
self.bytes.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.bytes.is_empty()
}
}
impl core::fmt::Debug for SecretVec {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "SecretVec(len={}, ***)", self.bytes.len())
}
}
impl Clone for SecretVec {
fn clone(&self) -> Self {
Self {
bytes: self.bytes.clone(),
}
}
}
pub struct KeyPair<SK: Zeroize, PK> {
secret: SK,
public: PK,
}
impl<SK: Zeroize, PK> KeyPair<SK, PK> {
#[must_use]
pub fn new(secret: SK, public: PK) -> Self {
Self { secret, public }
}
#[must_use]
pub fn secret(&self) -> &SK {
&self.secret
}
#[must_use]
pub fn public(&self) -> &PK {
&self.public
}
}
impl<SK: Zeroize, PK> Drop for KeyPair<SK, PK> {
fn drop(&mut self) {
self.secret.zeroize();
}
}
impl<SK: Zeroize + core::fmt::Debug, PK: core::fmt::Debug> core::fmt::Debug for KeyPair<SK, PK> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("KeyPair")
.field("secret", &"***")
.field("public", &self.public)
.finish()
}
}