use std::marker::PhantomData;
use zeroize::Zeroize;
use crate::{
api::AuthenticatedAead,
core::hub::{DecryptData, Kyber, KyberSizeVariant, MlKem1024},
error::CryptError,
markers::{Data, Decryption, XChaCha20Poly1305},
protocol::Envelope,
};
pub struct MissingSecretKey;
pub struct WithSecretKey;
pub struct Decryptor<K = MlKem1024, A = XChaCha20Poly1305>(PhantomData<(K, A)>)
where
K: KyberSizeVariant,
A: AuthenticatedAead;
impl<K, A> Decryptor<K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
{
#[allow(clippy::new_ret_no_self)]
pub fn new() -> DecryptorBuilder<MissingSecretKey, K, A> {
DecryptorBuilder::new()
}
}
pub struct DecryptorBuilder<S, K = MlKem1024, A = XChaCha20Poly1305>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
{
secret_key: Option<Vec<u8>>,
_state: PhantomData<(S, K, A)>,
}
struct DecryptSession<K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
{
kyber: Kyber<Decryption, K, Data, A>,
}
impl<K, A> DecryptSession<K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
Kyber<Decryption, K, Data, A>: DecryptData,
{
fn open(&self, envelope: &Envelope) -> Result<Vec<u8>, CryptError> {
self.kyber.decrypt_data(&envelope.ciphertext, "", envelope)
}
}
impl<K, A> Drop for DecryptSession<K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
{
fn drop(&mut self) {
self.kyber.zeroize_key();
}
}
impl<S, K, A> Drop for DecryptorBuilder<S, K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
{
fn drop(&mut self) {
if let Some(secret_key) = self.secret_key.as_mut() {
secret_key.zeroize();
}
}
}
impl<K, A> DecryptorBuilder<MissingSecretKey, K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
{
pub fn new() -> Self {
Self {
secret_key: None,
_state: PhantomData,
}
}
pub fn secret_key(self, secret_key: Vec<u8>) -> DecryptorBuilder<WithSecretKey, K, A> {
DecryptorBuilder {
secret_key: Some(secret_key),
_state: PhantomData,
}
}
}
impl<K, A> DecryptorBuilder<WithSecretKey, K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
Kyber<Decryption, K, Data, A>: DecryptData,
{
pub fn open(mut self, envelope: &Envelope) -> Result<Vec<u8>, CryptError> {
let secret_key = self.secret_key.take().ok_or(CryptError::MissingSecretKey)?;
let session = DecryptSession {
kyber: Kyber::<Decryption, K, Data, A>::new(secret_key, None)?,
};
session.open(envelope)
}
}
impl<K, A> Default for DecryptorBuilder<MissingSecretKey, K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
{
fn default() -> Self {
Self::new()
}
}