use std::marker::PhantomData;
use zeroize::{Zeroize, Zeroizing};
use crate::{
api::AuthenticatedAead,
core::hub::{EncryptData, Kyber, KyberSizeVariant, MlKem1024},
error::CryptError,
markers::{Data, Encryption, XChaCha20Poly1305},
protocol::Envelope,
};
pub struct MissingRecipient;
pub struct WithRecipient;
pub struct MissingPlaintext;
pub struct WithPlaintext;
pub struct Encryptor<K = MlKem1024, A = XChaCha20Poly1305>(PhantomData<(K, A)>)
where
K: KyberSizeVariant,
A: AuthenticatedAead;
impl<K, A> Encryptor<K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
{
#[allow(clippy::new_ret_no_self)]
pub fn new() -> EncryptorBuilder<MissingRecipient, MissingPlaintext, K, A> {
EncryptorBuilder::new()
}
}
pub struct EncryptorBuilder<R, P, K = MlKem1024, A = XChaCha20Poly1305>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
{
recipient: Option<Vec<u8>>,
plaintext: Option<Vec<u8>>,
_state: PhantomData<(R, P, K, A)>,
}
impl<R, P, K, A> Drop for EncryptorBuilder<R, P, K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
{
fn drop(&mut self) {
if let Some(plaintext) = self.plaintext.as_mut() {
plaintext.zeroize();
}
}
}
impl<K, A> EncryptorBuilder<MissingRecipient, MissingPlaintext, K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
{
pub fn new() -> Self {
Self {
recipient: None,
plaintext: None,
_state: PhantomData,
}
}
}
impl<P, K, A> EncryptorBuilder<MissingRecipient, P, K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
{
pub fn recipient(mut self, recipient: Vec<u8>) -> EncryptorBuilder<WithRecipient, P, K, A> {
EncryptorBuilder {
recipient: Some(recipient),
plaintext: self.plaintext.take(),
_state: PhantomData,
}
}
}
impl<K, A> EncryptorBuilder<WithRecipient, MissingPlaintext, K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
Kyber<Encryption, K, Data, A>: EncryptData,
{
pub fn plaintext<T: Into<Vec<u8>>>(
mut self,
plaintext: T,
) -> EncryptorBuilder<WithRecipient, WithPlaintext, K, A> {
EncryptorBuilder {
recipient: self.recipient.take(),
plaintext: Some(plaintext.into()),
_state: PhantomData,
}
}
pub fn seal_bytes<T: Into<Vec<u8>>>(self, plaintext: T) -> Result<Envelope, CryptError> {
self.plaintext(plaintext).seal()
}
}
impl<K, A> EncryptorBuilder<WithRecipient, WithPlaintext, K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
Kyber<Encryption, K, Data, A>: EncryptData,
{
pub fn seal(mut self) -> Result<Envelope, CryptError> {
let recipient = self.recipient.take().ok_or(CryptError::MissingPublicKey)?;
let plaintext = Zeroizing::new(self.plaintext.take().ok_or(CryptError::MissingData)?);
let mut kyber = Kyber::<Encryption, K, Data, A>::new(recipient, None)?;
kyber.encrypt_data(&plaintext, "")
}
}
impl<K, A> Default for EncryptorBuilder<MissingRecipient, MissingPlaintext, K, A>
where
K: KyberSizeVariant,
A: AuthenticatedAead,
{
fn default() -> Self {
Self::new()
}
}