use anyhow::Error;
use hex_buffer_serde::{Hex as _, HexForm};
use serde::{Deserialize, Serialize};
use core::{fmt, marker::PhantomData};
use crate::alloc::{Box, Vec};
pub trait DeriveKey: 'static {
fn salt_len(&self) -> usize;
fn derive_key(&self, buf: &mut [u8], password: &[u8], salt: &[u8]) -> Result<(), Error>;
}
impl DeriveKey for Box<dyn DeriveKey> {
fn salt_len(&self) -> usize {
(**self).salt_len()
}
fn derive_key(&self, buf: &mut [u8], password: &[u8], salt: &[u8]) -> Result<(), Error> {
(**self).derive_key(buf, password, salt)
}
}
#[derive(Debug, Clone, Default)]
pub struct MacMismatch;
impl fmt::Display for MacMismatch {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("MAC mismatch")
}
}
#[cfg(feature = "std")]
impl std::error::Error for MacMismatch {}
pub trait Cipher: 'static {
const KEY_LEN: usize;
const NONCE_LEN: usize;
const MAC_LEN: usize;
fn seal(message: &[u8], nonce: &[u8], key: &[u8]) -> CipherOutput;
fn open(
output: &mut [u8],
encrypted: &CipherOutput,
nonce: &[u8],
key: &[u8],
) -> Result<(), MacMismatch>;
}
#[derive(Debug)]
pub(crate) struct CipherObject<T>(PhantomData<T>);
impl<T> Default for CipherObject<T> {
fn default() -> Self {
CipherObject(PhantomData)
}
}
pub(crate) trait ObjectSafeCipher: 'static {
fn key_len(&self) -> usize;
fn nonce_len(&self) -> usize;
fn mac_len(&self) -> usize;
fn seal(&self, message: &[u8], nonce: &[u8], key: &[u8]) -> CipherOutput;
fn open(
&self,
output: &mut [u8],
encrypted: &CipherOutput,
nonce: &[u8],
key: &[u8],
) -> Result<(), MacMismatch>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CipherOutput {
#[serde(with = "HexForm")]
pub ciphertext: Vec<u8>,
#[serde(with = "HexForm")]
pub mac: Vec<u8>,
}
impl<T: Cipher> ObjectSafeCipher for CipherObject<T> {
fn key_len(&self) -> usize {
T::KEY_LEN
}
fn nonce_len(&self) -> usize {
T::NONCE_LEN
}
fn mac_len(&self) -> usize {
T::MAC_LEN
}
fn seal(&self, message: &[u8], nonce: &[u8], key: &[u8]) -> CipherOutput {
T::seal(message, nonce, key)
}
fn open(
&self,
output: &mut [u8],
encrypted: &CipherOutput,
nonce: &[u8],
key: &[u8],
) -> Result<(), MacMismatch> {
T::open(output, encrypted, nonce, key)
}
}
impl ObjectSafeCipher for Box<dyn ObjectSafeCipher> {
fn key_len(&self) -> usize {
(**self).key_len()
}
fn nonce_len(&self) -> usize {
(**self).nonce_len()
}
fn mac_len(&self) -> usize {
(**self).mac_len()
}
fn seal(&self, message: &[u8], nonce: &[u8], key: &[u8]) -> CipherOutput {
(**self).seal(message, nonce, key)
}
fn open(
&self,
output: &mut [u8],
encrypted: &CipherOutput,
nonce: &[u8],
key: &[u8],
) -> Result<(), MacMismatch> {
(**self).open(output, encrypted, nonce, key)
}
}