use ml_kem::kem::{Decapsulate, Encapsulate};
use x_wing::{DecapsulationKey, EncapsulationKey};
use super::symmetric;
pub struct SecretKey {
pub key: x_wing::DecapsulationKey,
}
impl SecretKey {
pub fn decode(key: Vec<u8>) -> Option<SecretKey> {
let key_slice: [u8; x_wing::DECAPSULATION_KEY_SIZE] = key.as_slice().try_into().ok()?;
return Some(SecretKey {
key: DecapsulationKey::from(key_slice),
});
}
pub fn encode(&self) -> Vec<u8> {
self.key.as_bytes().to_vec()
}
}
pub struct PublicKey {
pub key: EncapsulationKey,
}
impl PublicKey {
pub fn decode(key: Vec<u8>) -> Option<PublicKey> {
let key_slice: [u8; x_wing::ENCAPSULATION_KEY_SIZE] = key.as_slice().try_into().ok()?;
return Some(PublicKey {
key: EncapsulationKey::from(&key_slice),
});
}
pub fn encode(&self) -> Vec<u8> {
self.key.as_bytes().to_vec()
}
}
pub struct AsymmetricKeyPair {
pub public_key: PublicKey,
pub secret_key: SecretKey,
}
impl AsymmetricKeyPair {
pub fn generate() -> AsymmetricKeyPair {
let rng = &mut rand::rngs::OsRng;
let (priv_key, pub_key) = x_wing::generate_key_pair(rng);
AsymmetricKeyPair {
public_key: PublicKey { key: pub_key },
secret_key: SecretKey { key: priv_key },
}
}
}
pub fn encrypt(key: &PublicKey, message: &Vec<u8>) -> Option<Vec<u8>> {
let rng = &mut rand::rngs::OsRng;
let (ciphertext, shared_secret) = key.key.encapsulate(rng).ok()?;
let mut encrypted = symmetric::encrypt(&shared_secret, message)?;
encrypted.extend(ciphertext.as_bytes());
return Some(encrypted);
}
pub fn decrypt(priv_key: &SecretKey, ciphertext: &Vec<u8>) -> Option<Vec<u8>> {
if ciphertext.len() <= x_wing::CIPHERTEXT_SIZE {
return None;
}
let (encrypted_msg, x_ss_enc) = ciphertext.split_at(ciphertext.len() - x_wing::CIPHERTEXT_SIZE);
let x_ss_enc: [u8; x_wing::CIPHERTEXT_SIZE] = x_ss_enc.try_into().ok()?;
let x_ciph = x_wing::Ciphertext::from(&x_ss_enc);
let shared_secret = priv_key.key.decapsulate(&x_ciph).ok()?;
return Some(symmetric::decrypt(&shared_secret, &encrypted_msg.to_vec())?);
}