pub mod cipher_impls;
pub mod macros;
use crate::error::CryptError;
use crate::protocol::Envelope;
use std::{marker::PhantomData, path::PathBuf};
pub use crate::markers::{
AesCtr, AesGcmSiv, AesXts, Data, Decryption, Encryption, Files, Message, XChaCha20,
XChaCha20Poly1305, AES,
};
pub trait KyberFunctions {
fn encrypt_file(
&mut self,
path: PathBuf,
passphrase: &str,
) -> Result<(Vec<u8>, Vec<u8>), CryptError>;
fn encrypt_msg(
&mut self,
message: &str,
passphrase: &str,
) -> Result<(Vec<u8>, Vec<u8>), CryptError>;
fn encrypt_data(
&mut self,
data: Vec<u8>,
passphrase: &str,
) -> Result<(Vec<u8>, Vec<u8>), CryptError>;
fn decrypt_file(
&self,
path: PathBuf,
passphrase: &str,
ciphertext: Vec<u8>,
) -> Result<Vec<u8>, CryptError>;
fn decrypt_msg(
&self,
message: Vec<u8>,
passphrase: &str,
ciphertext: Vec<u8>,
) -> Result<Vec<u8>, CryptError>;
fn decrypt_data(
&self,
data: Vec<u8>,
passphrase: &str,
ciphertext: Vec<u8>,
) -> Result<Vec<u8>, CryptError>;
}
pub trait EncryptData {
fn encrypt_data(&mut self, data: &[u8], passphrase: &str) -> Result<Envelope, CryptError>;
}
pub trait EncryptText {
fn encrypt_msg(&mut self, message: &str, passphrase: &str) -> Result<Envelope, CryptError>;
}
pub trait EncryptFile {
fn encrypt_file(&mut self, path: PathBuf, passphrase: &str) -> Result<Envelope, CryptError>;
}
pub trait DecryptData {
fn decrypt_data(
&self,
data: &[u8],
passphrase: &str,
envelope: &Envelope,
) -> Result<Vec<u8>, CryptError>;
}
pub trait DecryptText {
fn decrypt_msg(
&self,
message: &[u8],
passphrase: &str,
envelope: &Envelope,
) -> Result<Vec<u8>, CryptError>;
}
pub trait DecryptFile {
fn decrypt_file(
&self,
path: PathBuf,
passphrase: &str,
envelope: &Envelope,
) -> Result<Vec<u8>, CryptError>;
}
pub enum KyberVariant {
Kyber512,
Kyber768,
Kyber1024,
}
pub trait KyberSizeVariant {
fn variant() -> KyberVariant;
fn kem_id() -> crate::kem::backend::KemId;
}
#[deprecated(note = "Use MlKem512 (FIPS 203)")]
pub struct Kyber512;
#[deprecated(note = "Use MlKem768 (FIPS 203)")]
pub struct Kyber768;
#[deprecated(note = "Use MlKem1024 (FIPS 203)")]
pub struct Kyber1024;
#[allow(deprecated)]
impl KyberSizeVariant for Kyber512 {
fn variant() -> KyberVariant {
KyberVariant::Kyber512
}
fn kem_id() -> crate::kem::backend::KemId {
crate::kem::backend::KemId::MlKem512
}
}
#[allow(deprecated)]
impl KyberSizeVariant for Kyber768 {
fn variant() -> KyberVariant {
KyberVariant::Kyber768
}
fn kem_id() -> crate::kem::backend::KemId {
crate::kem::backend::KemId::MlKem768
}
}
#[allow(deprecated)]
impl KyberSizeVariant for Kyber1024 {
fn variant() -> KyberVariant {
KyberVariant::Kyber1024
}
fn kem_id() -> crate::kem::backend::KemId {
crate::kem::backend::KemId::MlKem1024
}
}
pub struct MlKem512;
pub struct MlKem768;
pub struct MlKem1024;
impl KyberSizeVariant for MlKem512 {
fn variant() -> KyberVariant {
KyberVariant::Kyber512
}
fn kem_id() -> crate::kem::backend::KemId {
crate::kem::backend::KemId::MlKem512
}
}
impl KyberSizeVariant for MlKem768 {
fn variant() -> KyberVariant {
KyberVariant::Kyber768
}
fn kem_id() -> crate::kem::backend::KemId {
crate::kem::backend::KemId::MlKem768
}
}
impl KyberSizeVariant for MlKem1024 {
fn variant() -> KyberVariant {
KyberVariant::Kyber1024
}
fn kem_id() -> crate::kem::backend::KemId {
crate::kem::backend::KemId::MlKem1024
}
}
#[derive(PartialEq, Debug, Clone)]
pub struct KyberData {
key: Vec<u8>,
nonce: String,
}
impl KyberData {
pub fn key(&self) -> Result<Vec<u8>, CryptError> {
Ok(self.key.to_vec())
}
pub fn nonce(&self) -> Result<&str, CryptError> {
Ok(&self.nonce)
}
pub fn set_nonce(&mut self, nonce: String) -> Result<(), CryptError> {
self.nonce = nonce;
Ok(())
}
pub fn set_key(&mut self, key: Vec<u8>) -> Result<(), CryptError> {
self.key = key;
Ok(())
}
}
pub struct Kyber<
ProcessStatus = Encryption,
KyberSize = MlKem1024,
ContentStatus = Files,
AlgorithmParam = AES,
> where
KyberSize: KyberSizeVariant,
{
pub(crate) kyber_data: KyberData,
hmac_size: usize,
content_state: PhantomData<ContentStatus>,
kyber_state: PhantomData<KyberSize>,
algorithm_state: PhantomData<AlgorithmParam>,
process_state: PhantomData<ProcessStatus>,
}
impl<ProcessStatus, KyberSize: KyberSizeVariant, ContentStatus, AlgorithmParam>
Kyber<ProcessStatus, KyberSize, ContentStatus, AlgorithmParam>
{
pub fn new(key: Vec<u8>, nonce: Option<String>) -> Result<Self, CryptError> {
let nonce = nonce.unwrap_or_default();
Ok(Self {
kyber_data: KyberData { key, nonce },
hmac_size: 512,
content_state: PhantomData,
kyber_state: PhantomData,
algorithm_state: PhantomData,
process_state: PhantomData,
})
}
pub fn get_key(&self) -> Result<Vec<u8>, CryptError> {
self.kyber_data.key()
}
pub fn get_nonce(&self) -> Result<&str, CryptError> {
self.kyber_data.nonce()
}
pub fn hmac_sha256(&mut self) -> Result<(), CryptError> {
self.hmac_size = 256;
Ok(())
}
}
macro_rules! impl_size_switch {
($from:ty => $to:ty, $method:ident, $to_phantom:ty) => {
#[allow(deprecated)]
impl<ProcessStatus, ContentStatus, AlgorithmParam>
Kyber<ProcessStatus, $from, ContentStatus, AlgorithmParam>
{
pub fn $method(self) -> Kyber<ProcessStatus, $to, ContentStatus, AlgorithmParam> {
Kyber {
kyber_data: self.kyber_data,
hmac_size: self.hmac_size,
content_state: PhantomData,
kyber_state: PhantomData::<$to_phantom>,
algorithm_state: PhantomData,
process_state: PhantomData,
}
}
}
};
}
impl_size_switch!(Kyber1024 => Kyber768, kyber768, Kyber768);
impl_size_switch!(Kyber1024 => Kyber512, kyber512, Kyber512);
impl_size_switch!(Kyber768 => Kyber1024, kyber1024, Kyber1024);
impl_size_switch!(Kyber768 => Kyber512, kyber512, Kyber512);
impl_size_switch!(Kyber512 => Kyber1024, kyber1024, Kyber1024);
impl_size_switch!(Kyber512 => Kyber768, kyber768, Kyber768);
impl_size_switch!(MlKem1024 => MlKem768, ml_kem768, MlKem768);
impl_size_switch!(MlKem1024 => MlKem512, ml_kem512, MlKem512);
impl_size_switch!(MlKem768 => MlKem1024, ml_kem1024, MlKem1024);
impl_size_switch!(MlKem768 => MlKem512, ml_kem512, MlKem512);
impl_size_switch!(MlKem512 => MlKem1024, ml_kem1024, MlKem1024);
impl_size_switch!(MlKem512 => MlKem768, ml_kem768, MlKem768);
macro_rules! impl_alg_switch {
($from:ty, $to:ty, $method:ident) => {
impl<ProcessStatus, KyberSize: KyberSizeVariant, ContentStatus>
Kyber<ProcessStatus, KyberSize, ContentStatus, $from>
{
pub fn $method(self) -> Kyber<ProcessStatus, KyberSize, ContentStatus, $to> {
Kyber {
kyber_data: self.kyber_data,
hmac_size: self.hmac_size,
content_state: PhantomData,
kyber_state: PhantomData,
algorithm_state: PhantomData,
process_state: PhantomData,
}
}
}
};
}
impl_alg_switch!(AES, XChaCha20, xchacha20);
impl_alg_switch!(AES, AesGcmSiv, aes_gcm_siv);
impl_alg_switch!(AES, AesCtr, aes_ctr);
impl_alg_switch!(AES, AesXts, aes_xts);
impl_alg_switch!(AES, XChaCha20Poly1305, xchacha20poly1305);
impl_alg_switch!(XChaCha20, AES, aes);
impl_alg_switch!(XChaCha20, AesGcmSiv, aes_gcm_siv);
impl_alg_switch!(XChaCha20, AesCtr, aes_ctr);
impl_alg_switch!(XChaCha20, AesXts, aes_xts);
impl_alg_switch!(XChaCha20, XChaCha20Poly1305, xchacha20poly1305);
impl_alg_switch!(XChaCha20Poly1305, AES, aes);
impl_alg_switch!(XChaCha20Poly1305, AesGcmSiv, aes_gcm_siv);
impl_alg_switch!(XChaCha20Poly1305, AesCtr, aes_ctr);
impl_alg_switch!(XChaCha20Poly1305, AesXts, aes_xts);
impl_alg_switch!(XChaCha20Poly1305, XChaCha20, xchacha20);
impl_alg_switch!(AesGcmSiv, AES, aes);
impl_alg_switch!(AesGcmSiv, XChaCha20, xchacha20);
impl_alg_switch!(AesGcmSiv, XChaCha20Poly1305, xchacha20poly1305);
impl_alg_switch!(AesGcmSiv, AesCtr, aes_ctr);
impl_alg_switch!(AesGcmSiv, AesXts, aes_xts);
impl_alg_switch!(AesCtr, AES, aes);
impl_alg_switch!(AesCtr, XChaCha20, xchacha20);
impl_alg_switch!(AesCtr, AesGcmSiv, aes_gcm_siv);
impl_alg_switch!(AesCtr, AesXts, aes_xts);
impl_alg_switch!(AesCtr, XChaCha20Poly1305, xchacha20poly1305);
impl_alg_switch!(AesXts, AES, aes);
impl_alg_switch!(AesXts, XChaCha20, xchacha20);
impl_alg_switch!(AesXts, XChaCha20Poly1305, xchacha20poly1305);
impl_alg_switch!(AesXts, AesGcmSiv, aes_gcm_siv);
impl_alg_switch!(AesXts, AesCtr, aes_ctr);
impl<ProcessStatus, KyberSize: KyberSizeVariant, AlgorithmParam>
Kyber<ProcessStatus, KyberSize, Files, AlgorithmParam>
{
pub fn message(self) -> Kyber<ProcessStatus, KyberSize, Message, AlgorithmParam> {
Kyber {
kyber_data: self.kyber_data,
hmac_size: self.hmac_size,
content_state: PhantomData,
kyber_state: PhantomData,
algorithm_state: PhantomData,
process_state: PhantomData,
}
}
pub fn data(self) -> Kyber<ProcessStatus, KyberSize, Data, AlgorithmParam> {
Kyber {
kyber_data: self.kyber_data,
hmac_size: self.hmac_size,
content_state: PhantomData,
kyber_state: PhantomData,
algorithm_state: PhantomData,
process_state: PhantomData,
}
}
pub fn is_file(self) -> bool {
true
}
pub fn is_message(self) -> bool {
false
}
pub fn is_data(self) -> bool {
false
}
}
impl<ProcessStatus, KyberSize: KyberSizeVariant, AlgorithmParam>
Kyber<ProcessStatus, KyberSize, Message, AlgorithmParam>
{
pub fn file(self) -> Kyber<ProcessStatus, KyberSize, Files, AlgorithmParam> {
Kyber {
kyber_data: self.kyber_data,
hmac_size: self.hmac_size,
content_state: PhantomData,
kyber_state: PhantomData,
algorithm_state: PhantomData,
process_state: PhantomData,
}
}
pub fn data(self) -> Kyber<ProcessStatus, KyberSize, Data, AlgorithmParam> {
Kyber {
kyber_data: self.kyber_data,
hmac_size: self.hmac_size,
content_state: PhantomData,
kyber_state: PhantomData,
algorithm_state: PhantomData,
process_state: PhantomData,
}
}
pub fn is_file(self) -> bool {
false
}
pub fn is_message(self) -> bool {
true
}
pub fn is_data(self) -> bool {
false
}
}
impl<ProcessStatus, KyberSize: KyberSizeVariant, AlgorithmParam>
Kyber<ProcessStatus, KyberSize, Data, AlgorithmParam>
{
pub fn file(self) -> Kyber<ProcessStatus, KyberSize, Files, AlgorithmParam> {
Kyber {
kyber_data: self.kyber_data,
hmac_size: self.hmac_size,
content_state: PhantomData,
kyber_state: PhantomData,
algorithm_state: PhantomData,
process_state: PhantomData,
}
}
pub fn message(self) -> Kyber<ProcessStatus, KyberSize, Message, AlgorithmParam> {
Kyber {
kyber_data: self.kyber_data,
hmac_size: self.hmac_size,
content_state: PhantomData,
kyber_state: PhantomData,
algorithm_state: PhantomData,
process_state: PhantomData,
}
}
pub fn is_file(self) -> bool {
false
}
pub fn is_message(self) -> bool {
false
}
pub fn is_data(self) -> bool {
true
}
}
impl<KyberSize: KyberSizeVariant, ContentStatus, AlgorithmParam>
Kyber<Encryption, KyberSize, ContentStatus, AlgorithmParam>
{
pub fn decryption(self) -> Kyber<Decryption, KyberSize, Message, AlgorithmParam> {
Kyber {
kyber_data: self.kyber_data,
hmac_size: self.hmac_size,
content_state: PhantomData,
kyber_state: PhantomData,
algorithm_state: PhantomData,
process_state: PhantomData,
}
}
}
impl<KyberSize: KyberSizeVariant, ContentStatus, AlgorithmParam>
Kyber<Decryption, KyberSize, ContentStatus, AlgorithmParam>
{
pub fn encryption(self) -> Kyber<Encryption, KyberSize, Files, AlgorithmParam> {
Kyber {
kyber_data: self.kyber_data,
hmac_size: self.hmac_size,
content_state: PhantomData,
kyber_state: PhantomData,
algorithm_state: PhantomData,
process_state: PhantomData,
}
}
}