use pqcrypto_kyber::kyber1024;
use pqcrypto_traits::kem::{PublicKey, SecretKey, Ciphertext, SharedSecret};
use zeroize::Zeroize;
use crate::{CryptoError, Result};
#[derive(Clone)]
pub struct KyberPublicKey(kyber1024::PublicKey);
impl KyberPublicKey {
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
if bytes.len() != kyber1024::public_key_bytes() {
return Err(CryptoError::InvalidKeyLength {
expected: kyber1024::public_key_bytes(),
actual: bytes.len(),
});
}
let key = kyber1024::PublicKey::from_bytes(bytes)
.map_err(|_| CryptoError::InvalidKeyLength {
expected: kyber1024::public_key_bytes(),
actual: bytes.len(),
})?;
Ok(Self(key))
}
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn size() -> usize {
kyber1024::public_key_bytes()
}
}
pub struct KyberSecretKey(kyber1024::SecretKey);
impl KyberSecretKey {
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
if bytes.len() != kyber1024::secret_key_bytes() {
return Err(CryptoError::InvalidKeyLength {
expected: kyber1024::secret_key_bytes(),
actual: bytes.len(),
});
}
let key = kyber1024::SecretKey::from_bytes(bytes)
.map_err(|_| CryptoError::InvalidKeyLength {
expected: kyber1024::secret_key_bytes(),
actual: bytes.len(),
})?;
Ok(Self(key))
}
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn size() -> usize {
kyber1024::secret_key_bytes()
}
}
impl Drop for KyberSecretKey {
fn drop(&mut self) {
}
}
pub struct KyberKeyPair {
pub public_key: KyberPublicKey,
pub secret_key: KyberSecretKey,
}
#[derive(Clone, Zeroize)]
#[zeroize(drop)]
pub struct KyberSharedSecret([u8; 32]);
impl KyberSharedSecret {
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn size() -> usize {
kyber1024::shared_secret_bytes()
}
}
pub struct KyberCiphertext(kyber1024::Ciphertext);
impl KyberCiphertext {
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
if bytes.len() != kyber1024::ciphertext_bytes() {
return Err(CryptoError::InvalidKeyLength {
expected: kyber1024::ciphertext_bytes(),
actual: bytes.len(),
});
}
let ct = kyber1024::Ciphertext::from_bytes(bytes)
.map_err(|_| CryptoError::InvalidKeyLength {
expected: kyber1024::ciphertext_bytes(),
actual: bytes.len(),
})?;
Ok(Self(ct))
}
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn size() -> usize {
kyber1024::ciphertext_bytes()
}
}
pub struct KyberCrypto;
impl KyberCrypto {
pub fn generate_keypair() -> KyberKeyPair {
let (pk, sk) = kyber1024::keypair();
KyberKeyPair {
public_key: KyberPublicKey(pk),
secret_key: KyberSecretKey(sk),
}
}
pub fn encapsulate(public_key: &KyberPublicKey) -> (KyberSharedSecret, KyberCiphertext) {
let (ss, ct) = kyber1024::encapsulate(&public_key.0);
let mut shared_secret = [0u8; 32];
shared_secret.copy_from_slice(ss.as_bytes());
(KyberSharedSecret(shared_secret), KyberCiphertext(ct))
}
pub fn decapsulate(
ciphertext: &KyberCiphertext,
secret_key: &KyberSecretKey,
) -> KyberSharedSecret {
let ss = kyber1024::decapsulate(&ciphertext.0, &secret_key.0);
let mut shared_secret = [0u8; 32];
shared_secret.copy_from_slice(ss.as_bytes());
KyberSharedSecret(shared_secret)
}
pub fn sizes() -> KyberSizes {
KyberSizes {
public_key: kyber1024::public_key_bytes(),
secret_key: kyber1024::secret_key_bytes(),
ciphertext: kyber1024::ciphertext_bytes(),
shared_secret: kyber1024::shared_secret_bytes(),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct KyberSizes {
pub public_key: usize,
pub secret_key: usize,
pub ciphertext: usize,
pub shared_secret: usize,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_keypair_generation() {
let keypair = KyberCrypto::generate_keypair();
assert_eq!(keypair.public_key.as_bytes().len(), KyberPublicKey::size());
assert_eq!(keypair.secret_key.as_bytes().len(), KyberSecretKey::size());
}
#[test]
fn test_encapsulate_decapsulate() {
let alice_keypair = KyberCrypto::generate_keypair();
let (bob_shared_secret, ciphertext) = KyberCrypto::encapsulate(&alice_keypair.public_key);
let alice_shared_secret = KyberCrypto::decapsulate(&ciphertext, &alice_keypair.secret_key);
assert_eq!(bob_shared_secret.as_bytes(), alice_shared_secret.as_bytes());
}
#[test]
fn test_serialization() {
let keypair = KyberCrypto::generate_keypair();
let pk_bytes = keypair.public_key.as_bytes();
let pk_restored = KyberPublicKey::from_bytes(pk_bytes).unwrap();
assert_eq!(pk_bytes, pk_restored.as_bytes());
let sk_bytes = keypair.secret_key.as_bytes();
let sk_restored = KyberSecretKey::from_bytes(sk_bytes).unwrap();
assert_eq!(sk_bytes, sk_restored.as_bytes());
let (ss1, ct) = KyberCrypto::encapsulate(&pk_restored);
let ss2 = KyberCrypto::decapsulate(&ct, &sk_restored);
assert_eq!(ss1.as_bytes(), ss2.as_bytes());
}
#[test]
fn test_sizes() {
let sizes = KyberCrypto::sizes();
assert_eq!(sizes.public_key, 1568); assert_eq!(sizes.secret_key, 3168); assert_eq!(sizes.ciphertext, 1568); assert_eq!(sizes.shared_secret, 32); }
}