use crate::{error::CryptError, log_activity, FileMetadata, FileState, FileTypes, Key, KeyTypes};
use pqcrypto_traits::kem::{Ciphertext, PublicKey, SecretKey, SharedSecret};
use std::{
marker::PhantomData,
path::{Path, PathBuf},
result::Result,
};
use zeroize::Zeroize;
pub trait KyberKeyFunctions {
fn keypair() -> Result<(Vec<u8>, Vec<u8>), CryptError>;
fn encap(public_key: &[u8]) -> Result<(Vec<u8>, Vec<u8>), CryptError>;
fn decap(secret_key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, CryptError>;
}
pub struct KeyControKyber1024;
impl KyberKeyFunctions for KeyControKyber1024 {
fn keypair() -> Result<(Vec<u8>, Vec<u8>), CryptError> {
use pqcrypto_kyber::kyber1024::*;
log_activity!(
"Generating a new keypair.\n\tThe used KEM: ",
format!("Kyber{}", 1024).as_str()
);
let (pk, sk) = keypair();
let public_key = pk.as_bytes().to_owned();
let secret_key = sk.as_bytes().to_owned();
log_activity!(
"A new keypair was created.\n\tThe used KEM: ",
format!("Kyber{}", 1024).as_str()
);
Ok((public_key, secret_key))
}
fn encap(public: &[u8]) -> Result<(Vec<u8>, Vec<u8>), CryptError> {
use pqcrypto_kyber::kyber1024::*;
log_activity!(
"Generating shared_secret and ciphertext.\n\tThe used KEM: ",
format!("Kyber{}", 1024).as_str()
);
let pk = PublicKey::from_bytes(public).unwrap();
let (ss, ct) = encapsulate(&pk);
let ciphertext = ct.as_bytes().to_vec();
let shared_secret = ss.as_bytes().to_vec();
log_activity!(
"Finished generating shared_secret and ciphertext.\n\tThe used KEM: ",
format!("Kyber{}", 1024).as_str()
);
Ok((shared_secret, ciphertext))
}
fn decap(sec: &[u8], cipher: &[u8]) -> Result<Vec<u8>, CryptError> {
use pqcrypto_kyber::kyber1024::*;
log_activity!("Starting decapsulation of shared_secret using secret_key and ciphertext.\n\tThe used KEM: ", format!("Kyber{}", 1024).as_str());
let ct = Ciphertext::from_bytes(cipher).unwrap();
let sk = SecretKey::from_bytes(sec).unwrap();
let ss2 = decapsulate(&ct, &sk);
let shared_secret = ss2.as_bytes().to_vec();
log_activity!(
"Decapsulated the shared_secret using secret_key and ciphertext.\n\tThe used KEM: ",
format!("Kyber{}", 1024).as_str()
);
Ok(shared_secret)
}
}
impl KeyControKyber1024 {
pub fn keypair() -> Result<(Vec<u8>, Vec<u8>), CryptError> {
<Self as KyberKeyFunctions>::keypair()
}
pub fn encap(public_key: &[u8]) -> Result<(Vec<u8>, Vec<u8>), CryptError> {
<Self as KyberKeyFunctions>::encap(public_key)
}
pub fn decap(secret_key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, CryptError> {
<Self as KyberKeyFunctions>::decap(secret_key, ciphertext)
}
}
pub struct KeyControKyber768;
impl KyberKeyFunctions for KeyControKyber768 {
fn keypair() -> Result<(Vec<u8>, Vec<u8>), CryptError> {
use pqcrypto_kyber::kyber768::*;
log_activity!(
"Generating a new keypair.\n\tThe used KEM: ",
format!("Kyber{}", 768).as_str()
);
let (pk, sk) = keypair();
let public_key = pk.as_bytes().to_vec();
let secret_key = sk.as_bytes().to_vec();
log_activity!(
"A new keypair was created.\n\tThe used KEM: ",
format!("Kyber{}", 768).as_str()
);
Ok((public_key, secret_key))
}
fn encap(public: &[u8]) -> Result<(Vec<u8>, Vec<u8>), CryptError> {
use pqcrypto_kyber::kyber768::*;
log_activity!(
"Generating shared_secret and ciphertext.\n\tThe used KEM: ",
format!("Kyber{}", 768).as_str()
);
let pk = PublicKey::from_bytes(public).unwrap();
let (ss, ct) = encapsulate(&pk);
let ciphertext = ct.as_bytes().to_vec();
let shared_secret = ss.as_bytes().to_vec();
log_activity!(
"Finished generating shared_secret and ciphertext.\n\tThe used KEM: ",
format!("Kyber{}", 768).as_str()
);
Ok((shared_secret, ciphertext))
}
fn decap(sec: &[u8], cipher: &[u8]) -> Result<Vec<u8>, CryptError> {
use pqcrypto_kyber::kyber768::*;
log_activity!("Starting decapsulation of shared_secret using secret_key and ciphertext.\n\tThe used KEM: ", format!("Kyber{}", 768).as_str());
let ct = Ciphertext::from_bytes(cipher).unwrap();
let sk = SecretKey::from_bytes(sec).unwrap();
let ss2 = decapsulate(&ct, &sk);
let shared_secret = ss2.as_bytes().to_vec();
log_activity!(
"Decapsulated the shared_secret using secret_key and ciphertext.\n\tThe used KEM: ",
format!("Kyber{}", 768).as_str()
);
Ok(shared_secret)
}
}
impl KeyControKyber768 {
pub fn keypair() -> Result<(Vec<u8>, Vec<u8>), CryptError> {
<Self as KyberKeyFunctions>::keypair()
}
pub fn encap(public_key: &[u8]) -> Result<(Vec<u8>, Vec<u8>), CryptError> {
<Self as KyberKeyFunctions>::encap(public_key)
}
pub fn decap(secret_key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, CryptError> {
<Self as KyberKeyFunctions>::decap(secret_key, ciphertext)
}
}
pub struct KeyControKyber512;
impl KyberKeyFunctions for KeyControKyber512 {
fn keypair() -> Result<(Vec<u8>, Vec<u8>), CryptError> {
use pqcrypto_kyber::kyber512::*;
log_activity!(
"Generating a new keypair.\n\tThe used KEM: ",
format!("Kyber{}", 512).as_str()
);
let (pk, sk) = keypair();
let public_key = pk.as_bytes().to_vec();
let secret_key = sk.as_bytes().to_vec();
log_activity!(
"A new keypair was created.\n\tThe used KEM: ",
format!("Kyber{}", 512).as_str()
);
Ok((public_key, secret_key))
}
fn encap(public: &[u8]) -> Result<(Vec<u8>, Vec<u8>), CryptError> {
use pqcrypto_kyber::kyber512::*;
log_activity!(
"Generating shared_secret and ciphertext.\n\tThe used KEM: ",
format!("Kyber{}", 512).as_str()
);
let pk = PublicKey::from_bytes(public).unwrap();
let (ss, ct) = encapsulate(&pk);
let ciphertext = ct.as_bytes().to_vec();
let shared_secret = ss.as_bytes().to_vec();
log_activity!(
"Finished generating shared_secret and ciphertext.\n\tThe used KEM: ",
format!("Kyber{}", 512).as_str()
);
Ok((shared_secret, ciphertext))
}
fn decap(sec: &[u8], cipher: &[u8]) -> Result<Vec<u8>, CryptError> {
use pqcrypto_kyber::kyber512::*;
log_activity!("Starting decapsulation of shared_secret using secret_key and ciphertext.\n\tThe used KEM: ", format!("Kyber{}", 512).as_str());
let ct = Ciphertext::from_bytes(cipher).unwrap();
let sk = SecretKey::from_bytes(sec).unwrap();
let ss2 = decapsulate(&ct, &sk);
let shared_secret = ss2.as_bytes().to_vec();
log_activity!(
"Decapsulated the shared_secret using secret_key and ciphertext.\n\tThe used KEM: ",
format!("Kyber{}", 512).as_str()
);
Ok(shared_secret)
}
}
impl KeyControKyber512 {
pub fn keypair() -> Result<(Vec<u8>, Vec<u8>), CryptError> {
<Self as KyberKeyFunctions>::keypair()
}
pub fn encap(public_key: &[u8]) -> Result<(Vec<u8>, Vec<u8>), CryptError> {
<Self as KyberKeyFunctions>::encap(public_key)
}
pub fn decap(secret_key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, CryptError> {
<Self as KyberKeyFunctions>::decap(secret_key, ciphertext)
}
}
pub struct KeyControl<T: KyberKeyFunctions> {
pub public_key: Vec<u8>,
pub secret_key: Vec<u8>,
pub ciphertext: Vec<u8>,
pub shared_secret: Vec<u8>,
_marker: std::marker::PhantomData<T>,
}
impl<T: KyberKeyFunctions> Drop for KeyControl<T> {
fn drop(&mut self) {
self.secret_key.zeroize();
self.shared_secret.zeroize();
}
}
impl<T: KyberKeyFunctions> KeyControl<T> {
pub fn new() -> Self {
KeyControl {
public_key: Vec::new(),
secret_key: Vec::new(),
ciphertext: Vec::new(),
shared_secret: Vec::new(),
_marker: PhantomData,
}
}
pub fn set_ciphertext(&mut self, cipher: Vec<u8>) -> Result<(), CryptError> {
self.ciphertext = cipher;
Ok(())
}
pub fn set_public_key(&mut self, public: Vec<u8>) -> Result<(), CryptError> {
self.public_key = public;
Ok(())
}
pub fn set_secret_key(&mut self, sec: Vec<u8>) -> Result<(), CryptError> {
self.secret_key = sec;
Ok(())
}
pub fn get_key(&self, key: KeyTypes) -> Result<Key, CryptError> {
let key = match key {
KeyTypes::None => unimplemented!(),
KeyTypes::PublicKey => Key::new(KeyTypes::PublicKey, self.public_key.to_vec()),
KeyTypes::SecretKey => Key::new(KeyTypes::SecretKey, self.secret_key.to_vec()),
KeyTypes::Ciphertext => Key::new(KeyTypes::Ciphertext, self.ciphertext.to_vec()),
KeyTypes::SharedSecret => Key::new(KeyTypes::SharedSecret, self.shared_secret.to_vec()),
};
Ok(key)
}
pub fn save(&self, key: KeyTypes, base_path: PathBuf) -> Result<(), CryptError> {
let key = match key {
KeyTypes::None => unimplemented!(),
KeyTypes::PublicKey => Key::new(KeyTypes::PublicKey, self.public_key.to_vec()),
KeyTypes::SecretKey => Key::new(KeyTypes::SecretKey, self.secret_key.to_vec()),
KeyTypes::Ciphertext => Key::new(KeyTypes::Ciphertext, self.ciphertext.to_vec()),
KeyTypes::SharedSecret => unimplemented!(),
};
key.save(base_path)
}
pub fn load(&self, key: KeyTypes, path: &Path) -> Result<Vec<u8>, CryptError> {
let key = match key {
KeyTypes::None => unimplemented!(),
KeyTypes::PublicKey => {
FileMetadata::from(PathBuf::from(path), FileTypes::PublicKey, FileState::Other)
}
KeyTypes::SecretKey => {
FileMetadata::from(PathBuf::from(path), FileTypes::SecretKey, FileState::Other)
}
KeyTypes::Ciphertext => {
FileMetadata::from(PathBuf::from(path), FileTypes::Ciphertext, FileState::Other)
}
KeyTypes::SharedSecret => unimplemented!(),
};
Ok(key.load().unwrap())
}
pub fn public_key(&self) -> Result<Vec<u8>, CryptError> {
let key = &self.public_key;
Ok(key.to_vec())
}
pub fn secret_key(&self) -> Result<Vec<u8>, CryptError> {
let key = &self.secret_key;
Ok(key.to_vec())
}
pub fn ciphertext(&self) -> Result<Vec<u8>, CryptError> {
let key = &self.ciphertext;
Ok(key.to_vec())
}
pub fn shared_secret(&self) -> Result<Vec<u8>, CryptError> {
let key = &self.shared_secret;
Ok(key.to_vec())
}
pub fn encap(&self, public: &[u8]) -> Result<(Vec<u8>, Vec<u8>), CryptError> {
T::encap(public)
}
pub fn decap(&self, secret_key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, CryptError> {
T::decap(secret_key, ciphertext)
}
}
impl<T: KyberKeyFunctions> Default for KeyControl<T> {
fn default() -> Self {
Self::new()
}
}