#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
)]
#![allow(non_snake_case)] #![allow(clippy::clone_on_copy)]
#![cfg_attr(feature = "getrandom", doc = "```")]
#![cfg_attr(not(feature = "getrandom"), doc = "```ignore")]
mod algebra;
mod crypto;
mod compress;
mod decapsulation_key;
mod encapsulation_key;
mod pke;
mod param;
pub mod pkcs8;
pub use array::{self, ArraySize};
pub use decapsulation_key::DecapsulationKey;
#[allow(deprecated)]
pub use decapsulation_key::ExpandedKeyEncoding;
pub use encapsulation_key::EncapsulationKey;
pub use kem::{
self, Ciphertext, Decapsulate, Encapsulate, FromSeed, Generate, InvalidKey, Kem, Key,
KeyExport, KeyInit, KeySizeUser, TryKeyInit,
};
pub use ml_kem_512::MlKem512;
pub use ml_kem_768::MlKem768;
pub use ml_kem_1024::MlKem1024;
pub use param::{ExpandedDecapsulationKey, ParameterSet};
use array::{
Array,
sizes::{U2, U3, U4, U5, U10, U11, U32, U64},
};
use core::fmt::Debug;
pub type B32 = Array<u8, U32>;
pub type Seed = Array<u8, U64>;
pub mod ml_kem_512 {
use crate::{
Debug, ParameterSet, U2, U3, U4, U10,
kem::Kem,
param::{self, EncodedUSize, EncodedVSize},
};
use array::{sizes::U32, typenum::Sum};
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
pub struct MlKem512;
impl ParameterSet for MlKem512 {
type K = U2;
type Eta1 = U3;
type Eta2 = U2;
type Du = U10;
type Dv = U4;
}
impl Kem for MlKem512 {
type DecapsulationKey = DecapsulationKey;
type EncapsulationKey = EncapsulationKey;
type CiphertextSize = Sum<EncodedUSize<Self>, EncodedVSize<Self>>;
type SharedKeySize = U32;
}
pub type DecapsulationKey = crate::DecapsulationKey<MlKem512>;
pub type EncapsulationKey = crate::EncapsulationKey<MlKem512>;
pub type Ciphertext = kem::Ciphertext<MlKem512>;
#[doc(hidden)]
#[deprecated(since = "0.3.0", note = "use `Seed` instead")]
pub type ExpandedDecapsulationKey = param::ExpandedDecapsulationKey<MlKem512>;
}
pub mod ml_kem_768 {
use crate::{
Debug, ParameterSet, U2, U3, U4, U10,
kem::Kem,
param::{self, EncodedUSize, EncodedVSize},
};
use array::sizes::U32;
use array::typenum::Sum;
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
pub struct MlKem768;
impl ParameterSet for MlKem768 {
type K = U3;
type Eta1 = U2;
type Eta2 = U2;
type Du = U10;
type Dv = U4;
}
impl Kem for MlKem768 {
type DecapsulationKey = DecapsulationKey;
type EncapsulationKey = EncapsulationKey;
type CiphertextSize = Sum<EncodedUSize<Self>, EncodedVSize<Self>>;
type SharedKeySize = U32;
}
pub type DecapsulationKey = crate::DecapsulationKey<MlKem768>;
pub type EncapsulationKey = crate::EncapsulationKey<MlKem768>;
pub type Ciphertext = kem::Ciphertext<MlKem768>;
#[doc(hidden)]
#[deprecated(since = "0.3.0", note = "use `Seed` instead")]
pub type ExpandedDecapsulationKey = param::ExpandedDecapsulationKey<MlKem768>;
}
pub mod ml_kem_1024 {
use crate::{
Debug, ParameterSet, U2, U4, U5, U11,
kem::Kem,
param::{self, EncodedUSize, EncodedVSize},
};
use array::{sizes::U32, typenum::Sum};
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
pub struct MlKem1024;
impl ParameterSet for MlKem1024 {
type K = U4;
type Eta1 = U2;
type Eta2 = U2;
type Du = U11;
type Dv = U5;
}
impl Kem for MlKem1024 {
type DecapsulationKey = DecapsulationKey;
type EncapsulationKey = EncapsulationKey;
type CiphertextSize = Sum<EncodedUSize<Self>, EncodedVSize<Self>>;
type SharedKeySize = U32;
}
pub type DecapsulationKey = crate::DecapsulationKey<MlKem1024>;
pub type EncapsulationKey = crate::EncapsulationKey<MlKem1024>;
pub type Ciphertext = kem::Ciphertext<MlKem1024>;
#[doc(hidden)]
#[deprecated(since = "0.3.0", note = "use `Seed` instead")]
pub type ExpandedDecapsulationKey = param::ExpandedDecapsulationKey<MlKem1024>;
}
pub type DecapsulationKey512 = ml_kem_512::DecapsulationKey;
pub type EncapsulationKey512 = ml_kem_512::EncapsulationKey;
pub type DecapsulationKey768 = ml_kem_768::DecapsulationKey;
pub type EncapsulationKey768 = ml_kem_768::EncapsulationKey;
pub type DecapsulationKey1024 = ml_kem_1024::DecapsulationKey;
pub type EncapsulationKey1024 = ml_kem_1024::EncapsulationKey;
pub type SharedKey = Array<u8, U32>;
#[cfg(test)]
#[cfg(feature = "getrandom")]
mod test {
use super::*;
use crate::{MlKem512, MlKem768, MlKem1024, param::KemParams};
use ::kem::{Encapsulate, Generate, InvalidKey, TryDecapsulate};
use array::typenum::Unsigned;
use getrandom::SysRng;
use rand_core::{TryRng, UnwrapErr};
fn round_trip_test<K>()
where
K: Kem,
{
let (dk, ek) = K::generate_keypair();
let (ct, k_send) = ek.encapsulate();
let k_recv = dk.try_decapsulate(&ct).unwrap();
assert_eq!(k_send, k_recv);
}
#[test]
fn round_trip() {
round_trip_test::<MlKem512>();
round_trip_test::<MlKem768>();
round_trip_test::<MlKem1024>();
}
fn seed_test<P>()
where
P: KemParams,
{
let mut rng = UnwrapErr(SysRng);
let mut seed = Seed::default();
rng.try_fill_bytes(&mut seed).unwrap();
let dk = DecapsulationKey::<P>::from_seed(seed.clone());
let seed_encoded = dk.to_seed().unwrap();
assert_eq!(seed, seed_encoded);
let ek_original = dk.encapsulation_key();
let ek_encoded = ek_original.to_bytes();
let ek_decoded = EncapsulationKey::new(&ek_encoded).unwrap();
assert_eq!(ek_original, &ek_decoded);
}
#[test]
fn seed() {
seed_test::<MlKem512>();
seed_test::<MlKem768>();
seed_test::<MlKem1024>();
}
#[allow(deprecated)]
fn expanded_key_test<P>()
where
P: KemParams,
{
let mut rng = UnwrapErr(SysRng);
let dk_original = DecapsulationKey::<P>::generate_from_rng(&mut rng);
let dk_encoded = dk_original.to_expanded_bytes();
let dk_decoded = DecapsulationKey::from_expanded_bytes(&dk_encoded).unwrap();
assert_eq!(dk_original, dk_decoded);
}
#[test]
fn expanded_key() {
expanded_key_test::<MlKem512>();
expanded_key_test::<MlKem768>();
expanded_key_test::<MlKem1024>();
}
fn invalid_hash_expanded_key_test<P>()
where
P: KemParams,
{
let mut rng = UnwrapErr(SysRng);
let dk_original = DecapsulationKey::<P>::generate_from_rng(&mut rng);
#[allow(deprecated)]
let mut dk_encoded = dk_original.to_expanded_bytes();
let hash_offset = P::NttVectorSize::USIZE + P::EncryptionKeySize::USIZE;
dk_encoded[hash_offset] ^= 0xFF;
#[allow(deprecated)]
let dk_decoded: Result<DecapsulationKey<P>, InvalidKey> =
DecapsulationKey::from_expanded_bytes(&dk_encoded);
assert!(dk_decoded.is_err());
}
#[test]
fn invalid_hash_expanded_key() {
invalid_hash_expanded_key_test::<MlKem512>();
invalid_hash_expanded_key_test::<MlKem768>();
invalid_hash_expanded_key_test::<MlKem1024>();
}
fn key_inequality_test<P>()
where
P: KemParams,
{
let mut rng = UnwrapErr(SysRng);
let dk1 = DecapsulationKey::<P>::generate_from_rng(&mut rng);
let dk2 = DecapsulationKey::<P>::generate_from_rng(&mut rng);
let ek1 = dk1.encapsulation_key();
let ek2 = dk2.encapsulation_key();
assert_ne!(dk1, dk2);
assert_ne!(ek1, ek2);
}
#[test]
fn key_inequality() {
key_inequality_test::<MlKem512>();
key_inequality_test::<MlKem768>();
key_inequality_test::<MlKem1024>();
}
}