From 7a85383be2c3bb397b30855d28bb0f6598bd2a11 Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Thu, 4 Jun 2026 08:19:08 +0200 Subject: [PATCH 1/2] reformat code to rust coding style Signed-off-by: Nikola Pajkovsky --- cli/src/encoders_cmd.rs | 43 +- cli/src/helpers.rs | 31 +- cli/src/hkdf_cmd.rs | 38 +- cli/src/mac_cmd.rs | 4 +- cli/src/main.rs | 159 ++- cli/src/mldsa_cmd.rs | 105 +- cli/src/mlkem_cmd.rs | 51 +- cli/src/rng_cmd.rs | 8 +- cli/src/sha2_cmd.rs | 10 +- cli/src/sha3_cmd.rs | 15 +- crypto/base64/benches/base64_benches.rs | 25 +- crypto/base64/src/lib.rs | 7 +- crypto/base64/tests/base64_tests.rs | 27 +- crypto/core-test-framework/src/kdf.rs | 4 +- crypto/core-test-framework/src/kem.rs | 38 +- crypto/core-test-framework/src/mac.rs | 22 +- crypto/core-test-framework/src/signature.rs | 17 +- crypto/core/src/errors.rs | 12 +- crypto/core/src/key_material.rs | 5 +- crypto/core/src/traits.rs | 83 +- crypto/core/tests/key_material_tests.rs | 7 +- crypto/factory/src/lib.rs | 6 +- crypto/factory/src/rng_factory.rs | 54 +- crypto/factory/tests/hash_factory_tests.rs | 16 +- crypto/factory/tests/kdf_factory_tests.rs | 49 +- crypto/factory/tests/mac_factory_tests.rs | 11 +- crypto/factory/tests/rng_factory_tests.rs | 8 +- crypto/factory/tests/xof_factory_tests.rs | 2 +- crypto/hex/benches/hex_benches.rs | 2 +- crypto/hkdf/benches/hkdf_benches.rs | 26 +- crypto/hkdf/src/lib.rs | 76 +- crypto/hkdf/tests/hkdf_tests.rs | 312 +++-- crypto/hmac/benches/hmac_benches.rs | 8 +- crypto/hmac/tests/hmac_tests.rs | 128 +- crypto/mldsa/benches/mldsa_benches.rs | 137 +- crypto/mldsa/src/aux_functions.rs | 35 +- crypto/mldsa/src/polynomial.rs | 42 +- crypto/mldsa/tests/bc_test_data.rs | 6 +- .../mldsa_lowmemory/benches/mldsa_benches.rs | 51 +- crypto/mldsa_lowmemory/src/aux_functions.rs | 29 +- .../mldsa_lowmemory/src/low_memory_helpers.rs | 27 +- crypto/mldsa_lowmemory/src/mldsa.rs | 636 +++++---- crypto/mldsa_lowmemory/src/mldsa_keys.rs | 374 +++-- crypto/mldsa_lowmemory/src/polynomial.rs | 60 +- crypto/mldsa_lowmemory/tests/bc_test_data.rs | 7 +- .../mldsa_lowmemory/tests/hash_mldsa_tests.rs | 45 +- .../mldsa_lowmemory/tests/mldsa_key_tests.rs | 35 +- crypto/mldsa_lowmemory/tests/mldsa_tests.rs | 254 ++-- crypto/mlkem/benches/mlkem_benches.rs | 131 +- crypto/mlkem/src/aux_functions.rs | 76 +- crypto/mlkem/src/lib.rs | 38 +- crypto/mlkem/src/matrix.rs | 70 +- crypto/mlkem/src/mlkem.rs | 219 ++- crypto/mlkem/src/mlkem_keys.rs | 422 +++--- crypto/mlkem/src/polynomial.rs | 71 +- crypto/mlkem/tests/mlkem_key_tests.rs | 88 +- crypto/mlkem/tests/mlkem_tests.rs | 204 +-- .../mlkem_lowmemory/benches/mlkem_benches.rs | 52 +- crypto/mlkem_lowmemory/src/aux_functions.rs | 39 +- crypto/mlkem_lowmemory/src/lib.rs | 26 +- .../mlkem_lowmemory/src/low_memory_helpers.rs | 193 +-- crypto/mlkem_lowmemory/src/mlkem.rs | 263 ++-- crypto/mlkem_lowmemory/src/mlkem_keys.rs | 207 +-- crypto/mlkem_lowmemory/src/polynomial.rs | 83 +- crypto/mlkem_lowmemory/tests/bc_test_data.rs | 2 +- .../mlkem_lowmemory/tests/mlkem_key_tests.rs | 64 +- crypto/mlkem_lowmemory/tests/mlkem_tests.rs | 179 ++- crypto/rng/benches/hash_drbg_benches.rs | 2 +- crypto/rng/src/hash_drbg80090a.rs | 27 +- crypto/rng/tests/hash_drbg80090a_tests.rs | 4 +- crypto/sha2/src/sha256.rs | 7 +- crypto/sha2/src/sha512.rs | 2 +- crypto/sha3/benches/sha3_benches.rs | 2 +- crypto/sha3/src/sha3.rs | 10 +- crypto/sha3/src/shake.rs | 23 +- crypto/sha3/tests/sha3_tests.rs | 12 +- crypto/utils/src/ct.rs | 64 +- mem_usage_benches/bench_mlkem_mem_usage.rs | 1222 +++++++++++++++-- src/lib.rs | 6 +- 79 files changed, 4558 insertions(+), 2397 deletions(-) diff --git a/cli/src/encoders_cmd.rs b/cli/src/encoders_cmd.rs index 1de9d59..c3b6d0b 100644 --- a/cli/src/encoders_cmd.rs +++ b/cli/src/encoders_cmd.rs @@ -1,17 +1,17 @@ use std::io; use std::io::{Read, Write}; -use bouncycastle::hex; use bouncycastle::base64; +use bouncycastle::hex; pub(crate) fn hex_encode_cmd() { // Stream from stdin to stdout in chunks of 1 kb let mut buf: [u8; 1024] = [0u8; 1024]; let mut bytes_read = io::stdin().read(&mut buf).expect("Failed to read from stdin"); while bytes_read != 0 { - io::stdout().write_all( - hex::encode(&buf[..bytes_read]).as_bytes() - ).expect("Failed to write to stdout"); + io::stdout() + .write_all(hex::encode(&buf[..bytes_read]).as_bytes()) + .expect("Failed to write to stdout"); bytes_read = io::stdin().read(&mut buf).expect("Failed to read from stdin"); } @@ -22,13 +22,12 @@ pub(crate) fn hex_decode_cmd() { let mut buf: [u8; 1024] = [0u8; 1024]; let mut bytes_read = io::stdin().read(&mut buf).expect("Failed to read from stdin"); while bytes_read != 0 { - let chunk_str: String = String::from_utf8( - Vec::from(&buf[..bytes_read]) - ).expect("Input was not valid utf8."); + let chunk_str: String = + String::from_utf8(Vec::from(&buf[..bytes_read])).expect("Input was not valid utf8."); - io::stdout().write_all( - &*hex::decode(chunk_str.as_str()).expect("Input was not valid hex.") - ).expect("Failed to write to stdout"); + io::stdout() + .write_all(&*hex::decode(chunk_str.as_str()).expect("Input was not valid hex.")) + .expect("Failed to write to stdout"); bytes_read = io::stdin().read(&mut buf).expect("Failed to read from stdin"); } @@ -40,9 +39,9 @@ pub(crate) fn base64_encode_cmd() { let mut buf: [u8; 1024] = [0u8; 1024]; let mut bytes_read = io::stdin().read(&mut buf).expect("Failed to read from stdin"); while bytes_read != 0 { - io::stdout().write_all( - encoder.do_update(&buf[..bytes_read]).as_bytes() - ).expect("Failed to write to stdout"); + io::stdout() + .write_all(encoder.do_update(&buf[..bytes_read]).as_bytes()) + .expect("Failed to write to stdout"); bytes_read = io::stdin().read(&mut buf).expect("Failed to read from stdin"); } @@ -54,14 +53,18 @@ pub(crate) fn base64_decode_cmd() { let mut decoder = base64::Base64Decoder::new(true); let mut bytes_read = io::stdin().read(&mut buf).expect("Failed to read from stdin"); while bytes_read != 0 { - let chunk_str: String = String::from_utf8( - Vec::from(&buf[..bytes_read]) - ).expect("Input was not valid utf8."); + let chunk_str: String = + String::from_utf8(Vec::from(&buf[..bytes_read])).expect("Input was not valid utf8."); - io::stdout().write_all( - decoder.do_update(chunk_str.as_str()).expect("Input was not valid base64.").as_slice() - ).expect("Failed to write to stdout"); + io::stdout() + .write_all( + decoder + .do_update(chunk_str.as_str()) + .expect("Input was not valid base64.") + .as_slice(), + ) + .expect("Failed to write to stdout"); bytes_read = io::stdin().read(&mut buf).expect("Failed to read from stdin"); } -} \ No newline at end of file +} diff --git a/cli/src/helpers.rs b/cli/src/helpers.rs index 7fa4adf..62a7741 100644 --- a/cli/src/helpers.rs +++ b/cli/src/helpers.rs @@ -1,10 +1,10 @@ -use std::{io}; +use bouncycastle::core::key_material::{KeyMaterial, KeyMaterialTrait, KeyType}; +use bouncycastle::core::traits::SecurityStrength; +use bouncycastle::hex; use std::fs::File; +use std::io; use std::io::{Read, Write}; use std::process::exit; -use bouncycastle::core::key_material::{KeyMaterial, KeyMaterialTrait, KeyType}; -use bouncycastle::core::traits::{SecurityStrength}; -use bouncycastle::hex; /// Reads either bin or hex pub(crate) fn read_from_file(filename: &str) -> Vec { @@ -12,20 +12,20 @@ pub(crate) fn read_from_file(filename: &str) -> Vec { if file.is_ok() { let mut buf = Vec::::new(); match file.unwrap().read_to_end(&mut buf) { - Ok(_bytes_read) => { + Ok(_bytes_read) => { // try hex decoding it match hex::decode(&buf) { - Ok(decoded) => { decoded }, + Ok(decoded) => decoded, Err(_) => { // well, it's not hex, so return it raw buf - }, + } } - }, + } Err(_) => { eprintln!("Error: couldn't open file '{}'", &filename); exit(-1); - }, + } } } else { eprintln!("Error: couldn't open file '{}'", &filename); @@ -35,22 +35,21 @@ pub(crate) fn read_from_file(filename: &str) -> Vec { /// Reads either bin or hex pub(crate) fn read_from_file_or_stdin(filename: &Option) -> Vec { - if filename.is_some() { // This already reads either bin or hex return read_from_file(filename.as_ref().unwrap()); } - + let mut buf = Vec::::new(); io::stdin().read_to_end(&mut buf).expect("Failed to read from stdin"); // try hex decoding it match hex::decode(&buf) { - Ok(decoded) => { decoded }, + Ok(decoded) => decoded, Err(_) => { // well, it's not hex, so return it raw buf - }, + } } } @@ -84,7 +83,7 @@ pub(crate) fn parse_seed(bytes: &[u8]) -> Result { - if decoded_bytes.len() < SEED_LEN || decoded_bytes.len() > SEED_LEN +1 { + if decoded_bytes.len() < SEED_LEN || decoded_bytes.len() > SEED_LEN + 1 { // it was valid hex, but the wrong length return Err(()); } @@ -92,7 +91,7 @@ pub(crate) fn parse_seed(bytes: &[u8]) -> Result { // it's not hex, so take the fist SEED_LEN bytes of the raw binary - if bytes.len() < SEED_LEN || bytes.len() > SEED_LEN +1 { + if bytes.len() < SEED_LEN || bytes.len() > SEED_LEN + 1 { return Err(()); } bytes[..SEED_LEN].try_into().unwrap() @@ -113,4 +112,4 @@ pub(crate) fn parse_seed(bytes: &[u8]) -> Result, - salt_file: &Option, - ikm: &Option, - ikm_file: &Option, - additional_input: &Option, - additional_input_file: &Option, - len: usize, - output_hex: bool ) { +pub(crate) fn hkdf_cmd( + hkdfname: &str, + salt: &Option, + salt_file: &Option, + ikm: &Option, + ikm_file: &Option, + additional_input: &Option, + additional_input_file: &Option, + len: usize, + output_hex: bool, +) { let salt_bytes: Vec; let ikm_bytes: Vec; let additional_input_bytes: Vec; @@ -53,7 +55,6 @@ pub(crate) fn hkdf_cmd(hkdfname: &str, exit(-1) }; - additional_input_bytes = if additional_input.is_some() { hex::decode(additional_input.as_ref().unwrap()).unwrap() } else if additional_input.is_some() { @@ -72,21 +73,24 @@ pub(crate) fn hkdf_cmd(hkdfname: &str, h.do_extract_update_bytes(ikm_bytes.as_slice()).unwrap(); h.do_extract_update_bytes(additional_input_bytes.as_slice()).unwrap(); h.do_extract_final_out(&mut out_key).unwrap(); - }, + } "HKDF-SHA512" => { let mut h = hkdf::HKDF_SHA512::new(); h.do_extract_init(&salt_key).unwrap(); h.do_extract_update_bytes(ikm_bytes.as_slice()).unwrap(); h.do_extract_update_bytes(additional_input_bytes.as_slice()).unwrap(); h.do_extract_final_out(&mut out_key).unwrap(); - }, - _ => { panic!("{} is not a supported HKDF variant.", hkdfname); } + } + _ => { + panic!("{} is not a supported HKDF variant.", hkdfname); + } } - if output_hex { for b in out_key.ref_to_bytes().iter() { print!("{b:02x}"); } - } else { io::stdout().write(&out_key.ref_to_bytes()).unwrap(); } -} \ No newline at end of file + } else { + io::stdout().write(&out_key.ref_to_bytes()).unwrap(); + } +} diff --git a/cli/src/mac_cmd.rs b/cli/src/mac_cmd.rs index 3a4e98d..343cb0b 100644 --- a/cli/src/mac_cmd.rs +++ b/cli/src/mac_cmd.rs @@ -37,13 +37,12 @@ pub(crate) fn mac_cmd( key.allow_hazardous_operations(); key.convert_key_type(KeyType::MACKey).unwrap(); - // instantiate the MAC object and call do_mac() match hmac_variant { HMACVariant::SHA256 => { let mac = HMAC_SHA256::new_allow_weak_key(&key).unwrap(); do_mac(mac, verify_val, output_hex); - }, + } HMACVariant::SHA512 => { let mac = HMAC_SHA512::new_allow_weak_key(&key).unwrap(); do_mac(mac, verify_val, output_hex); @@ -51,7 +50,6 @@ pub(crate) fn mac_cmd( } } - fn do_mac(mut mac: impl MAC, verify_val: &Option, output_hex: bool) { // read the content to be MAC'd from stdin let mut buf: [u8; 1024] = [0u8; 1024]; diff --git a/cli/src/main.rs b/cli/src/main.rs index 3296160..45205bf 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,21 +1,20 @@ -mod sha3_cmd; mod encoders_cmd; -mod sha2_cmd; -mod mac_cmd; +mod helpers; mod hkdf_cmd; -mod rng_cmd; +mod mac_cmd; mod mldsa_cmd; mod mlkem_cmd; -mod helpers; +mod rng_cmd; +mod sha2_cmd; +mod sha3_cmd; -use clap::{Parser, Subcommand}; use crate::mac_cmd::HMACVariant; use crate::mldsa_cmd::MLDSAAction; +use clap::{Parser, Subcommand}; #[derive(Parser)] #[command(version, about, long_about=None, arg_required_else_help=true)] struct Cli { - #[command(subcommand)] subcommands: Option, } @@ -30,7 +29,7 @@ enum Subcommands { /// Decode base64 data from stdin to binary. /// Supports streaming for low memory footprint and continuous processing from stdin to stdout. HexDecode, - + /// Encode binary data from stdin to base64. /// Supports streaming for low memory footprint and continuous processing from stdin to stdout. Base64Encode, @@ -163,7 +162,7 @@ enum Subcommands { /// If both key and key_file options are provided, the file will be used. #[arg(short, long)] key_file: Option, - + /// A MAC value to be verified. /// The command will output either 0 for success or -1 for verification failure. #[arg(short, long)] @@ -174,7 +173,6 @@ enum Subcommands { x: bool, }, - /// Perform HMAC-SHA256 of the content provided on stdin. /// HKDF.extract_and_expand(salt, ikm, additional_info, L) /// Note: in production uses, secrets should not be passed on the command-line because they get @@ -218,7 +216,6 @@ enum Subcommands { x: bool, }, - /// Perform HMAC-SHA512 of the content provided on stdin. /// HKDF.extract_and_expand(salt, ikm, additional_info, L) /// Note: in production uses, secrets should not be passed on the command-line because they get @@ -285,7 +282,7 @@ enum Subcommands { #[arg(long)] /// The public key file (in hex or binary) for encaps pkfile: Option, - + #[arg(long)] /// The ciphertext value file (in hex or binary) either for encaps to output to, or for decaps to read from. ctfile: Option, @@ -432,7 +429,6 @@ enum Subcommands { /// The signature value file (in hex or binary) for verifying sigfile: Option, - #[arg(short)] /// Output in hex format. x: bool, @@ -458,7 +454,6 @@ enum Subcommands { /// The signature value file (in hex or binary) for verifying sigfile: Option, - #[arg(short)] /// Output in hex format. x: bool, @@ -484,46 +479,120 @@ enum Subcommands { /// The signature value file (in hex or binary) for verifying sigfile: Option, - #[arg(short)] /// Output in hex format. x: bool, }, } - fn main() { let cli = Cli::parse(); match &cli.subcommands { - Some(Subcommands::HexEncode) => { encoders_cmd::hex_encode_cmd(); } - Some(Subcommands::HexDecode) => { encoders_cmd::hex_decode_cmd(); } - Some(Subcommands::Base64Encode) => { encoders_cmd::base64_encode_cmd(); } - Some(Subcommands::Base64Decode) => { encoders_cmd::base64_decode_cmd(); } - Some(Subcommands::SHA224 { x}) => { sha2_cmd::sha2_cmd(224, *x); }, - Some(Subcommands::SHA256 { x}) => { sha2_cmd::sha2_cmd(256, *x); }, - Some(Subcommands::SHA384 { x}) => { sha2_cmd::sha2_cmd(384, *x); }, - Some(Subcommands::SHA512 { x}) => { sha2_cmd::sha2_cmd(512, *x); }, - Some(Subcommands::SHA3_224 { x}) => { sha3_cmd::sha3_cmd(224, *x); }, - Some(Subcommands::SHA3_256 { x}) => { sha3_cmd::sha3_cmd(256, *x); }, - Some(Subcommands::SHA3_384 { x}) => { sha3_cmd::sha3_cmd(384, *x); }, - Some(Subcommands::SHA3_512 { x}) => { sha3_cmd::sha3_cmd(512, *x); }, - Some(Subcommands::SHAKE128 { length, x}) => { sha3_cmd::shake_cmd(128, *length, *x); }, - Some(Subcommands::SHAKE256 { length, x}) => { sha3_cmd::shake_cmd(256, *length, *x); }, - Some(Subcommands::HMAC_SHA256 { key, key_file, verify, x}) => { mac_cmd::mac_cmd(HMACVariant::SHA256, key, key_file, verify, *x)}, - Some(Subcommands::HMAC_SHA512 { key, key_file, verify, x}) => { mac_cmd::mac_cmd(HMACVariant::SHA512, key, key_file, verify, *x)}, - Some(Subcommands::HKDF_SHA256 { salt, salt_file, ikm, ikm_file, additional_input, additional_input_file, len, x}) => { hkdf_cmd::hkdf_cmd("HKDF-SHA256", salt, salt_file, ikm, ikm_file, additional_input, additional_input_file, *len, *x)}, - Some(Subcommands::HKDF_SHA512 { salt, salt_file, ikm, ikm_file, additional_input, additional_input_file, len, x}) => { hkdf_cmd::hkdf_cmd("HKDF-SHA512", salt, salt_file, ikm, ikm_file, additional_input, additional_input_file, *len, *x)}, - Some(Subcommands::RNG { len, x}) => { rng_cmd::rng_cmd(*len, *x)}, - Some(Subcommands::MLKEM512 { action, skfile, pkfile, ctfile, x }) => { mlkem_cmd::mlkem512_cmd(action, skfile, pkfile, ctfile, *x); } - Some(Subcommands::MLKEM768 { action, skfile, pkfile, ctfile, x }) => { mlkem_cmd::mlkem768_cmd(action, skfile, pkfile, ctfile, *x); } - Some(Subcommands::MLKEM1024 { action, skfile, pkfile, ctfile, x }) => { mlkem_cmd::mlkem1024_cmd(action, skfile, pkfile, ctfile, *x); } - Some(Subcommands::MLDSA44 { action, ctxfile, skfile, pkfile, sigfile, x }) => { mldsa_cmd::mldsa44_cmd(action, ctxfile, skfile, pkfile, sigfile, *x); } - Some(Subcommands::MLDSA65 { action, ctxfile, skfile, pkfile, sigfile, x }) => { mldsa_cmd::mldsa65_cmd(action, ctxfile, skfile, pkfile, sigfile, *x); } - Some(Subcommands::MLDSA87 { action, ctxfile, skfile, pkfile, sigfile, x }) => { mldsa_cmd::mldsa87_cmd(action, ctxfile, skfile, pkfile, sigfile, *x); } - Some(Subcommands::HashMLDSA44 { action, ctxfile, skfile, pkfile, sigfile, x }) => { mldsa_cmd::hash_mldsa44_sha512_cmd(action, ctxfile, skfile, pkfile, sigfile, *x); } - Some(Subcommands::HashMLDSA65 { action, ctxfile, skfile, pkfile, sigfile, x }) => { mldsa_cmd::hash_mldsa65_sha512_cmd(action, ctxfile, skfile, pkfile, sigfile, *x); } - Some(Subcommands::HashMLDSA87 { action, ctxfile, skfile, pkfile, sigfile, x }) => { mldsa_cmd::hash_mldsa87_sha512_cmd(action, ctxfile, skfile, pkfile, sigfile, *x); } - None => { eprintln!("No command provided. See -h") }, + Some(Subcommands::HexEncode) => { + encoders_cmd::hex_encode_cmd(); + } + Some(Subcommands::HexDecode) => { + encoders_cmd::hex_decode_cmd(); + } + Some(Subcommands::Base64Encode) => { + encoders_cmd::base64_encode_cmd(); + } + Some(Subcommands::Base64Decode) => { + encoders_cmd::base64_decode_cmd(); + } + Some(Subcommands::SHA224 { x }) => { + sha2_cmd::sha2_cmd(224, *x); + } + Some(Subcommands::SHA256 { x }) => { + sha2_cmd::sha2_cmd(256, *x); + } + Some(Subcommands::SHA384 { x }) => { + sha2_cmd::sha2_cmd(384, *x); + } + Some(Subcommands::SHA512 { x }) => { + sha2_cmd::sha2_cmd(512, *x); + } + Some(Subcommands::SHA3_224 { x }) => { + sha3_cmd::sha3_cmd(224, *x); + } + Some(Subcommands::SHA3_256 { x }) => { + sha3_cmd::sha3_cmd(256, *x); + } + Some(Subcommands::SHA3_384 { x }) => { + sha3_cmd::sha3_cmd(384, *x); + } + Some(Subcommands::SHA3_512 { x }) => { + sha3_cmd::sha3_cmd(512, *x); + } + Some(Subcommands::SHAKE128 { length, x }) => { + sha3_cmd::shake_cmd(128, *length, *x); + } + Some(Subcommands::SHAKE256 { length, x }) => { + sha3_cmd::shake_cmd(256, *length, *x); + } + Some(Subcommands::HMAC_SHA256 { key, key_file, verify, x }) => { + mac_cmd::mac_cmd(HMACVariant::SHA256, key, key_file, verify, *x) + } + Some(Subcommands::HMAC_SHA512 { key, key_file, verify, x }) => { + mac_cmd::mac_cmd(HMACVariant::SHA512, key, key_file, verify, *x) + } + Some(Subcommands::HKDF_SHA256 { + salt, + salt_file, + ikm, + ikm_file, + additional_input, + additional_input_file, + len, + x, + }) => hkdf_cmd::hkdf_cmd( + "HKDF-SHA256", salt, salt_file, ikm, ikm_file, additional_input, additional_input_file, + *len, *x, + ), + Some(Subcommands::HKDF_SHA512 { + salt, + salt_file, + ikm, + ikm_file, + additional_input, + additional_input_file, + len, + x, + }) => hkdf_cmd::hkdf_cmd( + "HKDF-SHA512", salt, salt_file, ikm, ikm_file, additional_input, additional_input_file, + *len, *x, + ), + Some(Subcommands::RNG { len, x }) => rng_cmd::rng_cmd(*len, *x), + Some(Subcommands::MLKEM512 { action, skfile, pkfile, ctfile, x }) => { + mlkem_cmd::mlkem512_cmd(action, skfile, pkfile, ctfile, *x); + } + Some(Subcommands::MLKEM768 { action, skfile, pkfile, ctfile, x }) => { + mlkem_cmd::mlkem768_cmd(action, skfile, pkfile, ctfile, *x); + } + Some(Subcommands::MLKEM1024 { action, skfile, pkfile, ctfile, x }) => { + mlkem_cmd::mlkem1024_cmd(action, skfile, pkfile, ctfile, *x); + } + Some(Subcommands::MLDSA44 { action, ctxfile, skfile, pkfile, sigfile, x }) => { + mldsa_cmd::mldsa44_cmd(action, ctxfile, skfile, pkfile, sigfile, *x); + } + Some(Subcommands::MLDSA65 { action, ctxfile, skfile, pkfile, sigfile, x }) => { + mldsa_cmd::mldsa65_cmd(action, ctxfile, skfile, pkfile, sigfile, *x); + } + Some(Subcommands::MLDSA87 { action, ctxfile, skfile, pkfile, sigfile, x }) => { + mldsa_cmd::mldsa87_cmd(action, ctxfile, skfile, pkfile, sigfile, *x); + } + Some(Subcommands::HashMLDSA44 { action, ctxfile, skfile, pkfile, sigfile, x }) => { + mldsa_cmd::hash_mldsa44_sha512_cmd(action, ctxfile, skfile, pkfile, sigfile, *x); + } + Some(Subcommands::HashMLDSA65 { action, ctxfile, skfile, pkfile, sigfile, x }) => { + mldsa_cmd::hash_mldsa65_sha512_cmd(action, ctxfile, skfile, pkfile, sigfile, *x); + } + Some(Subcommands::HashMLDSA87 { action, ctxfile, skfile, pkfile, sigfile, x }) => { + mldsa_cmd::hash_mldsa87_sha512_cmd(action, ctxfile, skfile, pkfile, sigfile, *x); + } + None => { + eprintln!("No command provided. See -h") + } } } diff --git a/cli/src/mldsa_cmd.rs b/cli/src/mldsa_cmd.rs index 79ba941..8a1a4e3 100644 --- a/cli/src/mldsa_cmd.rs +++ b/cli/src/mldsa_cmd.rs @@ -4,11 +4,16 @@ use crate::helpers::{parse_seed, read_from_file, read_from_file_or_stdin, write_bytes_or_hex}; use bouncycastle::core::traits::{Signature, SignaturePrivateKey, SignaturePublicKey}; use bouncycastle::hex; -use bouncycastle::mldsa::{MLDSA_SEED_LEN, MLDSA44, MLDSA44_SK_LEN, MLDSA44PrivateKey, MLDSA87_SK_LEN, MLDSAPrivateKeyTrait, MLDSATrait, MLDSA44PublicKey, MLDSA44_PK_LEN, MLDSA65_SK_LEN, MLDSA65PrivateKey, MLDSA65, MLDSA65PublicKey, MLDSA65_PK_LEN, MLDSA87PrivateKey, MLDSA87, MLDSA87PublicKey, MLDSA87_PK_LEN, HashMLDSA44_with_SHA512, HashMLDSA65_with_SHA512, HashMLDSA87_with_SHA512}; -use std::{io}; -use std::io::{Read}; -use std::process::exit; +use bouncycastle::mldsa::{ + HashMLDSA44_with_SHA512, HashMLDSA65_with_SHA512, HashMLDSA87_with_SHA512, MLDSA_SEED_LEN, + MLDSA44, MLDSA44_PK_LEN, MLDSA44_SK_LEN, MLDSA44PrivateKey, MLDSA44PublicKey, MLDSA65, + MLDSA65_PK_LEN, MLDSA65_SK_LEN, MLDSA65PrivateKey, MLDSA65PublicKey, MLDSA87, MLDSA87_PK_LEN, + MLDSA87_SK_LEN, MLDSA87PrivateKey, MLDSA87PublicKey, MLDSAPrivateKeyTrait, MLDSATrait, +}; use clap::ValueEnum; +use std::io; +use std::io::Read; +use std::process::exit; #[derive(ValueEnum, Clone, Debug)] pub(crate) enum MLDSAAction { @@ -48,7 +53,10 @@ pub(crate) fn mldsa44_cmd( let seed = match parse_seed::(&buf) { Ok(seed) => seed, Err(()) => { - eprintln!("Error: input could not be parsed as a {} byte seed in either hex or bin", MLDSA_SEED_LEN); + eprintln!( + "Error: input could not be parsed as a {} byte seed in either hex or bin", + MLDSA_SEED_LEN + ); exit(-1); } }; @@ -94,7 +102,9 @@ pub(crate) fn mldsa44_cmd( }; match MLDSA44::keypair_consistency_check(&pk, &sk) { - Ok(_) => { println!("SUCCESS: pk and sk match."); } + Ok(_) => { + println!("SUCCESS: pk and sk match."); + } Err(_) => { eprintln!("FAILURE: pk and sk do not match."); exit(-1); @@ -113,7 +123,9 @@ pub(crate) fn mldsa44_cmd( // then read ctx let ctx = if ctxfile.is_some() { read_from_file(ctxfile.as_ref().unwrap()) - } else { vec![0u8;0] }; + } else { + vec![0u8; 0] + }; // and now sign, streaming the message from stdin let sk = match parse_mldsa44_sk(&sk_bytes) { @@ -156,7 +168,9 @@ pub(crate) fn mldsa44_cmd( // then read ctx let ctx = if ctxfile.is_some() { read_from_file(ctxfile.as_ref().unwrap()) - } else { vec![0u8;0] }; + } else { + vec![0u8; 0] + }; // then read the sig let sig = if sigfile.is_some() { @@ -185,7 +199,7 @@ pub(crate) fn mldsa44_cmd( eprintln!("Signature is invalid."); exit(-1); } - }, + } } } @@ -247,7 +261,9 @@ pub(crate) fn mldsa65_cmd( }; match MLDSA65::keypair_consistency_check(&pk, &sk) { - Ok(_) => { println!("SUCCESS: pk and sk match."); } + Ok(_) => { + println!("SUCCESS: pk and sk match."); + } Err(_) => { eprintln!("FAILURE: pk and sk do not match."); exit(-1); @@ -266,7 +282,9 @@ pub(crate) fn mldsa65_cmd( // then read ctx let ctx = if ctxfile.is_some() { read_from_file(ctxfile.as_ref().unwrap()) - } else { vec![0u8;0] }; + } else { + vec![0u8; 0] + }; // and now sign, streaming the message from stdin let sk = match parse_mldsa65_sk(&sk_bytes) { @@ -309,7 +327,9 @@ pub(crate) fn mldsa65_cmd( // then read ctx let ctx = if ctxfile.is_some() { read_from_file(ctxfile.as_ref().unwrap()) - } else { vec![0u8;0] }; + } else { + vec![0u8; 0] + }; // then read the sig let sig = if sigfile.is_some() { @@ -338,7 +358,7 @@ pub(crate) fn mldsa65_cmd( eprintln!("Signature is invalid."); exit(-1); } - }, + } } } pub(crate) fn mldsa87_cmd( @@ -383,7 +403,6 @@ pub(crate) fn mldsa87_cmd( } }; - // first, read the pk let pk_bytes = if pkfile.is_some() { read_from_file(pkfile.as_ref().unwrap()) @@ -400,7 +419,9 @@ pub(crate) fn mldsa87_cmd( }; match MLDSA87::keypair_consistency_check(&pk, &sk) { - Ok(_) => { println!("SUCCESS: pk and sk match."); } + Ok(_) => { + println!("SUCCESS: pk and sk match."); + } Err(_) => { eprintln!("FAILURE: pk and sk do not match."); exit(-1); @@ -419,7 +440,9 @@ pub(crate) fn mldsa87_cmd( // then read ctx let ctx = if ctxfile.is_some() { read_from_file(ctxfile.as_ref().unwrap()) - } else { vec![0u8;0] }; + } else { + vec![0u8; 0] + }; // and now sign, streaming the message from stdin let sk = match parse_mldsa87_sk(&sk_bytes) { @@ -462,7 +485,9 @@ pub(crate) fn mldsa87_cmd( // then read ctx let ctx = if ctxfile.is_some() { read_from_file(ctxfile.as_ref().unwrap()) - } else { vec![0u8;0] }; + } else { + vec![0u8; 0] + }; // then read the sig let sig = if sigfile.is_some() { @@ -491,7 +516,7 @@ pub(crate) fn mldsa87_cmd( eprintln!("Signature is invalid."); exit(-1); } - }, + } } } @@ -553,7 +578,9 @@ pub(crate) fn hash_mldsa44_sha512_cmd( }; match MLDSA44::keypair_consistency_check(&pk, &sk) { - Ok(_) => { println!("SUCCESS: pk and sk match."); } + Ok(_) => { + println!("SUCCESS: pk and sk match."); + } Err(_) => { eprintln!("FAILURE: pk and sk do not match."); exit(-1); @@ -572,7 +599,9 @@ pub(crate) fn hash_mldsa44_sha512_cmd( // then read ctx let ctx = if ctxfile.is_some() { read_from_file(ctxfile.as_ref().unwrap()) - } else { vec![0u8;0] }; + } else { + vec![0u8; 0] + }; // and now sign, streaming the message from stdin let sk = match parse_mldsa44_sk(&sk_bytes) { @@ -615,7 +644,9 @@ pub(crate) fn hash_mldsa44_sha512_cmd( // then read ctx let ctx = if ctxfile.is_some() { read_from_file(ctxfile.as_ref().unwrap()) - } else { vec![0u8;0] }; + } else { + vec![0u8; 0] + }; // then read the sig let sig = if sigfile.is_some() { @@ -644,7 +675,7 @@ pub(crate) fn hash_mldsa44_sha512_cmd( eprintln!("Signature is invalid."); exit(-1); } - }, + } } } @@ -706,7 +737,9 @@ pub(crate) fn hash_mldsa65_sha512_cmd( }; match MLDSA65::keypair_consistency_check(&pk, &sk) { - Ok(_) => { println!("SUCCESS: pk and sk match."); } + Ok(_) => { + println!("SUCCESS: pk and sk match."); + } Err(_) => { eprintln!("FAILURE: pk and sk do not match."); exit(-1); @@ -725,7 +758,9 @@ pub(crate) fn hash_mldsa65_sha512_cmd( // then read ctx let ctx = if ctxfile.is_some() { read_from_file(ctxfile.as_ref().unwrap()) - } else { vec![0u8;0] }; + } else { + vec![0u8; 0] + }; // and now sign, streaming the message from stdin let sk = match parse_mldsa65_sk(&sk_bytes) { @@ -768,7 +803,9 @@ pub(crate) fn hash_mldsa65_sha512_cmd( // then read ctx let ctx = if ctxfile.is_some() { read_from_file(ctxfile.as_ref().unwrap()) - } else { vec![0u8;0] }; + } else { + vec![0u8; 0] + }; // then read the sig let sig = if sigfile.is_some() { @@ -797,7 +834,7 @@ pub(crate) fn hash_mldsa65_sha512_cmd( eprintln!("Signature is invalid."); exit(-1); } - }, + } } } pub(crate) fn hash_mldsa87_sha512_cmd( @@ -858,7 +895,9 @@ pub(crate) fn hash_mldsa87_sha512_cmd( }; match MLDSA87::keypair_consistency_check(&pk, &sk) { - Ok(_) => { println!("SUCCESS: pk and sk match."); } + Ok(_) => { + println!("SUCCESS: pk and sk match."); + } Err(_) => { eprintln!("FAILURE: pk and sk do not match."); exit(-1); @@ -877,7 +916,9 @@ pub(crate) fn hash_mldsa87_sha512_cmd( // then read ctx let ctx = if ctxfile.is_some() { read_from_file(ctxfile.as_ref().unwrap()) - } else { vec![0u8;0] }; + } else { + vec![0u8; 0] + }; // and now sign, streaming the message from stdin let sk = match parse_mldsa87_sk(&sk_bytes) { @@ -920,7 +961,9 @@ pub(crate) fn hash_mldsa87_sha512_cmd( // then read ctx let ctx = if ctxfile.is_some() { read_from_file(ctxfile.as_ref().unwrap()) - } else { vec![0u8;0] }; + } else { + vec![0u8; 0] + }; // then read the sig let sig = if sigfile.is_some() { @@ -949,7 +992,7 @@ pub(crate) fn hash_mldsa87_sha512_cmd( eprintln!("Signature is invalid."); exit(-1); } - }, + } } } @@ -1137,4 +1180,4 @@ fn parse_mldsa87_pk(bytes: &[u8]) -> Result { } // else: we're out of things to try Err("Error: couldn't parse the input as a valid ML-DSA-87 public key.") -} \ No newline at end of file +} diff --git a/cli/src/mlkem_cmd.rs b/cli/src/mlkem_cmd.rs index de56238..2ac50e2 100644 --- a/cli/src/mlkem_cmd.rs +++ b/cli/src/mlkem_cmd.rs @@ -1,13 +1,21 @@ //! Yup, this file is as absolutely atrocious mess of duplicate code that could be much improved //! by using generics or macros. I just, haven't ... yet. -use std::process::exit; -use clap::ValueEnum; +use crate::helpers::{ + parse_seed, read_from_file, read_from_file_or_stdin, write_bytes_or_hex, + write_bytes_or_hex_to_file, +}; use bouncycastle::core::key_material::KeyMaterialTrait; -use bouncycastle::core::traits::{KEMPrivateKey, KEMPublicKey, KEM}; +use bouncycastle::core::traits::{KEM, KEMPrivateKey, KEMPublicKey}; use bouncycastle::hex; -use bouncycastle::mlkem::{MLKEM512, MLKEMTrait, MLKEM512PrivateKey, MLKEM512_SK_LEN, MLKEM512PublicKey, MLKEM512_PK_LEN, MLKEMPrivateKeyTrait, MLKEM512_CT_LEN, MLKEM768PrivateKey, MLKEM768_SK_LEN, MLKEM768, MLKEM768PublicKey, MLKEM768_PK_LEN, MLKEM1024PrivateKey, MLKEM1024_SK_LEN, MLKEM1024, MLKEM1024_PK_LEN, MLKEM1024PublicKey, MLKEM768_CT_LEN, MLKEM1024_CT_LEN}; -use crate::helpers::{parse_seed, read_from_file, read_from_file_or_stdin, write_bytes_or_hex, write_bytes_or_hex_to_file}; +use bouncycastle::mlkem::{ + MLKEM512, MLKEM512_CT_LEN, MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM512PrivateKey, + MLKEM512PublicKey, MLKEM768, MLKEM768_CT_LEN, MLKEM768_PK_LEN, MLKEM768_SK_LEN, + MLKEM768PrivateKey, MLKEM768PublicKey, MLKEM1024, MLKEM1024_CT_LEN, MLKEM1024_PK_LEN, + MLKEM1024_SK_LEN, MLKEM1024PrivateKey, MLKEM1024PublicKey, MLKEMPrivateKeyTrait, MLKEMTrait, +}; +use clap::ValueEnum; +use std::process::exit; #[derive(ValueEnum, Clone, Debug)] pub(crate) enum MLKEMAction { @@ -94,13 +102,15 @@ pub(crate) fn mlkem512_cmd( }; match MLKEM512::keypair_consistency_check(&pk, &sk) { - Ok(_) => { println!("SUCCESS: pk and sk match."); } + Ok(_) => { + println!("SUCCESS: pk and sk match."); + } Err(_) => { eprintln!("FAILURE: pk and sk do not match."); exit(-1); } } - }, + } MLKEMAction::Encaps => { // first, read the pk let pk_bytes = read_from_file_or_stdin(pkfile); @@ -124,8 +134,7 @@ pub(crate) fn mlkem512_cmd( println!(); write_bytes_or_hex(ss.ref_to_bytes(), true); } - - }, + } MLKEMAction::Decaps => { // first, read the sk let sk_bytes = read_from_file_or_stdin(skfile); @@ -216,13 +225,15 @@ pub(crate) fn mlkem768_cmd( }; match MLKEM768::keypair_consistency_check(&pk, &sk) { - Ok(_) => { println!("SUCCESS: pk and sk match."); } + Ok(_) => { + println!("SUCCESS: pk and sk match."); + } Err(_) => { eprintln!("FAILURE: pk and sk do not match."); exit(-1); } } - }, + } MLKEMAction::Encaps => { // first, read the pk let pk_bytes = read_from_file_or_stdin(pkfile); @@ -246,7 +257,7 @@ pub(crate) fn mlkem768_cmd( println!(); write_bytes_or_hex(ss.ref_to_bytes(), true); } - }, + } MLKEMAction::Decaps => { // first, read the sk let sk_bytes = read_from_file_or_stdin(skfile); @@ -337,13 +348,15 @@ pub(crate) fn mlkem1024_cmd( }; match MLKEM1024::keypair_consistency_check(&pk, &sk) { - Ok(_) => { println!("SUCCESS: pk and sk match."); } + Ok(_) => { + println!("SUCCESS: pk and sk match."); + } Err(_) => { eprintln!("FAILURE: pk and sk do not match."); exit(-1); } } - }, + } MLKEMAction::Encaps => { // first, read the pk let pk_bytes = read_from_file_or_stdin(pkfile); @@ -367,7 +380,7 @@ pub(crate) fn mlkem1024_cmd( println!(); write_bytes_or_hex(ss.ref_to_bytes(), true); } - }, + } MLKEMAction::Decaps => { // first, read the sk let sk_bytes = read_from_file_or_stdin(skfile); @@ -401,7 +414,6 @@ pub(crate) fn mlkem1024_cmd( } } - fn parse_mlkem512_sk(bytes: &[u8]) -> Result { // try it in Biggest -> Smallest order @@ -459,7 +471,7 @@ fn parse_mlkem512_pk(bytes: &[u8]) -> Result { if pk.is_ok() { return Ok(pk.unwrap()); } - } // else: we're out of things to try + } // else: we're out of things to try Err("Error: couldn't parse the input as a valid ML-KEM-768 public key.") } @@ -521,7 +533,7 @@ fn parse_mlkem768_pk(bytes: &[u8]) -> Result { if pk.is_ok() { return Ok(pk.unwrap()); } - } // else: we're out of things to try + } // else: we're out of things to try Err("Error: couldn't parse the input as a valid ML-KEM-768 public key.") } @@ -583,8 +595,7 @@ fn parse_mlkem1024_pk(bytes: &[u8]) -> Result if pk.is_ok() { return Ok(pk.unwrap()); } - } // else: we're out of things to try + } // else: we're out of things to try Err("Error: couldn't parse the input as a valid ML-KEM-1024 public key.") } - diff --git a/cli/src/rng_cmd.rs b/cli/src/rng_cmd.rs index 7fabca8..e7a28e5 100644 --- a/cli/src/rng_cmd.rs +++ b/cli/src/rng_cmd.rs @@ -1,4 +1,4 @@ -use bouncycastle::core::traits::{RNG}; +use bouncycastle::core::traits::RNG; use bouncycastle::factory::AlgorithmFactory; use bouncycastle::factory::rng_factory::RNGFactory; @@ -13,9 +13,11 @@ pub(crate) fn rng_cmd(len: Option, output_hex: bool) { while loop_forever || bytes_left_to_write > 0 { rng.next_bytes_out(&mut buf).unwrap(); - if bytes_left_to_write < buf.len() { buf.truncate(bytes_left_to_write); } + if bytes_left_to_write < buf.len() { + buf.truncate(bytes_left_to_write); + } write_bytes_or_hex(&buf, output_hex); bytes_left_to_write -= buf.len(); } println!(); -} \ No newline at end of file +} diff --git a/cli/src/sha2_cmd.rs b/cli/src/sha2_cmd.rs index 4007a13..3551c9d 100644 --- a/cli/src/sha2_cmd.rs +++ b/cli/src/sha2_cmd.rs @@ -1,4 +1,4 @@ -use bouncycastle::core::traits::{Hash}; +use bouncycastle::core::traits::Hash; use std::io; use std::io::{Read, Write}; @@ -10,7 +10,7 @@ pub(crate) fn sha2_cmd(bit_len: usize, output_hex: bool) { 256 => do_sha2(SHA256::new(), output_hex), 384 => do_sha2(SHA384::new(), output_hex), 512 => do_sha2(SHA512::new(), output_hex), - _ => panic!("Unsupported algorithm: SHA{}", bit_len) + _ => panic!("Unsupported algorithm: SHA{}", bit_len), } } @@ -30,6 +30,8 @@ fn do_sha2(mut sha2: impl Hash, output_hex: bool) { for b in out.iter() { print!("{b:02x}"); } - } else { io::stdout().write(&out).unwrap(); } + } else { + io::stdout().write(&out).unwrap(); + } println!(); -} \ No newline at end of file +} diff --git a/cli/src/sha3_cmd.rs b/cli/src/sha3_cmd.rs index 3efa6a7..27d5feb 100644 --- a/cli/src/sha3_cmd.rs +++ b/cli/src/sha3_cmd.rs @@ -2,7 +2,6 @@ use bouncycastle::core::traits::{Hash, XOF}; use std::io; use std::io::{Read, Write}; - use bouncycastle::sha3::{SHA3_224, SHA3_256, SHA3_384, SHA3_512, SHAKE128, SHAKE256}; pub(crate) fn sha3_cmd(bit_len: usize, output_hex: bool) { @@ -11,7 +10,7 @@ pub(crate) fn sha3_cmd(bit_len: usize, output_hex: bool) { 256 => do_sha3(SHA3_256::new(), output_hex), 384 => do_sha3(SHA3_384::new(), output_hex), 512 => do_sha3(SHA3_512::new(), output_hex), - _ => panic!("Unsupported algorithm: SHA3-{}", bit_len) + _ => panic!("Unsupported algorithm: SHA3-{}", bit_len), } } @@ -31,7 +30,9 @@ fn do_sha3(mut sha3: impl Hash, output_hex: bool) { for b in out.iter() { print!("{b:02x}"); } - } else { io::stdout().write(&out).unwrap(); } + } else { + io::stdout().write(&out).unwrap(); + } println!(); } @@ -39,7 +40,7 @@ pub(crate) fn shake_cmd(bit_len: usize, output_len: usize, output_hex: bool) { match bit_len { 128 => do_shake(SHAKE128::new(), output_len, output_hex), 256 => do_shake(SHAKE256::new(), output_len, output_hex), - _ => panic!("Unsupported algorithm: SHAKE-{}", bit_len) + _ => panic!("Unsupported algorithm: SHAKE-{}", bit_len), } } @@ -57,6 +58,8 @@ fn do_shake(mut shake: impl XOF, output_len: usize, output_hex: bool) { for b in out.iter() { print!("{b:02x}"); } - } else { io::stdout().write(&out).unwrap(); } + } else { + io::stdout().write(&out).unwrap(); + } println!(); -} \ No newline at end of file +} diff --git a/crypto/base64/benches/base64_benches.rs b/crypto/base64/benches/base64_benches.rs index 914d671..efe84d0 100644 --- a/crypto/base64/benches/base64_benches.rs +++ b/crypto/base64/benches/base64_benches.rs @@ -1,8 +1,8 @@ -use std::hint::black_box; -use criterion::{Criterion, Throughput, criterion_group, criterion_main}; -use bouncycastle_rng as rng; +use bouncycastle_base64::{Base64Decoder, Base64Encoder}; use bouncycastle_core::traits::RNG; -use bouncycastle_base64::{Base64Encoder, Base64Decoder}; +use bouncycastle_rng as rng; +use criterion::{Criterion, Throughput, criterion_group, criterion_main}; +use std::hint::black_box; fn bench_base64_encode(c: &mut Criterion) { const INPUT_SIZE: usize = 16 * 1024; @@ -37,7 +37,7 @@ fn bench_base64_decode(c: &mut Criterion) { // Generate some base65-encoded data. let mut encoder = Base64Encoder::new(); - let input: String = encoder.do_update(&data); // will be 1024 * 4 / 3 + 2 = 1368 bytes long. + let input: String = encoder.do_update(&data); // will be 1024 * 4 / 3 + 2 = 1368 bytes long. let mut output = vec![0u8; INPUT_SIZE]; @@ -47,16 +47,21 @@ fn bench_base64_decode(c: &mut Criterion) { b.iter(|| { let mut decoder = Base64Decoder::new(false); for _ in 0..16 { - output.extend_from_slice(&*decoder.do_update(black_box(&input)).expect("TODO: panic message")); + output.extend_from_slice( + &*decoder.do_update(black_box(&input)).expect("TODO: panic message"), + ); } - output.extend_from_slice(decoder.do_final(&str::from_utf8(&[0u8; 0]).expect("TODO: panic message")) - .expect("TODO: panic message").as_slice()); + output.extend_from_slice( + decoder + .do_final(&str::from_utf8(&[0u8; 0]).expect("TODO: panic message")) + .expect("TODO: panic message") + .as_slice(), + ); black_box(&output); }) }); group.finish(); } - criterion_group!(benches, bench_base64_encode, bench_base64_decode); -criterion_main!(benches); \ No newline at end of file +criterion_main!(benches); diff --git a/crypto/base64/src/lib.rs b/crypto/base64/src/lib.rs index 8b7cfeb..bd2fdb8 100644 --- a/crypto/base64/src/lib.rs +++ b/crypto/base64/src/lib.rs @@ -81,7 +81,6 @@ // /// "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=" // URLSafe, - use bouncycastle_utils::ct::Condition; /// One-shot encode from bytes to a base64-encoded string using a constant-time implementation. @@ -229,7 +228,7 @@ impl Base64Decoder { #[allow(non_snake_case)] let c_AZ: i64 = b as i64 - 'A' as i64; let c_az: i64 = b as i64 - 'a' as i64 + 26; - let c_09: i64 = b as i64 - '0' as i64 + 2*26; + let c_09: i64 = b as i64 - '0' as i64 + 2 * 26; let mut ret: i64 = 0xFFi64; @@ -307,7 +306,9 @@ impl Base64Decoder { let mut out = match self.decode_internal(input, false) { Ok(out) => out, Err(Base64Error::PaddingEnconteredDuringDoUpdate) => { - panic!("rollback_if_padding = false should not produce a Base64Error::PaddingEnconteredDuringDoUpdate"); + panic!( + "rollback_if_padding = false should not produce a Base64Error::PaddingEnconteredDuringDoUpdate" + ); } Err(e) => return Err(e), }; diff --git a/crypto/base64/tests/base64_tests.rs b/crypto/base64/tests/base64_tests.rs index 607356e..eba9036 100644 --- a/crypto/base64/tests/base64_tests.rs +++ b/crypto/base64/tests/base64_tests.rs @@ -1,7 +1,7 @@ extern crate core; use bouncycastle_base64 as base64; -use bouncycastle_base64::{Base64Encoder, Base64Decoder}; +use bouncycastle_base64::{Base64Decoder, Base64Encoder}; const LOREM_IPSUM: &[u8] = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; const LOREM_IPSUM_B64: &str = "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwgc2VkIGRvIGVpdXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWduYSBhbGlxdWEuIFV0IGVuaW0gYWQgbWluaW0gdmVuaWFtLCBxdWlzIG5vc3RydWQgZXhlcmNpdGF0aW9uIHVsbGFtY28gbGFib3JpcyBuaXNpIHV0IGFsaXF1aXAgZXggZWEgY29tbW9kbyBjb25zZXF1YXQuIER1aXMgYXV0ZSBpcnVyZSBkb2xvciBpbiByZXByZWhlbmRlcml0IGluIHZvbHVwdGF0ZSB2ZWxpdCBlc3NlIGNpbGx1bSBkb2xvcmUgZXUgZnVnaWF0IG51bGxhIHBhcmlhdHVyLiBFeGNlcHRldXIgc2ludCBvY2NhZWNhdCBjdXBpZGF0YXQgbm9uIHByb2lkZW50LCBzdW50IGluIGN1bHBhIHF1aSBvZmZpY2lhIGRlc2VydW50IG1vbGxpdCBhbmltIGlkIGVzdCBsYWJvcnVtLg=="; @@ -9,7 +9,7 @@ const LOREM_IPSUM_B64: &str = "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3Rld #[cfg(test)] mod ctbase64_test { use super::*; - + #[test] fn test_base64_encode() { assert_eq!(base64::encode(b"\x00"), "AA=="); @@ -40,20 +40,29 @@ mod ctbase64_test { assert_eq!(base64::decode("SGVsbG8sIFdvcmxkIQ==").unwrap(), b"Hello, World!"); assert_eq!(base64::decode("AAECAwQFBg==").unwrap(), b"\x00\x01\x02\x03\x04\x05\x06"); assert_eq!(base64::decode("AAECAwQFBgc=").unwrap(), b"\x00\x01\x02\x03\x04\x05\x06\x07"); - assert_eq!(base64::decode("AAECAwQFBgcI").unwrap(), b"\x00\x01\x02\x03\x04\x05\x06\x07\x08"); + assert_eq!( + base64::decode("AAECAwQFBgcI").unwrap(), + b"\x00\x01\x02\x03\x04\x05\x06\x07\x08" + ); // test some whitespace // failure case - let decoder = Base64Decoder::new(/*skip_whitespace=*/false); + let decoder = Base64Decoder::new(/*skip_whitespace=*/ false); match decoder.do_final(" AAE CA wQF \nBgcI") { Ok(_) => panic!("expected decode to fail"), Err(_) => {} } // success case - let decoder = Base64Decoder::new(/*skip_whitespace=*/true); - assert_eq!(decoder.do_final(" AAE CA wQF BgcI").unwrap(), b"\x00\x01\x02\x03\x04\x05\x06\x07\x08"); - assert_eq!(base64::decode(" AAE CA wQF BgcI").unwrap(), b"\x00\x01\x02\x03\x04\x05\x06\x07\x08"); + let decoder = Base64Decoder::new(/*skip_whitespace=*/ true); + assert_eq!( + decoder.do_final(" AAE CA wQF BgcI").unwrap(), + b"\x00\x01\x02\x03\x04\x05\x06\x07\x08" + ); + assert_eq!( + base64::decode(" AAE CA wQF BgcI").unwrap(), + b"\x00\x01\x02\x03\x04\x05\x06\x07\x08" + ); // test invalid base64 match base64::decode("AAECAwQF&?nBgcI") { @@ -73,10 +82,10 @@ mod ctbase64_test { let mut i: usize = 0; while i < LOREM_IPSUM_B64.len() - 10 { - out.extend(decoder.do_update(&LOREM_IPSUM_B64[i..i+10]).unwrap()); + out.extend(decoder.do_update(&LOREM_IPSUM_B64[i..i + 10]).unwrap()); i += 10; } out.extend(decoder.do_final(&LOREM_IPSUM_B64[i..]).unwrap()); assert_eq!(LOREM_IPSUM, out); } -} \ No newline at end of file +} diff --git a/crypto/core-test-framework/src/kdf.rs b/crypto/core-test-framework/src/kdf.rs index 35b429a..3f60b49 100644 --- a/crypto/core-test-framework/src/kdf.rs +++ b/crypto/core-test-framework/src/kdf.rs @@ -1,4 +1,6 @@ -use bouncycastle_core::key_material::{KeyMaterial256, KeyMaterial512, KeyMaterial, KeyType, KeyMaterialTrait}; +use bouncycastle_core::key_material::{ + KeyMaterial, KeyMaterial256, KeyMaterial512, KeyMaterialTrait, KeyType, +}; use bouncycastle_core::traits::{KDF, SecurityStrength}; pub struct TestFrameworkKDF {} diff --git a/crypto/core-test-framework/src/kem.rs b/crypto/core-test-framework/src/kem.rs index 785d499..cc16593 100644 --- a/crypto/core-test-framework/src/kem.rs +++ b/crypto/core-test-framework/src/kem.rs @@ -1,5 +1,5 @@ use bouncycastle_core::errors::KEMError; -use bouncycastle_core::traits::{KEMPrivateKey, KEMPublicKey, KEM}; +use bouncycastle_core::traits::{KEM, KEMPrivateKey, KEMPublicKey}; pub struct TestFrameworkKEM { // Put any config options here @@ -53,12 +53,15 @@ impl TestFrameworkKEM { assert_ne!(ss, ss2); } else { match KEMAlg::decaps(&sk, &ct) { - Err(KEMError::DecapsulationFailed) => /* good */ (), + Err(KEMError::DecapsulationFailed) => + /* good */ + { + () + } _ => panic!("This should have thrown an error but it didn't."), } } - // test flipping every bit ... this will take some time to run if run_full_bitflipping_tests { for i in 0..ct.len() { @@ -72,30 +75,33 @@ impl TestFrameworkKEM { assert_ne!(ss, ss2); } else { match KEMAlg::decaps(&sk, &ct) { - Err(KEMError::DecapsulationFailed) => /* good */ (), + Err(KEMError::DecapsulationFailed) => + /* good */ + { + () + } _ => panic!("This should have thrown an error but it didn't."), } } } } } - // test ct the wrong length let (pk, sk) = KEMAlg::keygen().unwrap(); let (_ss, ct) = KEMAlg::encaps(&pk).unwrap(); - + // too short - match KEMAlg::decaps(&sk, &ct[..CT_LEN-1]) { - Err(KEMError::LengthError(_)) => { /* good */ }, + match KEMAlg::decaps(&sk, &ct[..CT_LEN - 1]) { + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("This should have thrown an error but it didn't."), }; - + // too long let mut long_ct = vec![1u8; CT_LEN + 2]; long_ct.as_mut_slice()[..CT_LEN].copy_from_slice(&ct); match KEMAlg::decaps(&sk, &long_ct) { - Err(KEMError::LengthError(_)) => { /* good */ }, + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("This should have thrown an error but it didn't."), }; } @@ -104,9 +110,8 @@ impl TestFrameworkKEM { pub struct TestFrameworkKEMKeys {} impl TestFrameworkKEMKeys { - pub fn new() -> Self { - Self { } + Self {} } pub fn test_keys< @@ -117,7 +122,9 @@ impl TestFrameworkKEMKeys { const SK_LEN: usize, const CT_LEN: usize, const SS_LEN: usize, - >(&self) { + >( + &self, + ) { self.test_boundary_conditions::(); } @@ -130,7 +137,9 @@ impl TestFrameworkKEMKeys { const SK_LEN: usize, const CT_LEN: usize, const SS_LEN: usize, - >(&self) { + >( + &self, + ) { let (pk, sk) = KEMAlg::keygen().unwrap(); let pk_bytes = pk.encode(); @@ -149,7 +158,6 @@ impl TestFrameworkKEMKeys { _ => panic!("Should have failed"), } - let sk_bytes = sk.encode(); assert_eq!(sk_bytes.len(), SK_LEN); // too short diff --git a/crypto/core-test-framework/src/mac.rs b/crypto/core-test-framework/src/mac.rs index 728e35c..87c8db5 100644 --- a/crypto/core-test-framework/src/mac.rs +++ b/crypto/core-test-framework/src/mac.rs @@ -1,8 +1,8 @@ use crate::DUMMY_SEED_512; use bouncycastle_core::errors::{KeyMaterialError, MACError}; -use bouncycastle_core::key_material::{KeyMaterial512, KeyType, KeyMaterialTrait}; +use bouncycastle_core::key_material::{KeyMaterial512, KeyMaterialTrait, KeyType}; use bouncycastle_core::traits::MAC; -use bouncycastle_core::traits::{SecurityStrength}; +use bouncycastle_core::traits::SecurityStrength; pub struct TestFrameworkMAC { // Put any config options here @@ -71,7 +71,6 @@ impl TestFrameworkMAC { mac.do_update(input); mac.do_verify_final(expected_output); - // entropy of input key // MACs of all security strengths should throw an error on a no-security (and non-zero) key. @@ -81,8 +80,10 @@ impl TestFrameworkMAC { key_none.set_security_strength(SecurityStrength::None).unwrap(); match M::new(&key_none) { - Err(MACError::KeyMaterialError(KeyMaterialError::SecurityStrength(_))) => { /* fine */ }, - _ => panic!("This should have thrown a KeyMaterialError::SecurityStrength error but it didn't"), + Err(MACError::KeyMaterialError(KeyMaterialError::SecurityStrength(_))) => { /* fine */ } + _ => panic!( + "This should have thrown a KeyMaterialError::SecurityStrength error but it didn't" + ), } let mut low_security_key = @@ -113,11 +114,18 @@ impl TestFrameworkMAC { low_security_key.drop_hazardous_operations(); // init - assert!(low_security_key.security_strength() < M::new_allow_weak_key(key).unwrap().max_security_strength()); + assert!( + low_security_key.security_strength() + < M::new_allow_weak_key(key).unwrap().max_security_strength() + ); // complains at first match M::new(&low_security_key) { Err(MACError::KeyMaterialError(KeyMaterialError::SecurityStrength(_))) => { /* fine */ } - _ => { panic!("This should have thrown a KeyMaterialError::SecurityStrength error but it didn't") } + _ => { + panic!( + "This should have thrown a KeyMaterialError::SecurityStrength error but it didn't" + ) + } } // but fine if you do it with .allow_weak_keys() let mut hmac = M::new_allow_weak_key(&low_security_key).unwrap(); diff --git a/crypto/core-test-framework/src/signature.rs b/crypto/core-test-framework/src/signature.rs index 1ee694e..329e8f6 100644 --- a/crypto/core-test-framework/src/signature.rs +++ b/crypto/core-test-framework/src/signature.rs @@ -106,7 +106,7 @@ impl TestFrameworkSignature { // fn sign_final_out(&mut self, msg_chunk: &[u8], ctx: &[u8], output: &mut [u8]) -> Result<(), SignatureError>; // First, test the streaming API with one call to .sign_update - let mut s = SigAlg::sign_init(&sk, Some(b"streaming API")).unwrap(); + let mut s = SigAlg::sign_init(&sk, Some(b"streaming API")).unwrap(); s.sign_update(DUMMY_SEED_1024); let sig_val = s.sign_final().unwrap(); SigAlg::verify(&pk, DUMMY_SEED_1024, Some(b"streaming API"), &sig_val).unwrap(); @@ -151,14 +151,12 @@ impl TestFrameworkSignature { assert_eq!(bytes_written, SIG_LEN); SigAlg::verify(&pk, DUMMY_SEED_1024, Some(b"streaming API"), &sig_val).unwrap(); - // the ::verify API should accept a sig value that's too long and just ignore the extra bytes let mut sig_val_too_long = vec![1u8; SIG_LEN + 2]; sig_val_too_long[..SIG_LEN].copy_from_slice(&sig_val); SigAlg::verify(&pk, DUMMY_SEED_1024, Some(b"streaming API"), &sig_val).unwrap(); } - /// Test all the members of trait Hash against the given input-output pair. /// This gives good baseline test coverage, but is not exhaustive. pub fn test_ph_signature< @@ -243,7 +241,6 @@ impl TestFrameworkSignature { let sig = SigAlg::sign(&sk, DUMMY_SEED_1024, None).unwrap(); SigAlg::verify(&pk, DUMMY_SEED_1024, None, &sig).unwrap(); - // the ::verify API should not accept a sig value that's too let mut sig_val_too_long = vec![1u8; SIG_LEN + 2]; sig_val_too_long[..SIG_LEN].copy_from_slice(&sig); @@ -257,9 +254,8 @@ impl TestFrameworkSignature { pub struct TestFrameworkSignatureKeys {} impl TestFrameworkSignatureKeys { - pub fn new() -> Self { - Self { } + Self {} } pub fn test_keys< @@ -269,7 +265,9 @@ impl TestFrameworkSignatureKeys { const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, - >(&self) { + >( + &self, + ) { self.test_boundary_conditions::(); } @@ -281,7 +279,9 @@ impl TestFrameworkSignatureKeys { const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, - >(&self) { + >( + &self, + ) { let (pk, sk) = SigAlg::keygen().unwrap(); let pk_bytes = pk.encode(); @@ -300,7 +300,6 @@ impl TestFrameworkSignatureKeys { _ => panic!("Should have failed"), } - let sk_bytes = sk.encode(); assert_eq!(sk_bytes.len(), SK_LEN); // too short diff --git a/crypto/core/src/errors.rs b/crypto/core/src/errors.rs index 9b52bc6..b2eaf0c 100644 --- a/crypto/core/src/errors.rs +++ b/crypto/core/src/errors.rs @@ -80,9 +80,6 @@ pub enum SignatureError { RNGError(RNGError), } - - - /*** Promotion functions ***/ impl From for HashError { fn from(e: KeyMaterialError) -> HashError { @@ -115,7 +112,9 @@ impl From for KEMError { } impl From for KEMError { - fn from(e: RNGError) -> KEMError { Self::RNGError(e) } + fn from(e: RNGError) -> KEMError { + Self::RNGError(e) + } } impl From for MACError { @@ -143,6 +142,7 @@ impl From for SignatureError { } impl From for SignatureError { - fn from(e: RNGError) -> SignatureError { Self::RNGError(e) } + fn from(e: RNGError) -> SignatureError { + Self::RNGError(e) + } } - diff --git a/crypto/core/src/key_material.rs b/crypto/core/src/key_material.rs index df17c88..48f903e 100644 --- a/crypto/core/src/key_material.rs +++ b/crypto/core/src/key_material.rs @@ -38,7 +38,7 @@ //! It as always possible, for example, to extract the bytes from a KeyMaterial object, manipulate them, and then re-wrap them in a new KeyMaterial object. use crate::errors::KeyMaterialError; -use crate::traits::{RNG, SecurityStrength, Secret}; +use crate::traits::{RNG, Secret, SecurityStrength}; use bouncycastle_utils::{ct, min}; use core::cmp::{Ordering, PartialOrd}; @@ -51,7 +51,6 @@ pub type KeyMaterial128 = KeyMaterial<16>; pub type KeyMaterial256 = KeyMaterial<32>; pub type KeyMaterial512 = KeyMaterial<64>; - /// A helper class used across the bc-rust.test library to hold bytes-like key material. /// See [KeyMaterial] for for details, such as constructors. pub trait KeyMaterialTrait { @@ -121,7 +120,7 @@ pub trait KeyMaterialTrait { /// [KeyMaterialTrait::allow_hazardous_operations] set. /// Throws [KeyMaterialError::InvalidLength] on a request to set the security level higher than the current key length. fn set_security_strength(&mut self, strength: SecurityStrength) - -> Result<(), KeyMaterialError>; + -> Result<(), KeyMaterialError>; /// Sets this instance to be able to perform potentially hazardous conversions such as /// casting a KeyMaterial of type RawUnknownEntropy or RawLowEntropy into RawFullEntropy or SymmetricCipherKey, diff --git a/crypto/core/src/traits.rs b/crypto/core/src/traits.rs index 27dd844..8f6a8a1 100644 --- a/crypto/core/src/traits.rs +++ b/crypto/core/src/traits.rs @@ -1,9 +1,9 @@ //! Provides simplified abstracted APIs over classes of cryptigraphic primitives, such as Hash, KDF, etc. -use core::marker::Sized; -use core::fmt::{Debug, Display}; use crate::errors::{HashError, KDFError, KEMError, MACError, RNGError, SignatureError}; use crate::key_material::KeyMaterialTrait; +use core::fmt::{Debug, Display}; +use core::marker::Sized; // Imports needed for docs #[allow(unused_imports)] @@ -17,7 +17,7 @@ pub trait Algorithm { const MAX_SECURITY_STRENGTH: SecurityStrength; } -pub trait Hash : Default { +pub trait Hash: Default { /// The size of the internal block in bits -- needed by functions such as HMAC to compute security parameters. fn block_bitlen(&self) -> usize; @@ -84,7 +84,7 @@ pub trait HashAlgParams: Algorithm { /// A Key Derivation Function (KDF) is a function that takes in one or more input key and some unstructured /// additional input, and uses them to produces a derived key. -pub trait KDF : Default { +pub trait KDF: Default { /// Implementations of this function are capable of deriving an output key from an input key, /// assuming that they have been properly initialized. /// @@ -186,11 +186,12 @@ pub trait KEM< const SK_LEN: usize, const CT_LEN: usize, const SS_LEN: usize, ->: Sized { +>: Sized +{ /// Generate a keypair. /// Error condition: Basically only on RNG failures fn keygen() -> Result<(PK, SK), KEMError>; - + /// Performs an encapsulation against the given public key. /// Returns the ciphertext and derived shared secret. fn encaps(pk: &PK) -> Result<(KeyMaterial, [u8; CT_LEN]), KEMError>; @@ -204,7 +205,9 @@ pub trait KEM< // todo: that automatically call the encode and from_bytes() ? /// A public key for a KEM algorithm, often denoted "pk". -pub trait KEMPublicKey : PartialEq + Eq + Clone + Debug + Display + Sized { +pub trait KEMPublicKey: + PartialEq + Eq + Clone + Debug + Display + Sized +{ /// Write it out to bytes in its standard encoding. fn encode(&self) -> [u8; PK_LEN]; /// Write it out to bytes in its standard encoding. @@ -214,7 +217,7 @@ pub trait KEMPublicKey : PartialEq + Eq + Clone + Debug + D } /// A private key for a KEM algorithm, often denoted "sk" (for "secret key"). -pub trait KEMPrivateKey : PartialEq + Eq + Clone + Secret + Sized { +pub trait KEMPrivateKey: PartialEq + Eq + Clone + Secret + Sized { /// Write it out to bytes in its standard encoding. fn encode(&self) -> [u8; SK_LEN]; /// Write it out to bytes in its standard encoding. @@ -223,7 +226,6 @@ pub trait KEMPrivateKey : PartialEq + Eq + Clone + Secret + fn from_bytes(bytes: &[u8]) -> Result; } - /// A Message Authentication Code algorithm is a keyed hash function that behaves somewhat like a symmetric signature function. /// A MAC algorithm takes in a key and some data, and produces a MAC (message authentication code) that /// can be used to verify the integrity of data. @@ -293,7 +295,7 @@ pub trait MAC: Sized { /// Depending on the underlying MAC implementation, NIST may require that the library enforce /// a minimum length on the mac output value. See documentation for the underlying implementation /// to see conditions under which it throws [MACError::InvalidLength]. - fn mac_out(self, data: &[u8],out: &mut [u8]) -> Result; + fn mac_out(self, data: &[u8], out: &mut [u8]) -> Result; /// One-shot API that verifies a MAC for the provided data. /// `data` can be of any length, including zero bytes. @@ -381,11 +383,14 @@ impl SecurityStrength { /// be used by applications that intend to submit to FIPS certification as it more closely aligns with the /// requirements of SP 800-90A. /// Note: this interface produces bytes. If you want a [KeyMaterialTrait], then use [KeyMaterial::from_rng]. -pub trait RNG : Default { +pub trait RNG: Default { // TODO: add back once we figure out streaming interaction with entropy sources. // fn add_seed_bytes(&mut self, additional_seed: &[u8]) -> Result<(), RNGError>; - fn add_seed_keymaterial(&mut self, additional_seed: impl KeyMaterialTrait) -> Result<(), RNGError>; + fn add_seed_keymaterial( + &mut self, + additional_seed: impl KeyMaterialTrait, + ) -> Result<(), RNGError>; fn next_int(&mut self) -> Result; /// Returns the number of requested bytes. @@ -403,9 +408,9 @@ pub trait RNG : Default { /// A trait that forces an object to implement a zeroizing Drop() as well as Debug and Display that /// will not log the sensitive contents, even in error or crash-dump scenarios. #[allow(drop_bounds)] // Since rust auto-implements Drop, there's a lint that explicitly bounding on Drop is useless. - // I disagree because I want to force things that are secrets to manually implement Drop that zeroizes the data. - // So I'm turning off this lint. -pub trait Secret : Drop + Debug + Display {} +// I disagree because I want to force things that are secrets to manually implement Drop that zeroizes the data. +// So I'm turning off this lint. +pub trait Secret: Drop + Debug + Display {} /// Pre-Hashed Signature is an extension to [Signature] that adds functionality specific to signature /// primatives that can operate on a pre-hashed message instead of the full message. @@ -415,8 +420,9 @@ pub trait PHSignature< const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, - const PH_LEN: usize>: - Signature{ + const PH_LEN: usize, +>: Signature +{ /// Produce a signature for the provided pre-hashed message and context. /// /// `ctx` accepts a zero-length byte array. @@ -441,12 +447,26 @@ pub trait PHSignature< /// Not all signature primitives will support a context value, so you may need to consult the /// documentation for the underlying primitive for how it handles a ctx in that case, for example, it /// might throw an error, ignore the provided ctx value, or append the ctx to the msg in a non-standard way. - fn sign_ph(sk: &SK, ph: &[u8; PH_LEN], ctx: Option<&[u8]>) -> Result<[u8; SIG_LEN], SignatureError>; + fn sign_ph( + sk: &SK, + ph: &[u8; PH_LEN], + ctx: Option<&[u8]>, + ) -> Result<[u8; SIG_LEN], SignatureError>; /// Returns the number of bytes written to the output buffer. Can be called with an oversized buffer. - fn sign_ph_out(sk: &SK, ph: &[u8; PH_LEN], ctx: Option<&[u8]>, output: &mut [u8; SIG_LEN]) -> Result; + fn sign_ph_out( + sk: &SK, + ph: &[u8; PH_LEN], + ctx: Option<&[u8]>, + output: &mut [u8; SIG_LEN], + ) -> Result; /// On success, returns Ok(()) /// On failure, returns Err([SignatureError::SignatureVerificationFailed]); may also return other types of [SignatureError] as appropriate (such as for invalid-length inputs). - fn verify_ph(pk: &PK, ph: &[u8; PH_LEN], ctx: Option<&[u8]>, sig: &[u8]) -> Result<(), SignatureError>; + fn verify_ph( + pk: &PK, + ph: &[u8; PH_LEN], + ctx: Option<&[u8]>, + sig: &[u8], + ) -> Result<(), SignatureError>; } /// A digital signature algorithm is defined as a set of three operations: @@ -469,8 +489,9 @@ pub trait Signature< SK: SignaturePrivateKey, const PK_LEN: usize, const SK_LEN: usize, - const SIG_LEN: usize ->: Sized { + const SIG_LEN: usize, +>: Sized +{ /// Generate a keypair. /// Error condition: Basically only on RNG failures fn keygen() -> Result<(PK, SK), SignatureError>; @@ -501,7 +522,12 @@ pub trait Signature< fn sign(sk: &SK, msg: &[u8], ctx: Option<&[u8]>) -> Result<[u8; SIG_LEN], SignatureError>; /// Returns the number of bytes written to the output buffer. Can be called with an oversized buffer. - fn sign_out(sk: &SK, msg: &[u8], ctx: Option<&[u8]>, output: &mut [u8; SIG_LEN]) -> Result; + fn sign_out( + sk: &SK, + msg: &[u8], + ctx: Option<&[u8]>, + output: &mut [u8; SIG_LEN], + ) -> Result; /* streaming signing API */ /// Initialize a signer for streaming mode with the provided private key. @@ -539,7 +565,9 @@ pub trait Signature< // todo: that automatically call the encode and from_bytes() ? /// A public key for a signature algorithm, often denoted "pk". -pub trait SignaturePublicKey : PartialEq + Eq + Clone + Debug + Display + Sized { +pub trait SignaturePublicKey: + PartialEq + Eq + Clone + Debug + Display + Sized +{ /// Write it out to bytes in its standard encoding. fn encode(&self) -> [u8; PK_LEN]; /// Write it out to bytes in its standard encoding. @@ -549,7 +577,9 @@ pub trait SignaturePublicKey : PartialEq + Eq + Clone + Deb } /// A private key for a signature algorithm, often denoted "sk" (for "secret key"). -pub trait SignaturePrivateKey : PartialEq + Eq + Clone + Secret + Sized { +pub trait SignaturePrivateKey: + PartialEq + Eq + Clone + Secret + Sized +{ /// Write it out to bytes in its standard encoding. fn encode(&self) -> [u8; SK_LEN]; /// Write it out to bytes in its standard encoding. @@ -558,7 +588,6 @@ pub trait SignaturePrivateKey : PartialEq + Eq + Clone + Se fn from_bytes(bytes: &[u8]) -> Result; } - /// Extensible Output Functions (XOFs) are similar to hash functions, except that they can produce output of arbitrary length. /// The naming used for the functions of this trait are borrowed from the SHA3-style sponge constructions that split XOF operation /// into two phases: an absorb phase in which an arbitrary amount of input is provided to the XOF, @@ -577,7 +606,7 @@ pub trait SignaturePrivateKey : PartialEq + Eq + Clone + Se /// to break anonymity-preserving technology. /// Applications that require the arbitrary-length output of an XOF, but also care about these /// distinguishing attacks should consider adding a cryptographic salt to diversify the inputs. -pub trait XOF : Default { +pub trait XOF: Default { /// A static one-shot API that digests the input data and produces `result_len` bytes of output. fn hash_xof(self, data: &[u8], result_len: usize) -> Vec; diff --git a/crypto/core/tests/key_material_tests.rs b/crypto/core/tests/key_material_tests.rs index 41fca0b..5e773fd 100644 --- a/crypto/core/tests/key_material_tests.rs +++ b/crypto/core/tests/key_material_tests.rs @@ -2,9 +2,10 @@ mod test_key_material { use bouncycastle_core::errors::KeyMaterialError; use bouncycastle_core::key_material::{ - KeyMaterial0, KeyMaterial128, KeyMaterial256, KeyMaterial512, KeyMaterial, KeyType, KeyMaterialTrait, + KeyMaterial, KeyMaterial0, KeyMaterial128, KeyMaterial256, KeyMaterial512, + KeyMaterialTrait, KeyType, }; - use bouncycastle_core::traits::{SecurityStrength}; + use bouncycastle_core::traits::SecurityStrength; const DUMMY_KEY: &[u8; 64] = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ @@ -443,7 +444,7 @@ mod test_key_material { let key1 = KeyMaterial256::from_bytes_as_type(&DUMMY_KEY[..32], KeyType::MACKey).unwrap(); assert_eq!(key1.key_type(), KeyType::MACKey); assert_eq!(key1.security_strength(), SecurityStrength::_256bit); - + // success case: same size using default From impl; only works if the sizes are the same (ie the compiler knows that they are the same type. let key2 = KeyMaterial256::from(key1.clone()); assert_eq!(key1.key_len(), key2.key_len()); diff --git a/crypto/factory/src/lib.rs b/crypto/factory/src/lib.rs index 3f6d974..7c0a12b 100644 --- a/crypto/factory/src/lib.rs +++ b/crypto/factory/src/lib.rs @@ -25,7 +25,7 @@ //! It also exposes [AlgorithmFactory::new] which can be used to create an instance of the algorithm //! by string name according to the string constants associated with the respective factory type. -use bouncycastle_core::errors::{MACError}; +use bouncycastle_core::errors::MACError; pub mod hash_factory; pub mod kdf_factory; @@ -38,7 +38,6 @@ pub const DEFAULT: &str = "Default"; pub const DEFAULT_128_BIT: &str = "Default128Bit"; pub const DEFAULT_256_BIT: &str = "Default256Bit"; - #[derive(Debug)] pub enum FactoryError { MACError(MACError), @@ -52,7 +51,6 @@ impl From for FactoryError { } pub trait AlgorithmFactory: Sized + Default { - // Get the default configured algorithm. // Not implemented because all factories MUST impl Default. // fn default() -> Self; @@ -65,4 +63,4 @@ pub trait AlgorithmFactory: Sized + Default { /// Create an instance of the algorithm by name. fn new(alg_name: &str) -> Result; -} \ No newline at end of file +} diff --git a/crypto/factory/src/rng_factory.rs b/crypto/factory/src/rng_factory.rs index 89aa3e7..77a3231 100644 --- a/crypto/factory/src/rng_factory.rs +++ b/crypto/factory/src/rng_factory.rs @@ -41,11 +41,11 @@ //! let output: Vec = h.hash(data); //! ``` -use bouncycastle_core::errors::RNGError; -use bouncycastle_core::traits::{SecurityStrength, RNG}; -use bouncycastle_core::key_material::KeyMaterialTrait; use crate::{AlgorithmFactory, FactoryError}; use crate::{DEFAULT, DEFAULT_128_BIT, DEFAULT_256_BIT}; +use bouncycastle_core::errors::RNGError; +use bouncycastle_core::key_material::KeyMaterialTrait; +use bouncycastle_core::traits::{RNG, SecurityStrength}; use bouncycastle_rng as rng; use bouncycastle_rng::{HASH_DRBG_SHA256_NAME, HASH_DRBG_SHA512_NAME}; @@ -55,8 +55,6 @@ pub const DEFAULT_DRBG_NAME: &str = HASH_DRBG_SHA512_NAME; pub const DEFAULT_128BIT_DRBG_NAME: &str = HASH_DRBG_SHA256_NAME; pub const DEFAULT_256BIT_DRBG_NAME: &str = HASH_DRBG_SHA512_NAME; - - /// All members must impl RNG. pub enum RNGFactory { #[allow(non_camel_case_types)] @@ -66,12 +64,18 @@ pub enum RNGFactory { } impl Default for RNGFactory { - fn default() -> Self { Self::new(DEFAULT_DRBG_NAME).unwrap() } + fn default() -> Self { + Self::new(DEFAULT_DRBG_NAME).unwrap() + } } impl AlgorithmFactory for RNGFactory { - fn default_128_bit() -> Self { Self::new(DEFAULT_128BIT_DRBG_NAME).unwrap() } - fn default_256_bit() -> Self { Self::new(DEFAULT_256BIT_DRBG_NAME).unwrap() } + fn default_128_bit() -> Self { + Self::new(DEFAULT_128BIT_DRBG_NAME).unwrap() + } + fn default_256_bit() -> Self { + Self::new(DEFAULT_256BIT_DRBG_NAME).unwrap() + } fn new(alg_name: &str) -> Result { match alg_name { @@ -80,51 +84,57 @@ impl AlgorithmFactory for RNGFactory { DEFAULT_256_BIT => Ok(Self::default_256_bit()), HASH_DRBG_SHA256_NAME => Ok(Self::HashDRBG_SHA256(rng::HashDRBG_SHA256::new_from_os())), HASH_DRBG_SHA512_NAME => Ok(Self::HashDRBG_SHA512(rng::HashDRBG_SHA512::new_from_os())), - _ => Err(FactoryError::UnsupportedAlgorithm(format!("The algorithm: \"{}\" is not a known RNG", alg_name))), + _ => Err(FactoryError::UnsupportedAlgorithm(format!( + "The algorithm: \"{}\" is not a known RNG", + alg_name + ))), } } } impl RNG for RNGFactory { - fn add_seed_keymaterial(&mut self, additional_seed: impl KeyMaterialTrait) -> Result<(), RNGError> { + fn add_seed_keymaterial( + &mut self, + additional_seed: impl KeyMaterialTrait, + ) -> Result<(), RNGError> { match self { - Self::HashDRBG_SHA256(rng) => {rng.add_seed_keymaterial(additional_seed) }, - Self::HashDRBG_SHA512(rng) => { rng.add_seed_keymaterial(additional_seed) }, + Self::HashDRBG_SHA256(rng) => rng.add_seed_keymaterial(additional_seed), + Self::HashDRBG_SHA512(rng) => rng.add_seed_keymaterial(additional_seed), } } fn next_int(&mut self) -> Result { match self { - Self::HashDRBG_SHA256(rng) => {rng.next_int() }, - Self::HashDRBG_SHA512(rng) => { rng.next_int() }, + Self::HashDRBG_SHA256(rng) => rng.next_int(), + Self::HashDRBG_SHA512(rng) => rng.next_int(), } } fn next_bytes(&mut self, len: usize) -> Result, RNGError> { match self { - Self::HashDRBG_SHA256(rng) => {rng.next_bytes(len) }, - Self::HashDRBG_SHA512(rng) => { rng.next_bytes(len) }, + Self::HashDRBG_SHA256(rng) => rng.next_bytes(len), + Self::HashDRBG_SHA512(rng) => rng.next_bytes(len), } } fn next_bytes_out(&mut self, out: &mut [u8]) -> Result { match self { - Self::HashDRBG_SHA256(rng) => {rng.next_bytes_out(out) }, - Self::HashDRBG_SHA512(rng) => { rng.next_bytes_out(out) }, + Self::HashDRBG_SHA256(rng) => rng.next_bytes_out(out), + Self::HashDRBG_SHA512(rng) => rng.next_bytes_out(out), } } fn fill_keymaterial_out(&mut self, out: &mut impl KeyMaterialTrait) -> Result { match self { - Self::HashDRBG_SHA256(rng) => {rng.fill_keymaterial_out(out) }, - Self::HashDRBG_SHA512(rng) => { rng.fill_keymaterial_out(out) }, + Self::HashDRBG_SHA256(rng) => rng.fill_keymaterial_out(out), + Self::HashDRBG_SHA512(rng) => rng.fill_keymaterial_out(out), } } fn security_strength(&self) -> SecurityStrength { match self { - Self::HashDRBG_SHA256(rng) => {rng.security_strength() }, - Self::HashDRBG_SHA512(rng) => { rng.security_strength() }, + Self::HashDRBG_SHA256(rng) => rng.security_strength(), + Self::HashDRBG_SHA512(rng) => rng.security_strength(), } } } diff --git a/crypto/factory/tests/hash_factory_tests.rs b/crypto/factory/tests/hash_factory_tests.rs index 55221ee..6be8756 100644 --- a/crypto/factory/tests/hash_factory_tests.rs +++ b/crypto/factory/tests/hash_factory_tests.rs @@ -1,17 +1,17 @@ #[cfg(test)] mod hash_factory_tests { - use bouncycastle_factory::AlgorithmFactory; - use bouncycastle_factory::hash_factory::{HashFactory}; - use bouncycastle_factory::xof_factory::{XOFFactory}; use bouncycastle_core::traits::{Hash, XOF}; use bouncycastle_core_test_framework::DUMMY_SEED_512; + use bouncycastle_factory::AlgorithmFactory; + use bouncycastle_factory::hash_factory::HashFactory; + use bouncycastle_factory::xof_factory::XOFFactory; mod sha3_tests { use super::*; - use bouncycastle_sha2::SHA224; + use bouncycastle_factory as factory; use bouncycastle_sha2 as sha2; + use bouncycastle_sha2::SHA224; use bouncycastle_sha3 as sha3; - use bouncycastle_factory as factory; #[test] fn sha2_hash_tests() { @@ -20,7 +20,6 @@ mod hash_factory_tests { let h = SHA224::new(); h.hash(&DUMMY_SEED_512[..24]); - let sha2 = HashFactory::new("SHA224").unwrap(); assert_eq!(sha2.output_len(), 28); assert_eq!(sha2.hash(DUMMY_SEED_512), b"\xb8\x06\x0c\xcc\x82\xd4\x0c\x57\x61\x56\xf7\xca\x03\x33\xe4\x38\x9e\x41\x0d\xf0\x27\xd2\xfb\x8f\x76\x4f\xa6\x03"); @@ -29,7 +28,6 @@ mod hash_factory_tests { assert_eq!(sha2.output_len(), 28); assert_eq!(sha2.hash(DUMMY_SEED_512), b"\xb8\x06\x0c\xcc\x82\xd4\x0c\x57\x61\x56\xf7\xca\x03\x33\xe4\x38\x9e\x41\x0d\xf0\x27\xd2\xfb\x8f\x76\x4f\xa6\x03"); - // SHA256 let sha2 = HashFactory::new("SHA256").unwrap(); assert_eq!(sha2.output_len(), 32); @@ -69,7 +67,6 @@ mod hash_factory_tests { assert_eq!(sha3.output_len(), 28); assert_eq!(sha3.hash(DUMMY_SEED_512), b"\xFE\x51\xC5\xD7\x62\x48\xE1\xE9\xD3\x01\x29\x6A\xE8\xAB\x94\x69\xD2\x86\x34\xB4\xAD\x3E\x9E\x78\xC8\xB0\x9D\x47"); - // SHA3-256 let sha3 = HashFactory::new("SHA3-256").unwrap(); assert_eq!(sha3.output_len(), 32); @@ -102,7 +99,6 @@ mod hash_factory_tests { fn sha3_xof_tests() { assert_eq!(XOFFactory::new("SHAKE128").unwrap().hash_xof(DUMMY_SEED_512, 32), b"\x88\x90\xed\x20\x4d\x22\x89\xe1\x72\xe9\xae\x68\x48\x18\x23\x77\x08\x20\x90\x80\x60\xa4\xdf\x33\x51\xa3\xf1\x84\xeb\xb6\xdd\x0f"); assert_eq!(XOFFactory::new("SHAKE256").unwrap().hash_xof(DUMMY_SEED_512, 32), b"\xa1\xd7\x18\x85\xb0\xa8\x41\xf0\x3d\x1d\xc7\xf2\x73\x8a\x15\xcc\x98\x40\x71\xa1\x7f\xfe\xd5\xec\xac\xb9\xf5\x87\x20\xa4\x73\xbe"); - } #[test] @@ -147,4 +143,4 @@ mod hash_factory_tests { assert_ne!(out, vec![0u8; out.len()]); } } -} \ No newline at end of file +} diff --git a/crypto/factory/tests/kdf_factory_tests.rs b/crypto/factory/tests/kdf_factory_tests.rs index 5530d6b..16e6949 100644 --- a/crypto/factory/tests/kdf_factory_tests.rs +++ b/crypto/factory/tests/kdf_factory_tests.rs @@ -1,19 +1,22 @@ #[cfg(test)] mod kdf_factory_tests { - use bouncycastle_factory::AlgorithmFactory; - use bouncycastle_factory::kdf_factory::{KDFFactory}; - use bouncycastle_core::key_material::{KeyMaterial256, KeyMaterial512, KeyType, KeyMaterialTrait}; + use bouncycastle_core::key_material::{ + KeyMaterial256, KeyMaterial512, KeyMaterialTrait, KeyType, + }; use bouncycastle_core::traits::KDF; use bouncycastle_core_test_framework::DUMMY_SEED_512; - use bouncycastle_utils::ct; use bouncycastle_factory as factory; + use bouncycastle_factory::AlgorithmFactory; + use bouncycastle_factory::kdf_factory::KDFFactory; + use bouncycastle_utils::ct; #[test] fn sha3_kdf_tests() { let key_material = KeyMaterial256::from_bytes(&DUMMY_SEED_512[..32]).unwrap(); // SHA3_224 - let derived_key = KDFFactory::new("SHA3-224").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); + let derived_key = + KDFFactory::new("SHA3-224").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); let expected_key = KeyMaterial256::from_bytes(b"\xbf\xc9\xc1\xe8\x93\x9a\xee\x95\x3c\xa0\xd4\x25\xa2\xf0\xcb\xdd\x2d\x18\x02\x5d\x5d\x6b\x79\x8f\x1c\x81\x50\xb9").unwrap(); // assert_eq!(&derived_key, &expected_key); // assert!(KeyMaterialInternal::equals(&expected_key, derived_key.deref())); @@ -21,52 +24,59 @@ mod kdf_factory_tests { assert!(ct::ct_eq_bytes(derived_key.ref_to_bytes(), &expected_key.ref_to_bytes())); // SHA3_256 - let derived_key = KDFFactory::new("SHA3-256").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); + let derived_key = + KDFFactory::new("SHA3-256").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); let expected_key = KeyMaterial256::from_bytes(b"\x05\x0a\x48\x73\x3b\xd5\xc2\x75\x6b\xa9\x5c\x58\x28\xcc\x83\xee\x16\xfa\xbc\xd3\xc0\x86\x88\x5b\x77\x44\xf8\x4a\x0f\x9e\x0d\x94").unwrap(); // assert_eq!(&derived_key, &expected_key); assert!(ct::ct_eq_bytes(derived_key.ref_to_bytes(), &expected_key.ref_to_bytes())); // SHA3_384 - let derived_key = KDFFactory::new("SHA3-384").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); + let derived_key = + KDFFactory::new("SHA3-384").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); let expected_key = KeyMaterial512::from_bytes(b"\xe0\x86\xa2\xb6\xa6\x9b\xb6\xfa\xe3\x7c\xaa\x70\x73\x57\x23\xe7\xcc\x8a\xe2\x18\x37\x88\xfb\xb4\xa5\xf1\xcc\xac\xd8\x32\x26\x85\x2c\xa6\xfa\xff\x50\x3e\x12\xff\x95\x42\x3f\x94\xf8\x72\xdd\xa3").unwrap(); // assert_eq!(&derived_key, &expected_key); assert!(ct::ct_eq_bytes(derived_key.ref_to_bytes(), &expected_key.ref_to_bytes())); // SHA3_512 - let derived_key = KDFFactory::new("SHA3-512").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); + let derived_key = + KDFFactory::new("SHA3-512").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); let expected_key = KeyMaterial512::from_bytes(b"\xcb\xd3\xf6\xee\xba\x67\x6b\x21\xe0\xf2\xc4\x75\x22\x29\x24\x82\xfd\x83\x0f\x33\x0c\x1d\x84\xa7\x94\xbb\x94\x72\x8b\x2d\x93\xfe\xbe\x4c\x18\xea\xe5\xa7\xe0\x17\xe3\x5f\xa0\x90\xde\x24\x26\x2e\x70\x95\x1a\xd1\xd7\xdf\xb3\xa8\xc9\x6d\x11\x34\xfb\x18\x79\xf2").unwrap(); // assert_eq!(&derived_key, &expected_key); assert!(ct::ct_eq_bytes(derived_key.ref_to_bytes(), &expected_key.ref_to_bytes())); // SHAKE128 - let derived_key = KDFFactory::new("SHAKE128").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); + let derived_key = + KDFFactory::new("SHAKE128").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); let expected_key = KeyMaterial512::from_bytes(b"\x06\x6a\x36\x1d\xc6\x75\xf8\x56\xce\xcd\xc0\x2b\x25\x21\x8a\x10\xce\xc0\xce\xcf\x79\x85\x9e\xc0\xfe\xc3\xd4\x09\xe5\x84\x7a\x92").unwrap(); // assert_eq!(&derived_key, &expected_key); assert!(ct::ct_eq_bytes(derived_key.ref_to_bytes(), &expected_key.ref_to_bytes())); // SHAKE256 - let derived_key = KDFFactory::new("SHAKE256").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); + let derived_key = + KDFFactory::new("SHAKE256").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); let expected_key = KeyMaterial512::from_bytes(b"\x69\xf0\x7c\x88\x40\xce\x80\x02\x4d\xb3\x09\x39\x88\x2c\x3d\x5b\xbc\x9c\x98\xb3\xe3\x1e\x45\x13\xeb\xd2\xca\x9b\x45\x03\xcd\xd3\xc9\xc9\x07\x42\x45\x2c\x71\x73\xd4\xa7\x5a\xc4\x91\x63\xe1\x4e\xe0\xcc\x24\xef\x70\x35\xb2\x72\xd1\x9a\x7a\xf1\x09\x9b\x33\x3f").unwrap(); // assert_eq!(&derived_key, &expected_key); assert!(ct::ct_eq_bytes(derived_key.ref_to_bytes(), &expected_key.ref_to_bytes())); } - + #[test] fn hkdf_tests() { /* HKDF-SHA256 */ // Note: this value is not checked against any external reference implementation, // I just hard-coded the value to make sure it stays consistent. - let key_material = KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..32], KeyType::MACKey).unwrap(); - let derived_key = KDFFactory::new("HKDF-SHA256").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); + let key_material = + KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..32], KeyType::MACKey).unwrap(); + let derived_key = + KDFFactory::new("HKDF-SHA256").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); let expected_key = KeyMaterial256::from_bytes(b"\x37\xad\x29\x10\x9f\x43\x26\x52\x87\x80\x4b\x67\x4e\x26\x53\xd0\xa5\x13\x71\x89\x07\xf9\x7f\xca\x97\xc9\x5b\xde\xd8\x10\x4b\xbf").unwrap(); assert!(ct::ct_eq_bytes(derived_key.ref_to_bytes(), &expected_key.ref_to_bytes())); - /* HKDF-SHA512 */ // Note: this value is not checked against any external reference implementation, // I just hard-coded the value to make sure it stays consistent. let key_material = KeyMaterial512::from_bytes(&DUMMY_SEED_512[..64]).unwrap(); - let derived_key = KDFFactory::new("HKDF-SHA512").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); + let derived_key = + KDFFactory::new("HKDF-SHA512").unwrap().derive_key(&key_material, &[0u8; 0]).unwrap(); let expected_key = KeyMaterial512::from_bytes(b"\x8f\x5a\x29\x79\xfe\x16\x4d\x3a\x01\x72\x02\x32\x6c\x61\x97\xae\xa2\x58\x56\x3d\x90\x9b\x01\x20\x12\x1c\x37\x22\x6c\xb3\xd3\x68\xf4\x31\xf9\x79\x9d\x33\x8c\xe3\x0e\xfc\x5f\x41\xaf\xfc\x3d\x38\x54\x44\xa0\x65\xae\x80\x78\x60\x59\x45\x79\x50\xa1\xe6\x5e\x57").unwrap(); assert!(ct::ct_eq_bytes(derived_key.ref_to_bytes(), &expected_key.ref_to_bytes())); } @@ -87,14 +97,15 @@ mod kdf_factory_tests { let _ = KDFFactory::new("Default128Bit").unwrap().derive_key(&key, &[0u8; 0]).unwrap(); - let _ = KDFFactory::new(factory::DEFAULT_128_BIT).unwrap().derive_key(&key, &[0u8; 0]).unwrap(); - + let _ = + KDFFactory::new(factory::DEFAULT_128_BIT).unwrap().derive_key(&key, &[0u8; 0]).unwrap(); // All the ways to get "default_256_bit" let _ = KDFFactory::default_256_bit().derive_key(&key, &[0u8; 0]).unwrap(); let _ = KDFFactory::new("Default256Bit").unwrap().derive_key(&key, &[0u8; 0]).unwrap(); - let _ = KDFFactory::new(factory::DEFAULT_256_BIT).unwrap().derive_key(&key, &[0u8; 0]).unwrap(); + let _ = + KDFFactory::new(factory::DEFAULT_256_BIT).unwrap().derive_key(&key, &[0u8; 0]).unwrap(); } -} \ No newline at end of file +} diff --git a/crypto/factory/tests/mac_factory_tests.rs b/crypto/factory/tests/mac_factory_tests.rs index d4c04da..912a758 100644 --- a/crypto/factory/tests/mac_factory_tests.rs +++ b/crypto/factory/tests/mac_factory_tests.rs @@ -1,9 +1,9 @@ #[cfg(test)] mod hash_factory_tests { - use bouncycastle_hex as hex; - use bouncycastle_factory::mac_factory::{MACFactory}; - use bouncycastle_core::traits::{MAC}; use bouncycastle_core::key_material::{KeyMaterial, KeyType}; + use bouncycastle_core::traits::MAC; + use bouncycastle_factory::mac_factory::MACFactory; + use bouncycastle_hex as hex; mod sha3_tests { use super::*; @@ -14,7 +14,8 @@ mod hash_factory_tests { let key = KeyMaterial::<32>::from_bytes_as_type( &hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(), KeyType::MACKey, - ).unwrap(); + ) + .unwrap(); let hmac = MACFactory::new("HMAC-SHA224", &key).unwrap(); assert!(hmac.verify( b"Hi There", @@ -24,4 +25,4 @@ mod hash_factory_tests { // TODO: at least one test for each type } } -} \ No newline at end of file +} diff --git a/crypto/factory/tests/rng_factory_tests.rs b/crypto/factory/tests/rng_factory_tests.rs index eb7361d..6e5d253 100644 --- a/crypto/factory/tests/rng_factory_tests.rs +++ b/crypto/factory/tests/rng_factory_tests.rs @@ -1,8 +1,8 @@ #[cfg(test)] mod tests { - use bouncycastle_core::traits::{SecurityStrength, RNG}; - use bouncycastle_factory::AlgorithmFactory; + use bouncycastle_core::traits::{RNG, SecurityStrength}; use bouncycastle_factory as factory; + use bouncycastle_factory::AlgorithmFactory; #[test] fn test_defaults() { @@ -19,7 +19,6 @@ mod tests { let out = rng.next_bytes(10).unwrap(); assert_ne!(out, &[0u8; 10],); - // All the ways to get "default_128_bit" let mut rng = factory::rng_factory::RNGFactory::default_128_bit(); assert_eq!(rng.security_strength(), SecurityStrength::_128bit); @@ -36,7 +35,6 @@ mod tests { let out = rng.next_bytes(10).unwrap(); assert_ne!(out, &[0u8; 10],); - // All the ways to get "default_256_bit" let mut rng = factory::rng_factory::RNGFactory::default_256_bit(); assert_eq!(rng.security_strength(), SecurityStrength::_256bit); @@ -53,4 +51,4 @@ mod tests { let out = rng.next_bytes(10).unwrap(); assert_ne!(out, &[0u8; 10],); } -} \ No newline at end of file +} diff --git a/crypto/factory/tests/xof_factory_tests.rs b/crypto/factory/tests/xof_factory_tests.rs index 6ca613d..7e414f9 100644 --- a/crypto/factory/tests/xof_factory_tests.rs +++ b/crypto/factory/tests/xof_factory_tests.rs @@ -1,4 +1,4 @@ #[cfg(test)] mod tests { // todo -} \ No newline at end of file +} diff --git a/crypto/hex/benches/hex_benches.rs b/crypto/hex/benches/hex_benches.rs index ae7b369..6cd85a2 100644 --- a/crypto/hex/benches/hex_benches.rs +++ b/crypto/hex/benches/hex_benches.rs @@ -1,5 +1,5 @@ -use criterion::{Criterion, Throughput, criterion_group, criterion_main}; use bouncycastle_hex as hex; +use criterion::{Criterion, Throughput, criterion_group, criterion_main}; use std::hint::black_box; fn bench_hex_encode(c: &mut Criterion) { diff --git a/crypto/hkdf/benches/hkdf_benches.rs b/crypto/hkdf/benches/hkdf_benches.rs index 7c0134b..72e3d77 100644 --- a/crypto/hkdf/benches/hkdf_benches.rs +++ b/crypto/hkdf/benches/hkdf_benches.rs @@ -1,9 +1,11 @@ -use std::hint::black_box; -use criterion::{Criterion, Throughput, criterion_group, criterion_main}; -use bouncycastle_rng as rng; -use bouncycastle_core::key_material::{KeyMaterial256, KeyMaterial512, KeyMaterial, KeyType, KeyMaterialTrait}; +use bouncycastle_core::key_material::{ + KeyMaterial, KeyMaterial256, KeyMaterial512, KeyMaterialTrait, KeyType, +}; use bouncycastle_core::traits::RNG; use bouncycastle_hkdf::{HKDF_SHA256, HKDF_SHA512}; +use bouncycastle_rng as rng; +use criterion::{Criterion, Throughput, criterion_group, criterion_main}; +use std::hint::black_box; fn bench_hkdf_sha256(c: &mut Criterion) { let mut data_block = [0_u8; 1024]; @@ -57,11 +59,12 @@ fn bench_hkdf_sha256(c: &mut Criterion) { group.finish(); let mut group = c.benchmark_group("HKDF_SHA256::expand_out max output size (255*HashLen)"); - group.throughput(Throughput::Bytes(255*32u64)); - group.bench_function(format!("{} bytes of output key material", 255*32u64), |b| { + group.throughput(Throughput::Bytes(255 * 32u64)); + group.bench_function(format!("{} bytes of output key material", 255 * 32u64), |b| { let mut output_key = KeyMaterial::<8160>::new(); b.iter(|| { - HKDF_SHA256::extract_and_expand_out(&key, &key, &data_block, 255*32, &mut output_key).unwrap(); + HKDF_SHA256::extract_and_expand_out(&key, &key, &data_block, 255 * 32, &mut output_key) + .unwrap(); black_box(&output_key); }); }); @@ -120,18 +123,17 @@ fn bench_hkdf_sha512(c: &mut Criterion) { group.finish(); let mut group = c.benchmark_group("HKDF_SHA512::expand_out max output size (255*HashLen)"); - group.throughput(Throughput::Bytes(255*64u64)); - group.bench_function(format!("{} bytes of output key material", 255*64u64), |b| { + group.throughput(Throughput::Bytes(255 * 64u64)); + group.bench_function(format!("{} bytes of output key material", 255 * 64u64), |b| { let mut output_key = KeyMaterial::<16320>::new(); b.iter(|| { - HKDF_SHA512::extract_and_expand_out(&key, &key, &data_block, 255*64, &mut output_key).unwrap(); + HKDF_SHA512::extract_and_expand_out(&key, &key, &data_block, 255 * 64, &mut output_key) + .unwrap(); black_box(&output_key); }); }); group.finish(); } - - criterion_group!(benches, bench_hkdf_sha256, bench_hkdf_sha512); criterion_main!(benches); diff --git a/crypto/hkdf/src/lib.rs b/crypto/hkdf/src/lib.rs index e79139c..76b47f0 100644 --- a/crypto/hkdf/src/lib.rs +++ b/crypto/hkdf/src/lib.rs @@ -145,23 +145,23 @@ //! let _bytes_written = HKDF_SHA256::extract_and_expand_out(&salt, &ikm, info, 200, &mut okm).unwrap(); //! ``` - #![forbid(unsafe_code)] -use std::marker::PhantomData; use bouncycastle_core::errors::{KDFError, MACError}; -use bouncycastle_core::key_material::{KeyMaterial0, KeyMaterial512, KeyMaterial, KeyMaterialTrait, KeyType}; -use bouncycastle_core::traits::{Hash, KDF, MAC, HashAlgParams, SecurityStrength}; +use bouncycastle_core::key_material::{ + KeyMaterial, KeyMaterial0, KeyMaterial512, KeyMaterialTrait, KeyType, +}; +use bouncycastle_core::traits::{Hash, HashAlgParams, KDF, MAC, SecurityStrength}; use bouncycastle_hmac::HMAC; use bouncycastle_sha2::{SHA256, SHA512}; use bouncycastle_utils::{max, min}; +use std::marker::PhantomData; // Imports needed only for docs #[allow(unused_imports)] use bouncycastle_core::traits::XOF; // end doc-only imports - /*** Constants ***/ // Slightly hacky, but set this to accomodate the underlying hash primitive with the largest output size. // Would be better to somehow pull that at compile time from H, but I'm not sure how to do that. @@ -172,7 +172,6 @@ const HMAC_BLOCK_LEN: usize = 64; pub const HKDF_SHA256_NAME: &str = "HKDF-SHA256"; pub const HKDF_SHA512_NAME: &str = "HKDF-SHA512"; - /*** Types ***/ #[allow(non_camel_case_types)] pub type HKDF_SHA256 = HKDF; @@ -180,9 +179,9 @@ pub type HKDF_SHA256 = HKDF; pub type HKDF_SHA512 = HKDF; pub struct HKDF { - hmac: Option>, // Optional because we can't construct an HMAC until they give us a key - // to initialize it with. - // None should correspond to a state of Uninitialized. + hmac: Option>, // Optional because we can't construct an HMAC until they give us a key + // to initialize it with. + // None should correspond to a state of Uninitialized. entropy: HkdfEntropyTracker, state: HkdfStates, } @@ -209,7 +208,9 @@ struct HkdfEntropyTracker { } impl HkdfEntropyTracker { - fn new() -> Self { Self { _phantomhash: PhantomData, entropy: 0, security_strength: SecurityStrength::None } } + fn new() -> Self { + Self { _phantomhash: PhantomData, entropy: 0, security_strength: SecurityStrength::None } + } /// Takes in a KeyMaterial that is being mixed and figures out how much entropy to credit. /// Returns the amount of entropy credited. @@ -217,7 +218,8 @@ impl HkdfEntropyTracker { let additional_entropy = if key.is_full_entropy() { key.key_len() } else { 0 }; self.entropy += additional_entropy; self.security_strength = max(&self.security_strength, &key.security_strength()).clone(); - self.security_strength = min(&self.security_strength, &SecurityStrength::from_bytes(H::OUTPUT_LEN/2)).clone(); + self.security_strength = + min(&self.security_strength, &SecurityStrength::from_bytes(H::OUTPUT_LEN / 2)).clone(); additional_entropy } @@ -233,11 +235,7 @@ impl HkdfEntropyTracker { /// Either [KeyMaterialTrait::BytesLowEntropy] or [KeyMaterialTrait::BytesFullEntropy] depending on /// whether enough input key material was provided for the internal hash function to have a full block. fn get_output_key_type(&self) -> KeyType { - if self.is_fully_seeded() { - KeyType::BytesFullEntropy - } else { - KeyType::BytesLowEntropy - } + if self.is_fully_seeded() { KeyType::BytesFullEntropy } else { KeyType::BytesLowEntropy } } } @@ -249,7 +247,11 @@ fn test_entropy_tracker() { assert_eq!(entropy.get_entropy(), 0); assert_eq!(entropy.get_output_key_type(), KeyType::BytesLowEntropy); - let key = KeyMaterial512::from_bytes_as_type(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", KeyType::BytesFullEntropy).unwrap(); + let key = KeyMaterial512::from_bytes_as_type( + b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + KeyType::BytesFullEntropy, + ) + .unwrap(); entropy.credit_entropy(&key); assert_eq!(entropy.get_entropy(), 16); assert_eq!(entropy.is_fully_seeded(), false); @@ -399,7 +401,8 @@ impl HKDF { // Could potentially speed this up by unrolling T(0) and T(1) // We're gonna have to kludge the prk key type to MACKey to make HMAC happy, but we'll set it back to the original value afterwards. - let prk_as_mac_key = KeyMaterial::::from_bytes_as_type(prk.ref_to_bytes(), KeyType::MACKey)?; + let prk_as_mac_key = + KeyMaterial::::from_bytes_as_type(prk.ref_to_bytes(), KeyType::MACKey)?; #[allow(non_snake_case)] let mut T = [0u8; HMAC_BLOCK_LEN]; @@ -443,7 +446,10 @@ impl HKDF { if okm.key_type() <= KeyType::BytesLowEntropy { okm.set_security_strength(SecurityStrength::None)?; } else { - okm.set_security_strength(min(&SecurityStrength::from_bytes(okm.key_len()), &entropy.security_strength).clone())?; + okm.set_security_strength( + min(&SecurityStrength::from_bytes(okm.key_len()), &entropy.security_strength) + .clone(), + )?; } okm.drop_hazardous_operations(); Ok(bytes_written) @@ -497,7 +503,10 @@ impl HKDF { /// In particular, this function may be called multiple times to add more than one IKM. /// /// Returns the number of bits of entropy credited to this input key material. - pub fn do_extract_update_key(&mut self, ikm: &impl KeyMaterialTrait) -> Result { + pub fn do_extract_update_key( + &mut self, + ikm: &impl KeyMaterialTrait, + ) -> Result { if self.state == HkdfStates::Uninitialized { return Err(MACError::InvalidState( "Must call do_extract_init() before calling do_extract_update_key()", @@ -559,14 +568,18 @@ impl HKDF { let output_key_type = self.entropy.get_output_key_type(); // need to do this above self.hmac.do_final_out, which will consume self. - okm.allow_hazardous_operations(); // doing it here to get mut_ref_to_bytes - let bytes_written = self.hmac.unwrap().do_final_out(&mut okm.mut_ref_to_bytes().unwrap())?; + okm.allow_hazardous_operations(); // doing it here to get mut_ref_to_bytes + let bytes_written = + self.hmac.unwrap().do_final_out(&mut okm.mut_ref_to_bytes().unwrap())?; okm.set_key_len(bytes_written)?; okm.set_key_type(output_key_type)?; if output_key_type <= KeyType::BytesLowEntropy { okm.set_security_strength(SecurityStrength::None)?; } else { - okm.set_security_strength(min(&SecurityStrength::from_bytes(okm.key_len()), &self.entropy.security_strength).clone())?; + okm.set_security_strength( + min(&SecurityStrength::from_bytes(okm.key_len()), &self.entropy.security_strength) + .clone(), + )?; } okm.drop_hazardous_operations(); Ok(bytes_written) @@ -604,7 +617,13 @@ impl KDF for HKDF { additional_input: &[u8], output_key: &mut impl KeyMaterialTrait, ) -> Result { - let bytes_written = HKDF::::extract_and_expand_out(&KeyMaterial::<0>::new(), key, additional_input, output_key.capacity(), output_key)?; + let bytes_written = HKDF::::extract_and_expand_out( + &KeyMaterial::<0>::new(), + key, + additional_input, + output_key.capacity(), + output_key, + )?; Ok(bytes_written) } @@ -628,7 +647,6 @@ impl KDF for HKDF { Ok(Box::new(output_key)) } - /// This behaves the same as [KDF::derive_key_from_multiple], except that it fills the provided /// [KeyMaterialTrait] object in place of exposing a Length parameter. fn derive_key_from_multiple_out( @@ -655,11 +673,15 @@ impl KDF for HKDF { } let mut prk = KeyMaterial::::new(); _ = hkdf.do_extract_final_out(&mut prk)?; - let bytes_written = HKDF::::expand_out(&prk, additional_input, output_key.capacity(), output_key)?; + let bytes_written = + HKDF::::expand_out(&prk, additional_input, output_key.capacity(), output_key)?; output_key.allow_hazardous_operations(); output_key.set_key_type(entropy.get_output_key_type())?; - output_key.set_security_strength(min(&SecurityStrength::from_bytes(output_key.key_len()), &entropy.security_strength).clone())?; + output_key.set_security_strength( + min(&SecurityStrength::from_bytes(output_key.key_len()), &entropy.security_strength) + .clone(), + )?; output_key.drop_hazardous_operations(); Ok(bytes_written) diff --git a/crypto/hkdf/tests/hkdf_tests.rs b/crypto/hkdf/tests/hkdf_tests.rs index e30fccf..1e13d37 100644 --- a/crypto/hkdf/tests/hkdf_tests.rs +++ b/crypto/hkdf/tests/hkdf_tests.rs @@ -1,19 +1,23 @@ #[cfg(test)] mod hkdf_tests { use bouncycastle_core::errors::{KDFError, KeyMaterialError, MACError}; - use bouncycastle_core::key_material::{KeyMaterial0, KeyMaterial128, KeyMaterial256, KeyMaterial512, KeyMaterial, KeyType, KeyMaterialTrait}; - use bouncycastle_core::traits::{HashAlgParams, SecurityStrength, KDF}; + use bouncycastle_core::key_material::{ + KeyMaterial, KeyMaterial0, KeyMaterial128, KeyMaterial256, KeyMaterial512, + KeyMaterialTrait, KeyType, + }; + use bouncycastle_core::traits::{HashAlgParams, KDF, SecurityStrength}; use bouncycastle_core_test_framework::DUMMY_SEED_512; use bouncycastle_core_test_framework::kdf::TestFrameworkKDF; use bouncycastle_hex as hex; use bouncycastle_hkdf::{HKDF, HKDF_SHA256, HKDF_SHA512}; - use bouncycastle_sha2::{SHA256}; + use bouncycastle_sha2::SHA256; use bouncycastle_utils::ct; #[test] fn test_streaming_apis() { // setup variables - let salt = KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[..16], KeyType::MACKey).unwrap(); + let salt = + KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[..16], KeyType::MACKey).unwrap(); let ikm = KeyMaterial256::from_bytes(&DUMMY_SEED_512[16..48]).unwrap(); let info = &DUMMY_SEED_512[48..64]; let mut okm = KeyMaterial512::new(); @@ -41,14 +45,23 @@ mod hkdf_tests { let info: &[u8] = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\0xF"; let zero_key = KeyMaterial0::new(); - let key1 = KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..32], KeyType::MACKey).unwrap(); - let key2 = KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[32..64], KeyType::MACKey).unwrap(); - let key3 = KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[64..96], KeyType::MACKey).unwrap(); - + let key1 = + KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..32], KeyType::MACKey).unwrap(); + let key2 = + KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[32..64], KeyType::MACKey).unwrap(); + let key3 = + KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[64..96], KeyType::MACKey).unwrap(); /* test case: 0 input keys (ie empty salt and no ikm's) */ let mut expected_okm = KeyMaterial512::new(); - HKDF_SHA256::extract_and_expand_out(&KeyMaterial256::new(), &KeyMaterial0::new(), info, 32, &mut expected_okm).unwrap(); + HKDF_SHA256::extract_and_expand_out( + &KeyMaterial256::new(), + &KeyMaterial0::new(), + info, + 32, + &mut expected_okm, + ) + .unwrap(); let okm1 = HKDF_SHA256::new().derive_key(&zero_key, info).unwrap(); assert_eq!(okm1.ref_to_bytes(), expected_okm.ref_to_bytes()); @@ -58,13 +71,18 @@ mod hkdf_tests { let okm2 = HKDF_SHA256::new().derive_key_from_multiple(&keys, info).unwrap(); assert!(ct::ct_eq_bytes(okm2.ref_to_bytes(), expected_okm.ref_to_bytes())); - - /* test case: 1 input ikm key (ie empty salt) */ // derive_key_from_multiple(&[&KeyMaterial0, &key) is equivalent to derive_key(&key) above // which is equivalent to extract_and_expand((&KeyMaterial0::new(), &key, info) let mut expected_okm = KeyMaterial512::new(); - HKDF_SHA256::extract_and_expand_out(&KeyMaterial0::new(), &key1, info, 32, &mut expected_okm).unwrap(); + HKDF_SHA256::extract_and_expand_out( + &KeyMaterial0::new(), + &key1, + info, + 32, + &mut expected_okm, + ) + .unwrap(); let okm1 = HKDF_SHA256::new().derive_key(&key1, info).unwrap(); assert!(ct::ct_eq_bytes(okm1.ref_to_bytes(), expected_okm.ref_to_bytes())); @@ -73,7 +91,6 @@ mod hkdf_tests { let okm2 = HKDF_SHA256::new().derive_key_from_multiple(&keys, info).unwrap(); assert!(ct::ct_eq_bytes(okm2.ref_to_bytes(), expected_okm.ref_to_bytes())); - /* test case: 1 input keys (salt and no ikm's) */ let mut expected_okm = KeyMaterial512::new(); HKDF_SHA256::extract_and_expand_out(&key1, &zero_key, info, 32, &mut expected_okm).unwrap(); @@ -84,7 +101,6 @@ mod hkdf_tests { let okm2 = HKDF_SHA256::new().derive_key_from_multiple(&keys, info).unwrap(); assert!(ct::ct_eq_bytes(okm2.ref_to_bytes(), expected_okm.ref_to_bytes())); - /* test case: 2 input keys (ie salt and one ikm) */ let mut expected_okm = KeyMaterial512::new(); HKDF_SHA256::extract_and_expand_out(&key1, &key2, info, 32, &mut expected_okm).unwrap(); @@ -95,9 +111,9 @@ mod hkdf_tests { let okm2 = HKDF_SHA256::new().derive_key_from_multiple(&keys, info).unwrap(); assert!(ct::ct_eq_bytes(okm2.ref_to_bytes(), expected_okm.ref_to_bytes())); - /* test case: 3 input keys (ie salt and two ikm's) */ - let key23 = KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[32..96], KeyType::MACKey).unwrap(); + let key23 = + KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[32..96], KeyType::MACKey).unwrap(); let mut expected_okm = KeyMaterial512::new(); HKDF_SHA256::extract_and_expand_out(&key1, &key23, info, 32, &mut expected_okm).unwrap(); @@ -110,11 +126,13 @@ mod hkdf_tests { #[test] fn test_entropy_tracking() { - // test the thresholds of HMAC-SHA256 - let key255 = KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..31], KeyType::MACKey).unwrap(); - let key256 = KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..32], KeyType::MACKey).unwrap(); - let key512 = KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[..64], KeyType::MACKey).unwrap(); + let key255 = + KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..31], KeyType::MACKey).unwrap(); + let key256 = + KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..32], KeyType::MACKey).unwrap(); + let key512 = + KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[..64], KeyType::MACKey).unwrap(); let zero_key = KeyMaterial0::new(); // not enough @@ -142,10 +160,11 @@ mod hkdf_tests { _ = HKDF_SHA256::extract_and_expand_out(&key256, &zero_key, &[], 32, &mut okm).unwrap(); assert_eq!(okm.key_type(), KeyType::BytesFullEntropy); - // test the thresholds of HMAC-SHA512 - let key511 = KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[..63], KeyType::MACKey).unwrap(); - let key512 = KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[..64], KeyType::MACKey).unwrap(); + let key511 = + KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[..63], KeyType::MACKey).unwrap(); + let key512 = + KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[..64], KeyType::MACKey).unwrap(); let zero_key = KeyMaterial0::new(); // not enough @@ -160,48 +179,87 @@ mod hkdf_tests { _ = HKDF_SHA512::extract_and_expand_out(&key512, &zero_key, &[], 32, &mut okm).unwrap(); assert_eq!(okm.key_type(), KeyType::BytesFullEntropy); - - // variable setup - let low_entropy_key = KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..32], KeyType::BytesLowEntropy).unwrap(); + let low_entropy_key = + KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..32], KeyType::BytesLowEntropy) + .unwrap(); let mut okm = KeyMaterial256::new(); - // failure case: should complain if low entropy bytes are provided // only as salt - match HKDF_SHA256::extract_and_expand_out(&low_entropy_key, &KeyMaterial0::new(), &[], 32, &mut okm) { - Ok(_) => { panic!("Should have thrown a KeyMaterialError"); }, - Err(KDFError::MACError(MACError::KeyMaterialError(KeyMaterialError::InvalidKeyType(_)))) => { /* good */ }, - Err(_) => { panic!("Should have thrown a KeyMaterialError"); } + match HKDF_SHA256::extract_and_expand_out( + &low_entropy_key, + &KeyMaterial0::new(), + &[], + 32, + &mut okm, + ) { + Ok(_) => { + panic!("Should have thrown a KeyMaterialError"); + } + Err(KDFError::MACError(MACError::KeyMaterialError( + KeyMaterialError::InvalidKeyType(_), + ))) => { /* good */ } + Err(_) => { + panic!("Should have thrown a KeyMaterialError"); + } }; let keys = [&low_entropy_key]; match HKDF_SHA256::new().derive_key_from_multiple(&keys, &[]) { - Ok(_) => { panic!("Should have thrown a KeyMaterialError"); }, - Err(KDFError::MACError(MACError::KeyMaterialError(KeyMaterialError::InvalidKeyType(_)))) => { /* good */ }, - Err(_) => { panic!("Should have thrown a KeyMaterialError"); } + Ok(_) => { + panic!("Should have thrown a KeyMaterialError"); + } + Err(KDFError::MACError(MACError::KeyMaterialError( + KeyMaterialError::InvalidKeyType(_), + ))) => { /* good */ } + Err(_) => { + panic!("Should have thrown a KeyMaterialError"); + } }; - // as both salt and ikm - match HKDF_SHA256::extract_and_expand_out(&low_entropy_key, &low_entropy_key, &[], 32, &mut okm) { - Ok(_) => { panic!("Should have thrown a KeyMaterialError"); }, - Err(KDFError::MACError(MACError::KeyMaterialError(KeyMaterialError::InvalidKeyType(_)))) => { /* good */ }, - Err(_) => { panic!("Should have thrown a KeyMaterialError"); } + match HKDF_SHA256::extract_and_expand_out( + &low_entropy_key, + &low_entropy_key, + &[], + 32, + &mut okm, + ) { + Ok(_) => { + panic!("Should have thrown a KeyMaterialError"); + } + Err(KDFError::MACError(MACError::KeyMaterialError( + KeyMaterialError::InvalidKeyType(_), + ))) => { /* good */ } + Err(_) => { + panic!("Should have thrown a KeyMaterialError"); + } }; let keys = [&low_entropy_key, &low_entropy_key]; match HKDF_SHA256::new().derive_key_from_multiple(&keys, &[]) { - Ok(_) => { panic!("Should have thrown a KeyMaterialError"); }, - Err(KDFError::MACError(MACError::KeyMaterialError(KeyMaterialError::InvalidKeyType(_)))) => { /* good */ }, - Err(_) => { panic!("Should have thrown a KeyMaterialError"); } + Ok(_) => { + panic!("Should have thrown a KeyMaterialError"); + } + Err(KDFError::MACError(MACError::KeyMaterialError( + KeyMaterialError::InvalidKeyType(_), + ))) => { /* good */ } + Err(_) => { + panic!("Should have thrown a KeyMaterialError"); + } }; - - // zero-length salt is allowed -- zeroized ikm - _ = HKDF_SHA256::extract_and_expand_out(&KeyMaterial0::new(), &KeyMaterial0::new(), &[], 32, &mut okm).unwrap(); + _ = HKDF_SHA256::extract_and_expand_out( + &KeyMaterial0::new(), + &KeyMaterial0::new(), + &[], + 32, + &mut okm, + ) + .unwrap(); // okm should be tracked as LowEntropy assert_eq!(okm.key_type(), KeyType::BytesLowEntropy); @@ -214,9 +272,15 @@ mod hkdf_tests { // okm should be tracked as LowEntropy assert_eq!(okm.key_type(), KeyType::BytesLowEntropy); - // zero-length salt is allowed -- low entropy ikm - _ = HKDF_SHA256::extract_and_expand_out(&KeyMaterial0::new(), &low_entropy_key, &[], 32, &mut okm).unwrap(); + _ = HKDF_SHA256::extract_and_expand_out( + &KeyMaterial0::new(), + &low_entropy_key, + &[], + 32, + &mut okm, + ) + .unwrap(); // okm should be tracked as LowEntropy assert_eq!(okm.key_type(), KeyType::BytesLowEntropy); @@ -229,17 +293,25 @@ mod hkdf_tests { // okm should be tracked as LowEntropy assert_eq!(okm.key_type(), KeyType::BytesLowEntropy); - - // salt and ikm are full-entropy, but not enough to seed the HKDF, according to FIPS // first, error case; not a MACKey - let salt = KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[..8], KeyType::BytesFullEntropy).unwrap(); - let ikm = KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[8..16], KeyType::BytesFullEntropy).unwrap(); + let salt = + KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[..8], KeyType::BytesFullEntropy) + .unwrap(); + let ikm = + KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[8..16], KeyType::BytesFullEntropy) + .unwrap(); match HKDF_SHA256::extract_and_expand_out(&salt, &ikm, &[], 32, &mut okm) { - Ok(_) => { panic!("Should have thrown a KeyMaterialError that you didn't give it a MACKey"); }, - Err(KDFError::MACError(MACError::KeyMaterialError(KeyMaterialError::InvalidKeyType(_)))) => { /* good */ }, - Err(_) => { panic!("Should have thrown a KeyMaterialError that you didn't give it a MACKey"); } + Ok(_) => { + panic!("Should have thrown a KeyMaterialError that you didn't give it a MACKey"); + } + Err(KDFError::MACError(MACError::KeyMaterialError( + KeyMaterialError::InvalidKeyType(_), + ))) => { /* good */ } + Err(_) => { + panic!("Should have thrown a KeyMaterialError that you didn't give it a MACKey"); + } }; // derive_key has a different behaviour here, since it hard-codes a zero salt as the HMAC key, which is valid, @@ -249,15 +321,23 @@ mod hkdf_tests { let keys = [&salt, &ikm]; match HKDF_SHA256::new().derive_key_from_multiple_out(&keys, &[], &mut okm) { - Ok(_) => { panic!("Should have thrown a KeyMaterialError that you didn't give it a MACKey"); }, - Err(KDFError::MACError(MACError::KeyMaterialError(KeyMaterialError::InvalidKeyType(_)))) => { /* good */ }, - Err(_) => { panic!("Should have thrown a KeyMaterialError that you didn't give it a MACKey"); } + Ok(_) => { + panic!("Should have thrown a KeyMaterialError that you didn't give it a MACKey"); + } + Err(KDFError::MACError(MACError::KeyMaterialError( + KeyMaterialError::InvalidKeyType(_), + ))) => { /* good */ } + Err(_) => { + panic!("Should have thrown a KeyMaterialError that you didn't give it a MACKey"); + } }; - // success case -- insufficient entropy returns KeyType::BytesLowEntropy - let salt = KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[..8], KeyType::MACKey).unwrap(); - let ikm = KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[8..16], KeyType::BytesFullEntropy).unwrap(); + let salt = + KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[..8], KeyType::MACKey).unwrap(); + let ikm = + KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[8..16], KeyType::BytesFullEntropy) + .unwrap(); _ = HKDF_SHA256::extract_and_expand_out(&salt, &ikm, &[], 32, &mut okm); assert_eq!(okm.key_type(), KeyType::BytesLowEntropy); @@ -269,18 +349,20 @@ mod hkdf_tests { _ = HKDF_SHA256::new().derive_key_from_multiple_out(&keys, &[], &mut okm); assert_eq!(okm.key_type(), KeyType::BytesLowEntropy); - - // success case -- sufficient entropy returns the highest input key type -- KeyType::BytesFullEntropy // Note that FIPS requires it to be seeded to a full internal block (which is, for example 512 bits for SHA256) // Note: will still return BytesFullEntropy because that one was first in the inputs. - let salt = KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..32], KeyType::MACKey).unwrap(); - let ikm = KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[32..64], KeyType::BytesFullEntropy).unwrap(); + let salt = + KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..32], KeyType::MACKey).unwrap(); + let ikm = + KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[32..64], KeyType::BytesFullEntropy) + .unwrap(); _ = HKDF_SHA256::extract_and_expand_out(&salt, &ikm, &[], 32, &mut okm); assert_eq!(okm.key_type(), KeyType::BytesFullEntropy); - let salt1 = KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[..64], KeyType::MACKey).unwrap(); + let salt1 = + KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[..64], KeyType::MACKey).unwrap(); _ = HKDF_SHA256::new().derive_key_out(&salt1, &[], &mut okm); assert_eq!(okm.key_type(), KeyType::BytesFullEntropy); @@ -288,11 +370,13 @@ mod hkdf_tests { _ = HKDF_SHA256::new().derive_key_from_multiple_out(&keys, &[], &mut okm); assert_eq!(okm.key_type(), KeyType::BytesFullEntropy); - // success case -- insufficient entropy due to key types -- KeyType::BytesLowEntropy // Note: will still return MACKey because that one was first in the inputs. - let salt = KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[..16], KeyType::MACKey).unwrap(); - let ikm = KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[16..32], KeyType::BytesLowEntropy).unwrap(); + let salt = + KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[..16], KeyType::MACKey).unwrap(); + let ikm = + KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[16..32], KeyType::BytesLowEntropy) + .unwrap(); _ = HKDF_SHA256::extract_and_expand_out(&salt, &ikm, &[], 32, &mut okm); assert_eq!(okm.key_type(), KeyType::BytesLowEntropy); @@ -303,13 +387,18 @@ mod hkdf_tests { _ = HKDF_SHA256::new().derive_key_from_multiple_out(&keys, &[], &mut okm); assert_eq!(okm.key_type(), KeyType::BytesLowEntropy); - /* get_entropy */ // This requires using the stateful streaming API and check the amount of entropy it tracks after each addition. - let salt16 = KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[..16], KeyType::MACKey).unwrap(); - let salt64 = KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[..64], KeyType::MACKey).unwrap(); - let low_entropy_key16 = KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[..16], KeyType::BytesLowEntropy).unwrap(); - let full_entropy_key16 = KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[16..32], KeyType::BytesFullEntropy).unwrap(); + let salt16 = + KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[..16], KeyType::MACKey).unwrap(); + let salt64 = + KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[..64], KeyType::MACKey).unwrap(); + let low_entropy_key16 = + KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[..16], KeyType::BytesLowEntropy) + .unwrap(); + let full_entropy_key16 = + KeyMaterial128::from_bytes_as_type(&DUMMY_SEED_512[16..32], KeyType::BytesFullEntropy) + .unwrap(); // can't test with a low entropy salt because the salt has to be full entropy or zero. // but can test with a zeroized key @@ -359,21 +448,44 @@ mod hkdf_tests { // success case: large but not over-limit let mut mega_huge_key = KeyMaterial::<8100>::new(); assert!(mega_huge_key.capacity() < 255 * hash_len); - _ = HKDF_SHA256::extract_and_expand_out(&KeyMaterial0::new(), &KeyMaterial0::new(), &[], 8100, &mut mega_huge_key).unwrap(); + _ = HKDF_SHA256::extract_and_expand_out( + &KeyMaterial0::new(), + &KeyMaterial0::new(), + &[], + 8100, + &mut mega_huge_key, + ) + .unwrap(); // test exactly the capacity let mut mega_huge_key = KeyMaterial::<8160>::new(); assert_eq!(mega_huge_key.capacity(), 255 * hash_len); - _ = HKDF_SHA256::extract_and_expand_out(&KeyMaterial0::new(), &KeyMaterial0::new(), &[], 8160, &mut mega_huge_key).unwrap(); - + _ = HKDF_SHA256::extract_and_expand_out( + &KeyMaterial0::new(), + &KeyMaterial0::new(), + &[], + 8160, + &mut mega_huge_key, + ) + .unwrap(); // failure case let mut mega_huge_key = KeyMaterial::<8192>::new(); assert!(mega_huge_key.capacity() > 255 * hash_len); - match HKDF_SHA256::extract_and_expand_out(&KeyMaterial0::new(), &KeyMaterial0::new(), &[], 8192, &mut mega_huge_key) { - Ok(_) => { panic!("Should have thrown a KeyMaterialError"); }, - Err(KDFError::InvalidLength(_)) => { /* good */ }, - Err(_) => { panic!("Should have thrown a KeyMaterialError"); } + match HKDF_SHA256::extract_and_expand_out( + &KeyMaterial0::new(), + &KeyMaterial0::new(), + &[], + 8192, + &mut mega_huge_key, + ) { + Ok(_) => { + panic!("Should have thrown a KeyMaterialError"); + } + Err(KDFError::InvalidLength(_)) => { /* good */ } + Err(_) => { + panic!("Should have thrown a KeyMaterialError"); + } }; } @@ -452,9 +564,10 @@ mod hkdf_tests { Ok(_) => { assert_eq!(okm_key.ref_to_bytes().len(), L); assert_eq!(okm_key.ref_to_bytes(), hex::decode(okm).unwrap()); - }, - Err(KDFError::KeyMaterialError(_)) => { /* some of the rfc5896 test vectors are in fact low entropy, so just skip */ }, - Err(_) => panic!("Should have returned a MACError::KeyMaterialError.") + } + Err(KDFError::KeyMaterialError(_)) => { /* some of the rfc5896 test vectors are in fact low entropy, so just skip */ + } + Err(_) => panic!("Should have returned a MACError::KeyMaterialError."), } /*** with the streaming APIs ... do_extract_final() ***/ @@ -487,7 +600,8 @@ mod hkdf_tests { #[test] fn hkdf_state_tests() { // setup - let key = KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..32], KeyType::MACKey).unwrap(); + let key = + KeyMaterial256::from_bytes_as_type(&DUMMY_SEED_512[..32], KeyType::MACKey).unwrap(); // error case: try to initialize twice let mut hkdf = HKDF_SHA256::new(); @@ -565,7 +679,7 @@ mod hkdf_tests { * "dkm":"1f6f7381c72f1d46d83e819bedeb482944adb0e3352cf2718e4bd334d95699e7256d01a48f35016f807bc1b739d41f5d53e442c67f6b455776d50d8667d62b3f3b632c5a88c371f7229a4c88beea1f28752a95fb2c533af28e6bfb19e69d750bbadc6609b2715dac19de9d9a6cfe3472a5e5312eabfd9bdbfa222cc7046ce3f7" * } * - **/ + **/ // SP800-56Cr2 tcId 1 let mut salt = KeyMaterial::<128>::new(); // have to do it this way for it to accept a zeroized key @@ -578,16 +692,25 @@ mod hkdf_tests { // info = uPartyInfo||vPartyInfo||i32(l) let mut additional_input: Vec = Vec::::new(); - /*fixedInfoPartyU*/additional_input.append(&mut hex::decode("338D1F2A8B222598565C798886E7B35B6D4BD5DD3018C899548C52A40A5A5EE82A93FF7F50E8BE7ADCF0DAA15B90CD292F5D14F905A3CA036D47A62F37C140954AE90CCDA9E4E08145DB80FA1B36E1FABC89664AF0A8D13761A963316A04565DEAF5D73C8B89B295A804A2D7DA2BADD178").unwrap()); - /*fixedInfoPartyV*/additional_input.append(&mut hex::decode("03EEF6BD71BCE550BBA98D7C0080B582").unwrap()); - /*L*/additional_input.append(&mut hex::decode("00000400").unwrap()); + /*fixedInfoPartyU*/ + additional_input.append(&mut hex::decode("338D1F2A8B222598565C798886E7B35B6D4BD5DD3018C899548C52A40A5A5EE82A93FF7F50E8BE7ADCF0DAA15B90CD292F5D14F905A3CA036D47A62F37C140954AE90CCDA9E4E08145DB80FA1B36E1FABC89664AF0A8D13761A963316A04565DEAF5D73C8B89B295A804A2D7DA2BADD178").unwrap()); + /*fixedInfoPartyV*/ + additional_input.append(&mut hex::decode("03EEF6BD71BCE550BBA98D7C0080B582").unwrap()); + /*L*/ + additional_input.append(&mut hex::decode("00000400").unwrap()); let mut expected_key = KeyMaterial::<128>::from_bytes_as_type(&hex::decode("1f6f7381c72f1d46d83e819bedeb482944adb0e3352cf2718e4bd334d95699e7256d01a48f35016f807bc1b739d41f5d53e442c67f6b455776d50d8667d62b3f3b632c5a88c371f7229a4c88beea1f28752a95fb2c533af28e6bfb19e69d750bbadc6609b2715dac19de9d9a6cfe3472a5e5312eabfd9bdbfa222cc7046ce3f7").unwrap(), KeyType::MACKey).unwrap(); - // do it manually just to check that we have the test vector right. let mut output_key = KeyMaterial::<128>::new(); - let bytes_written = HKDF::::extract_and_expand_out(&salt, &ikm, additional_input.as_slice(), 128, &mut output_key).unwrap(); + let bytes_written = HKDF::::extract_and_expand_out( + &salt, + &ikm, + additional_input.as_slice(), + 128, + &mut output_key, + ) + .unwrap(); assert_eq!(bytes_written, 128); assert_eq!(output_key.ref_to_bytes(), expected_key.ref_to_bytes()); @@ -599,9 +722,14 @@ mod hkdf_tests { expected_key_truncated.truncate(output_key.key_len()).unwrap(); assert_eq!(output_key.ref_to_bytes(), expected_key_truncated.ref_to_bytes()); - testframework.test_kdf_single_key::>(&ikm, &additional_input, &expected_key_truncated); + testframework + .test_kdf_single_key::>(&ikm, &additional_input, &expected_key_truncated); let keys = [&salt, &ikm]; - testframework.test_kdf_multiple_key::>(&keys, additional_input.as_slice(), &mut expected_key); + testframework.test_kdf_multiple_key::>( + &keys, + additional_input.as_slice(), + &mut expected_key, + ); } } diff --git a/crypto/hmac/benches/hmac_benches.rs b/crypto/hmac/benches/hmac_benches.rs index f395c37..0e9dd03 100644 --- a/crypto/hmac/benches/hmac_benches.rs +++ b/crypto/hmac/benches/hmac_benches.rs @@ -1,9 +1,9 @@ -use criterion::{Criterion, Throughput, criterion_group, criterion_main}; -use std::hint::black_box; -use bouncycastle_rng as rng; use bouncycastle_core::key_material::{KeyMaterial256, KeyMaterial512, KeyType}; use bouncycastle_core::traits::{MAC, RNG}; use bouncycastle_hmac::{HMAC_SHA256, HMAC_SHA512}; +use bouncycastle_rng as rng; +use criterion::{Criterion, Throughput, criterion_group, criterion_main}; +use std::hint::black_box; fn bench_hmac_sha256(c: &mut Criterion) { let mut data_block = [0_u8; 1024]; @@ -52,4 +52,4 @@ fn bench_hmac_sha512(c: &mut Criterion) { } criterion_group!(benches, bench_hmac_sha256, bench_hmac_sha512); -criterion_main!(benches); \ No newline at end of file +criterion_main!(benches); diff --git a/crypto/hmac/tests/hmac_tests.rs b/crypto/hmac/tests/hmac_tests.rs index 87dd118..a3d8e8c 100644 --- a/crypto/hmac/tests/hmac_tests.rs +++ b/crypto/hmac/tests/hmac_tests.rs @@ -1,11 +1,13 @@ #[cfg(test)] mod hmac_tests { - use bouncycastle_core::key_material::{KeyMaterial256, KeyMaterial512, KeyMaterial, KeyType, KeyMaterialTrait}; - use bouncycastle_core::traits::{Algorithm, Hash, SecurityStrength, MAC}; - use bouncycastle_core_test_framework::mac::TestFrameworkMAC; - use bouncycastle_hex as hex; use bouncycastle_core::errors::{KeyMaterialError, MACError}; + use bouncycastle_core::key_material::{ + KeyMaterial, KeyMaterial256, KeyMaterial512, KeyMaterialTrait, KeyType, + }; + use bouncycastle_core::traits::{Algorithm, Hash, MAC, SecurityStrength}; use bouncycastle_core_test_framework::DUMMY_SEED_512; + use bouncycastle_core_test_framework::mac::TestFrameworkMAC; + use bouncycastle_hex as hex; use bouncycastle_hmac::*; use bouncycastle_sha2::*; use bouncycastle_sha3::{SHA3_224, SHA3_256, SHA3_384, SHA3_512}; @@ -28,7 +30,8 @@ mod hmac_tests { let key = KeyMaterial256::from_bytes_as_type( b"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", KeyType::MACKey, - ).unwrap(); + ) + .unwrap(); let mut mac = HMAC::::new(&key).unwrap(); mac.do_update(b"Hi There"); let output = mac.do_final(); @@ -38,11 +41,16 @@ mod hmac_tests { let key = KeyMaterial256::from_bytes_as_type( b"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", KeyType::MACKey, - ).unwrap(); + ) + .unwrap(); let mac = HMAC::::new(&key).unwrap(); // mac.do_update(b"").unwrap(); let output = mac.do_final(); - assert_eq!(&output, &hex::decode("999a901219f032cd497cadb5e6051e97b6a29ab297bd6ae722bd6062a2f59542").unwrap()); + assert_eq!( + &output, + &hex::decode("999a901219f032cd497cadb5e6051e97b6a29ab297bd6ae722bd6062a2f59542") + .unwrap() + ); } #[test] @@ -63,7 +71,6 @@ mod hmac_tests { _ = HMAC::::new(&key).unwrap(); _ = HMAC_SHA512::new(&key).unwrap(); - _ = HMAC::::new(&key).unwrap(); _ = HMAC_SHA3_224::new(&key).unwrap(); @@ -82,12 +89,15 @@ mod hmac_tests { let short_key = KeyMaterial256::from_bytes_as_type( &hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(), KeyType::MACKey, - ).unwrap(); + ) + .unwrap(); assert_eq!(short_key.security_strength(), SecurityStrength::_112bit); // key is too short, so we expect it to fail match HMAC::::new(&short_key) { - Err(MACError::KeyMaterialError(KeyMaterialError::SecurityStrength(_))) => { /* good */ }, - _ => panic!("This should have thrown a KeyMaterialError::SecurityStrength error but it didn't"), + Err(MACError::KeyMaterialError(KeyMaterialError::SecurityStrength(_))) => { /* good */ } + _ => panic!( + "This should have thrown a KeyMaterialError::SecurityStrength error but it didn't" + ), } // but this'll work fine @@ -97,19 +107,38 @@ mod hmac_tests { let key = KeyMaterial256::from_bytes_as_type( &hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(), KeyType::MACKey, - ).unwrap(); + ) + .unwrap(); HMAC::::new(&key).unwrap(); } #[test] fn test_block_bitlen() { // give it a key that is exactly the block size - let key = KeyMaterial::<1000>::from_bytes_as_type(&vec![0x3cu8; SHA256::new().block_bitlen()/8], KeyType::MACKey).unwrap(); - assert!(HMAC_SHA256::new(&key).unwrap().verify(b"Hi There", &hex::decode("4da0a0bb56f010db147b8f6e5f2dbecf7bb35ff00c8b9da31c9b94cc81815873").unwrap())); + let key = KeyMaterial::<1000>::from_bytes_as_type( + &vec![0x3Cu8; SHA256::new().block_bitlen() / 8], + KeyType::MACKey, + ) + .unwrap(); + assert!( + HMAC_SHA256::new(&key).unwrap().verify( + b"Hi There", + &hex::decode("4da0a0bb56f010db147b8f6e5f2dbecf7bb35ff00c8b9da31c9b94cc81815873") + .unwrap() + ) + ); // Now give it a key that is larger than the block size and needs to be hashed down - let key = KeyMaterial::<1000>::from_bytes_as_type(&vec![0x3cu8; SHA256::new().block_bitlen()/8 + 1], KeyType::MACKey).unwrap(); - HMAC_SHA256::new(&key).unwrap().verify(b"Hi There", &hex::decode("5cb9475aba606afe8c82c2d1b3e1cfb1c814e8a72ce5a7b4fe43b0a0aac45144").unwrap()); + let key = KeyMaterial::<1000>::from_bytes_as_type( + &vec![0x3Cu8; SHA256::new().block_bitlen() / 8 + 1], + KeyType::MACKey, + ) + .unwrap(); + HMAC_SHA256::new(&key).unwrap().verify( + b"Hi There", + &hex::decode("5cb9475aba606afe8c82c2d1b3e1cfb1c814e8a72ce5a7b4fe43b0a0aac45144") + .unwrap(), + ); } #[test] @@ -129,15 +158,19 @@ mod hmac_tests { // but we don't allow zero-len keys that are not Zeroized or MACKey - // init - let mut key = KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[..64], KeyType::MACKey).unwrap(); + let mut key = + KeyMaterial512::from_bytes_as_type(&DUMMY_SEED_512[..64], KeyType::MACKey).unwrap(); assert_eq!(key.security_strength(), SecurityStrength::_256bit); key.set_security_strength(SecurityStrength::_128bit).unwrap(); // complains at first match HMAC::::new(&key) { - Err(MACError::KeyMaterialError(KeyMaterialError::SecurityStrength(_))) => { /* fine */ }, - _ => { panic!("This should have thrown a KeyMaterialError::SecurityStrength error but it didn't") }, + Err(MACError::KeyMaterialError(KeyMaterialError::SecurityStrength(_))) => { /* fine */ } + _ => { + panic!( + "This should have thrown a KeyMaterialError::SecurityStrength error but it didn't" + ) + } } // but fine if you set .allow_weak_keys() let mut hmac = HMAC::::new_allow_weak_key(&key).unwrap(); @@ -158,7 +191,8 @@ mod hmac_tests { let key = KeyMaterial256::from_bytes_as_type( b"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", KeyType::MACKey, - ).unwrap(); + ) + .unwrap(); // get the known-good output let out = HMAC::::new(&key).unwrap().mac(b"Hi There"); @@ -166,24 +200,28 @@ mod hmac_tests { // test output that's the wrong length, should simply return False let mut mac = HMAC::::new(&key).unwrap(); mac.do_update(b"Hi There"); - assert!( ! mac.do_verify_final(&out[..out.len() - 1])); + assert!(!mac.do_verify_final(&out[..out.len() - 1])); // test output that's the right length but wrong value -- do_verify let mut mac = HMAC::::new(&key).unwrap(); mac.do_update(b"Hi There"); - assert!( ! mac.do_verify_final(&[0x01_u8; 28])); + assert!(!mac.do_verify_final(&[0x01_u8; 28])); // test output that's the right length but wrong value -- static verify - assert!( ! HMAC_SHA224::new(&key).unwrap().verify( b"Hi There", &[0x01_u8; 28])); + assert!(!HMAC_SHA224::new(&key).unwrap().verify(b"Hi There", &[0x01_u8; 28])); // error case: test that it'll refuse to truncate below MIN_FIPS_DIGEST_LEN let mut mac = HMAC::::new(&key).unwrap(); mac.do_update(b"Hi There"); let mut out = vec![0u8; MIN_FIPS_DIGEST_LEN - 1]; match mac.do_final_out(&mut out) { - Ok(_) => { panic!("This should have throw an InvalidLength error")} - Err(MACError::InvalidLength(_)) => { /*** good **/ }, - Err(_) => { panic!("This should have throw an InvalidLength error but it threw something else")}, + Ok(_) => { + panic!("This should have throw an InvalidLength error") + } + Err(MACError::InvalidLength(_)) => { /*** good **/ } + Err(_) => { + panic!("This should have throw an InvalidLength error but it threw something else") + } } // success case: ... but it will truncate to exactly MIN_FIPS_DIGEST_LEN @@ -197,17 +235,17 @@ mod hmac_tests { // fail case: mac value is correct but truncated let mac = HMAC_SHA3_224::new(&key).unwrap(); let mut mac_val = mac.mac(b"Polly want a cracker?"); - let verifier = HMAC_SHA3_224::new(&key).unwrap(); + let verifier = HMAC_SHA3_224::new(&key).unwrap(); assert!(verifier.verify(b"Polly want a cracker?", &mac_val)); // truncation of the mac value is considered a fail - let verifier = HMAC_SHA3_224::new(&key).unwrap(); - assert!(! verifier.verify(b"Polly want a cracker?", &mac_val[..mac_val.len() - 1]) ); + let verifier = HMAC_SHA3_224::new(&key).unwrap(); + assert!(!verifier.verify(b"Polly want a cracker?", &mac_val[..mac_val.len() - 1])); // .. as is some extra bytes at the end - let verifier = HMAC_SHA3_224::new(&key).unwrap(); + let verifier = HMAC_SHA3_224::new(&key).unwrap(); mac_val.extend_from_slice(&[0u8; 4]); - assert!(! verifier.verify(b"Polly want a cracker?", &mac_val) ); + assert!(!verifier.verify(b"Polly want a cracker?", &mac_val)); } #[test] @@ -225,8 +263,8 @@ mod hmac_tests { #[cfg(test)] mod core_test_framework_rfc4231 { - use bouncycastle_core::key_material::KeyMaterial; use super::*; + use bouncycastle_core::key_material::KeyMaterial; #[test] fn hmac_sha224() { @@ -289,9 +327,10 @@ mod hmac_tests { // RFC4231 Test Case 6 -- Test with a combined length of key and data that is larger than 64 // bytes (= block-size of SHA-224 and SHA-256). let key = KeyMaterial::<131>::from_bytes_as_type(&hex::decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap(), KeyType::MACKey).unwrap(); - test_framework.test_mac::>(&key, - b"Test Using Larger Than Block-Size Key - Hash Key First", - &hex::decode("95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e").unwrap() + test_framework.test_mac::>( + &key, + b"Test Using Larger Than Block-Size Key - Hash Key First", + &hex::decode("95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e").unwrap(), ); // RFC4231 Test Case 7 -- Test with a key and data that is larger than 128 bytes (= block-size @@ -315,7 +354,8 @@ mod hmac_tests { test_framework.test_mac::>( &zero_length_key, b"Hello, world", - &hex::decode("c0fa4c55880318c31c1020e7a2cf830c2c695716387795c7a0eb918ba84e4bf0").unwrap(), + &hex::decode("c0fa4c55880318c31c1020e7a2cf830c2c695716387795c7a0eb918ba84e4bf0") + .unwrap(), ); // RFC4231 Test Case 1 @@ -325,16 +365,18 @@ mod hmac_tests { &hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(), KeyType::MACKey, ) - .unwrap(), + .unwrap(), b"Hi There", - &hex::decode("b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7").unwrap(), + &hex::decode("b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7") + .unwrap(), ); // RFC4231 Test Case 2 -- Test with a key shorter than the length of the HMAC output. test_framework.test_mac::>( &KeyMaterial256::from_bytes_as_type(b"Jefe", KeyType::MACKey).unwrap(), b"what do ya want for nothing?", - &hex::decode("5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843").unwrap(), + &hex::decode("5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843") + .unwrap(), ); // RFC4231 Test Case 3 -- Test with a combined length of key and data that is larger than 64 @@ -356,7 +398,7 @@ mod hmac_tests { &hex::decode("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c").unwrap(), KeyType::MACKey, ) - .unwrap(); + .unwrap(); let mut out = [0u8; 128 / 8]; HMAC::::new(&key).unwrap().mac_out(b"Test With Truncation", &mut out).unwrap(); assert_eq!(&Vec::from(out), &hex::decode("a3b6167473100ee06e0c796c2955552b").unwrap()); @@ -429,7 +471,7 @@ mod hmac_tests { &hex::decode("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c").unwrap(), KeyType::MACKey, ) - .unwrap(); + .unwrap(); let mut out = [0u8; 128 / 8]; // Key is shorter than HMAC security strength, so need to use new_allow_weak_keys() let hmac = HMAC::::new_allow_weak_key(&key).unwrap(); @@ -505,7 +547,7 @@ mod hmac_tests { &hex::decode("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c").unwrap(), KeyType::MACKey, ) - .unwrap(); + .unwrap(); let mut out = [0u8; 128 / 8]; // Key is shorter than HMAC security strength, so need to use new_allow_weak_keys() let hmac = HMAC::::new_allow_weak_key(&key).unwrap(); diff --git a/crypto/mldsa/benches/mldsa_benches.rs b/crypto/mldsa/benches/mldsa_benches.rs index 9d019a4..aa8f055 100644 --- a/crypto/mldsa/benches/mldsa_benches.rs +++ b/crypto/mldsa/benches/mldsa_benches.rs @@ -1,9 +1,14 @@ -use criterion::{Criterion, criterion_group, criterion_main}; use bouncycastle_core::key_material::{KeyMaterial256, KeyType}; -use std::hint::black_box; use bouncycastle_core::traits::Signature; -use bouncycastle_mldsa::{MLDSA44PrivateKeyExpanded, MLDSA44PublicKeyExpanded, MLDSA65PrivateKeyExpanded, MLDSA65PublicKeyExpanded, MLDSA87PrivateKeyExpanded, MLDSA87PublicKeyExpanded, MLDSAPrivateKeyTrait, MLDSAPublicKeyTrait, MLDSATrait, MLDSA44, MLDSA44_SIG_LEN, MLDSA65, MLDSA65_SIG_LEN, MLDSA87, MLDSA87_SIG_LEN}; use bouncycastle_hex as hex; +use bouncycastle_mldsa::{ + MLDSA44, MLDSA44_SIG_LEN, MLDSA44PrivateKeyExpanded, MLDSA44PublicKeyExpanded, MLDSA65, + MLDSA65_SIG_LEN, MLDSA65PrivateKeyExpanded, MLDSA65PublicKeyExpanded, MLDSA87, MLDSA87_SIG_LEN, + MLDSA87PrivateKeyExpanded, MLDSA87PublicKeyExpanded, MLDSAPrivateKeyTrait, MLDSAPublicKeyTrait, + MLDSATrait, +}; +use criterion::{Criterion, criterion_group, criterion_main}; +use std::hint::black_box; fn bench_mldsa_keygen(c: &mut Criterion) { let mut group = c.benchmark_group("KeyGen"); @@ -18,11 +23,11 @@ fn bench_mldsa_keygen(c: &mut Criterion) { group.throughput(criterion::Throughput::Elements(seeds.len() as u64)); group.bench_function("ML-DSA-44", |b| { - b.iter(|| { - for seed in seeds.iter() { - black_box(MLDSA44::keygen_from_seed(seed)).unwrap(); - } - }) + b.iter(|| { + for seed in seeds.iter() { + black_box(MLDSA44::keygen_from_seed(seed)).unwrap(); + } + }) }); group.bench_function("ML-DSA-65", |b| { @@ -94,16 +99,16 @@ fn bench_mldsa_sign(c: &mut Criterion) { let seed = KeyMaterial256::from_bytes_as_type( &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let msg = b"The quick brown fox jumped over the lazy dog"; /*** ML-DSA-44 ***/ let (_mldsa44_pk, mldsa44_sk) = MLDSA44::keygen_from_seed(&seed).unwrap(); - // signing nonce; we'll increment each time - let mut rnd= [0u8; 32]; + let mut rnd = [0u8; 32]; group.throughput(criterion::Throughput::Elements(1_u64)); @@ -116,7 +121,6 @@ fn bench_mldsa_sign(c: &mut Criterion) { }) }); - /*** ML-DSA-65 ***/ let (_mldsa65_pk, mldsa65_sk) = MLDSA65::keygen_from_seed(&seed).unwrap(); @@ -129,7 +133,6 @@ fn bench_mldsa_sign(c: &mut Criterion) { }) }); - /*** ML-DSA-87 ***/ let (_mldsa87_pk, mldsa87_sk) = MLDSA87::keygen_from_seed(&seed).unwrap(); @@ -154,7 +157,8 @@ fn bench_mldsa_sign_from_seed(c: &mut Criterion) { let seed = KeyMaterial256::from_bytes_as_type( &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let msg = b"The quick brown fox jumped over the lazy dog"; @@ -164,9 +168,8 @@ fn bench_mldsa_sign_from_seed(c: &mut Criterion) { sk.tr().clone() }; - // signing nonce; we'll increment each time - let mut rnd= [0u8; 32]; + let mut rnd = [0u8; 32]; group.throughput(criterion::Throughput::Elements(1_u64)); @@ -179,7 +182,6 @@ fn bench_mldsa_sign_from_seed(c: &mut Criterion) { }) }); - /*** ML-DSA-65 ***/ let tr = { let (_pk, sk) = MLDSA65::keygen_from_seed(&seed).unwrap(); @@ -187,7 +189,7 @@ fn bench_mldsa_sign_from_seed(c: &mut Criterion) { }; // signing nonce; we'll increment each time - let mut rnd= [0u8; 32]; + let mut rnd = [0u8; 32]; group.throughput(criterion::Throughput::Elements(1_u64)); @@ -200,7 +202,6 @@ fn bench_mldsa_sign_from_seed(c: &mut Criterion) { }) }); - /*** ML-DSA-87 ***/ let tr = { @@ -209,7 +210,7 @@ fn bench_mldsa_sign_from_seed(c: &mut Criterion) { }; // signing nonce; we'll increment each time - let mut rnd= [0u8; 32]; + let mut rnd = [0u8; 32]; group.throughput(criterion::Throughput::Elements(1_u64)); @@ -225,7 +226,6 @@ fn bench_mldsa_sign_from_seed(c: &mut Criterion) { group.finish(); } - fn bench_mldsa_sign_with_expanded_key(c: &mut Criterion) { let mut group = c.benchmark_group("Sign_with_expanded"); @@ -234,7 +234,8 @@ fn bench_mldsa_sign_with_expanded_key(c: &mut Criterion) { let seed = KeyMaterial256::from_bytes_as_type( &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let msg = b"The quick brown fox jumped over the lazy dog"; @@ -242,9 +243,8 @@ fn bench_mldsa_sign_with_expanded_key(c: &mut Criterion) { let (mldsa44_pk, mldsa44_sk) = MLDSA44::keygen_from_seed(&seed).unwrap(); let a_hat = mldsa44_pk.A_hat(); - // signing nonce; we'll increment each time - let mut rnd= [0u8; 32]; + let mut rnd = [0u8; 32]; group.throughput(criterion::Throughput::Elements(1_u64)); @@ -257,7 +257,6 @@ fn bench_mldsa_sign_with_expanded_key(c: &mut Criterion) { }) }); - /*** ML-DSA-65 ***/ let (mldsa65_pk, mldsa65_sk) = MLDSA65::keygen_from_seed(&seed).unwrap(); let a_hat = mldsa65_pk.A_hat(); @@ -271,7 +270,6 @@ fn bench_mldsa_sign_with_expanded_key(c: &mut Criterion) { }) }); - /*** ML-DSA-87 ***/ let (mldsa87_pk, mldsa87_sk) = MLDSA87::keygen_from_seed(&seed).unwrap(); @@ -297,21 +295,21 @@ fn bench_mldsa_verify(c: &mut Criterion) { let seed = KeyMaterial256::from_bytes_as_type( &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let msg = b"The quick brown fox jumped over the lazy dog"; - /*** ML-DSA-44 ***/ let (mldsa44_pk, mldsa44_sk) = MLDSA44::keygen_from_seed(&seed).unwrap(); // Create a vec of 1000 different signatures to verify // use ctx to make them different (in addition to the signing nonce being different) - let mut sigs = Vec::< ([u8; MLDSA44_SIG_LEN], u128) >::with_capacity(1000); + let mut sigs = Vec::<([u8; MLDSA44_SIG_LEN], u128)>::with_capacity(1000); let mut ctx = 0u128; for _ in 0..1000 { - sigs.push( (MLDSA44::sign(&mldsa44_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx) ); + sigs.push((MLDSA44::sign(&mldsa44_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx)); ctx += 1 } @@ -321,22 +319,21 @@ fn bench_mldsa_verify(c: &mut Criterion) { b.iter(|| { for i in 0..sigs.len() { let (sig, ctx) = &sigs[i]; - black_box( MLDSA44::verify(&mldsa44_pk, msg, Some(&ctx.to_le_bytes()), sig).unwrap() ) + black_box(MLDSA44::verify(&mldsa44_pk, msg, Some(&ctx.to_le_bytes()), sig).unwrap()) } }) }); - /*** ML-DSA-65 ***/ let (mldsa65_pk, mldsa65_sk) = MLDSA65::keygen_from_seed(&seed).unwrap(); // Create a vec of 1000 different signatures to verify // use ctx to make them different (in addition to the signing nonce being different) - let mut sigs = Vec::< ([u8; MLDSA65_SIG_LEN], u128) >::with_capacity(1000); + let mut sigs = Vec::<([u8; MLDSA65_SIG_LEN], u128)>::with_capacity(1000); let mut ctx = 0u128; for _ in 0..1000 { - sigs.push( (MLDSA65::sign(&mldsa65_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx) ); + sigs.push((MLDSA65::sign(&mldsa65_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx)); ctx += 1 } @@ -346,22 +343,21 @@ fn bench_mldsa_verify(c: &mut Criterion) { b.iter(|| { for i in 0..sigs.len() { let (sig, ctx) = &sigs[i]; - black_box( MLDSA65::verify(&mldsa65_pk, msg, Some(&ctx.to_le_bytes()), sig).unwrap() ) + black_box(MLDSA65::verify(&mldsa65_pk, msg, Some(&ctx.to_le_bytes()), sig).unwrap()) } }) }); - /*** ML-DSA-87 ***/ let (mldsa87_pk, mldsa87_sk) = MLDSA87::keygen_from_seed(&seed).unwrap(); // Create a vec of 1000 different signatures to verify // use ctx to make them different (in addition to the signing nonce being different) - let mut sigs = Vec::< ([u8; MLDSA87_SIG_LEN], u128) >::with_capacity(1000); + let mut sigs = Vec::<([u8; MLDSA87_SIG_LEN], u128)>::with_capacity(1000); let mut ctx = 0u128; for _ in 0..1000 { - sigs.push( (MLDSA87::sign(&mldsa87_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx) ); + sigs.push((MLDSA87::sign(&mldsa87_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx)); ctx += 1 } @@ -371,7 +367,7 @@ fn bench_mldsa_verify(c: &mut Criterion) { b.iter(|| { for i in 0..sigs.len() { let (sig, ctx) = &sigs[i]; - black_box( MLDSA87::verify(&mldsa87_pk, msg, Some(&ctx.to_le_bytes()), sig).unwrap() ) + black_box(MLDSA87::verify(&mldsa87_pk, msg, Some(&ctx.to_le_bytes()), sig).unwrap()) } }) }); @@ -387,22 +383,22 @@ fn bench_mldsa_verify_with_expanded_key(c: &mut Criterion) { let seed = KeyMaterial256::from_bytes_as_type( &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let msg = b"The quick brown fox jumped over the lazy dog"; - /*** ML-DSA-44 ***/ let (mldsa44_pk, mldsa44_sk) = MLDSA44::keygen_from_seed(&seed).unwrap(); let pk_expanded = MLDSA44PublicKeyExpanded::from(&mldsa44_pk); // Create a vec of 1000 different signatures to verify // use ctx to make them different (in addition to the signing nonce being different) - let mut sigs = Vec::< ([u8; MLDSA44_SIG_LEN], u128) >::with_capacity(1000); + let mut sigs = Vec::<([u8; MLDSA44_SIG_LEN], u128)>::with_capacity(1000); let mut ctx = 0u128; for _ in 0..1000 { - sigs.push( (MLDSA44::sign(&mldsa44_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx) ); + sigs.push((MLDSA44::sign(&mldsa44_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx)); ctx += 1 } @@ -412,23 +408,30 @@ fn bench_mldsa_verify_with_expanded_key(c: &mut Criterion) { b.iter(|| { for i in 0..sigs.len() { let (sig, ctx) = &sigs[i]; - black_box( MLDSA44::verify_with_expanded_key(&pk_expanded, msg, Some(&ctx.to_le_bytes()), sig).unwrap() ) + black_box( + MLDSA44::verify_with_expanded_key( + &pk_expanded, + msg, + Some(&ctx.to_le_bytes()), + sig, + ) + .unwrap(), + ) } }) }); - /*** ML-DSA-65 ***/ let (mldsa65_pk, mldsa65_sk) = MLDSA65::keygen_from_seed(&seed).unwrap(); let pk_expanded = MLDSA65PublicKeyExpanded::from(&mldsa65_pk); // Create a vec of 1000 different signatures to verify // use ctx to make them different (in addition to the signing nonce being different) - let mut sigs = Vec::< ([u8; MLDSA65_SIG_LEN], u128) >::with_capacity(1000); + let mut sigs = Vec::<([u8; MLDSA65_SIG_LEN], u128)>::with_capacity(1000); let mut ctx = 0u128; for _ in 0..1000 { - sigs.push( (MLDSA65::sign(&mldsa65_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx) ); + sigs.push((MLDSA65::sign(&mldsa65_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx)); ctx += 1 } @@ -438,23 +441,30 @@ fn bench_mldsa_verify_with_expanded_key(c: &mut Criterion) { b.iter(|| { for i in 0..sigs.len() { let (sig, ctx) = &sigs[i]; - black_box( MLDSA65::verify_with_expanded_key(&pk_expanded, msg, Some(&ctx.to_le_bytes()), sig).unwrap() ) + black_box( + MLDSA65::verify_with_expanded_key( + &pk_expanded, + msg, + Some(&ctx.to_le_bytes()), + sig, + ) + .unwrap(), + ) } }) }); - /*** ML-DSA-87 ***/ let (mldsa87_pk, mldsa87_sk) = MLDSA87::keygen_from_seed(&seed).unwrap(); let pk_expanded = MLDSA87PublicKeyExpanded::from(&mldsa87_pk); // Create a vec of 1000 different signatures to verify // use ctx to make them different (in addition to the signing nonce being different) - let mut sigs = Vec::< ([u8; MLDSA87_SIG_LEN], u128) >::with_capacity(1000); + let mut sigs = Vec::<([u8; MLDSA87_SIG_LEN], u128)>::with_capacity(1000); let mut ctx = 0u128; for _ in 0..1000 { - sigs.push( (MLDSA87::sign(&mldsa87_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx) ); + sigs.push((MLDSA87::sign(&mldsa87_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx)); ctx += 1 } @@ -464,7 +474,15 @@ fn bench_mldsa_verify_with_expanded_key(c: &mut Criterion) { b.iter(|| { for i in 0..sigs.len() { let (sig, ctx) = &sigs[i]; - black_box( MLDSA87::verify_with_expanded_key(&pk_expanded, msg, Some(&ctx.to_le_bytes()), sig).unwrap() ) + black_box( + MLDSA87::verify_with_expanded_key( + &pk_expanded, + msg, + Some(&ctx.to_le_bytes()), + sig, + ) + .unwrap(), + ) } }) }); @@ -472,11 +490,16 @@ fn bench_mldsa_verify_with_expanded_key(c: &mut Criterion) { group.finish(); } - -criterion_group!(benches, - bench_mldsa_keygen, bench_mldsa_keygen_and_expand, - bench_mldsa_sign, bench_mldsa_sign_with_expanded_key, bench_mldsa_sign_from_seed, - bench_mldsa_verify, bench_mldsa_verify_with_expanded_key); +criterion_group!( + benches, + bench_mldsa_keygen, + bench_mldsa_keygen_and_expand, + bench_mldsa_sign, + bench_mldsa_sign_with_expanded_key, + bench_mldsa_sign_from_seed, + bench_mldsa_verify, + bench_mldsa_verify_with_expanded_key +); criterion_main!(benches); const DUMMY_SEED_1024: &[u8; 1024] = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; diff --git a/crypto/mldsa/src/aux_functions.rs b/crypto/mldsa/src/aux_functions.rs index 720a480..7ffd75f 100644 --- a/crypto/mldsa/src/aux_functions.rs +++ b/crypto/mldsa/src/aux_functions.rs @@ -1,7 +1,7 @@ //! Implements auxiliary functions for ML-DSA as defined in Section 7 of FIPS 204. use crate::matrix::{Matrix, Vector}; -use crate::mldsa::{q_inv, G, H}; +use crate::mldsa::{G, H, q_inv}; use crate::mldsa::{ MLDSA44_GAMMA1, MLDSA44_GAMMA2, MLDSA65_GAMMA1, MLDSA65_GAMMA2, N, POLY_T0PACKED_LEN, POLY_T1PACKED_LEN, d, q, @@ -308,8 +308,7 @@ pub(crate) fn bit_unpack_t0(a: &[u8; POLY_T0PACKED_LEN]) -> Polynomial { t0[8 * i + 6] = ((((a[13 * i + 9] as i32) >> 6) | (a[13 * i + 10] as i32) << 2) | ((a[13 * i + 11] as i32) << 10)) & 0x1FFF; - t0[8 * i + 7] = - (((a[13 * i + 11] as i32) >> 3) | ((a[13 * i + 12] as i32) << 5)) & 0x1FFF; + t0[8 * i + 7] = (((a[13 * i + 11] as i32) >> 3) | ((a[13 * i + 12] as i32) << 5)) & 0x1FFF; t0[8 * i] = (1 << (d - 1)) - t0[8 * i]; t0[8 * i + 1] = (1 << (d - 1)) - t0[8 * i + 1]; @@ -861,12 +860,7 @@ pub(crate) fn make_hint(z: i32, r: i32) -> i32 { // By the powers of someone much more clever than me, this is equivalent. - if z <= GAMMA2 || z > q - GAMMA2 || (z == q - GAMMA2 && r == 0) - { - 0 - } else { - 1 - } + if z <= GAMMA2 || z > q - GAMMA2 || (z == q - GAMMA2 && r == 0) { 0 } else { 1 } } /// Creates the hint vector from two Vector's, and also returns its hamming weight (ie the number of 1's). @@ -913,11 +907,7 @@ pub(super) fn use_hint(a: i32, hint: i32) -> i32 { MLDSA65_GAMMA2 => { // mutants note: this passes unit tests if it's a1 >= 0 // we'll leave it like this because it matches the spec - if a1 > 0 { - (a0 + 1) & 15 - } else { - (a0 - 1) & 15 - } + if a1 > 0 { (a0 + 1) & 15 } else { (a0 - 1) & 15 } } _ => { panic!("Invalid GAMMA2 value") @@ -967,7 +957,7 @@ pub(crate) fn multiply_ntt(a: &Polynomial, b: &Polynomial) -> Polynomial { /// of expressions of the form c = a * b (mod q). /// The output is not necessarily less than q in absolute value, but it is less than 2q in absolute value pub(crate) fn montgomery_reduce(a: i64) -> i32 { - debug_assert!(a > - ((q as i64) <<31) && a < ((q as i64) <<31)); + debug_assert!(a > -((q as i64) << 31) && a < ((q as i64) << 31)); // 2: 𝑡 ← ((𝑎 mod 2^32) ⋅ QINV) mod 2^32 let t: i32 = (a as i32).wrapping_mul(q_inv); @@ -980,23 +970,21 @@ pub(crate) fn conditional_add_q(a: i32) -> i32 { a + ((a >> 31) & q) } - #[test] /// These are the results it's giving; I'm not sure if these are "correct" or not. fn test_conditional_add_q() { - assert_eq!(conditional_add_q(-q -1), -1); + assert_eq!(conditional_add_q(-q - 1), -1); assert_eq!(conditional_add_q(-q), 0); - assert_eq!(conditional_add_q(-q -2), -2); - assert_eq!(conditional_add_q(-q +1), 1); - assert_eq!(conditional_add_q(-1), q-1); + assert_eq!(conditional_add_q(-q - 2), -2); + assert_eq!(conditional_add_q(-q + 1), 1); + assert_eq!(conditional_add_q(-1), q - 1); assert_eq!(conditional_add_q(0), 0); assert_eq!(conditional_add_q(1), 1); - assert_eq!(conditional_add_q(q -1), q-1); + assert_eq!(conditional_add_q(q - 1), q - 1); assert_eq!(conditional_add_q(q), q); - assert_eq!(conditional_add_q(q +1), q+1); + assert_eq!(conditional_add_q(q + 1), q + 1); } - /// Constants for NTT pub(crate) const ZETAS: [i32; 256] = [ 0, 25847, -2608894, -518909, 237124, -777960, -876248, 466468, 1826347, 2353451, -359251, @@ -1026,4 +1014,3 @@ pub(crate) const ZETAS: [i32; 256] = [ -2235985, -420899, -2286327, 183443, -976891, 1612842, -3545687, -554416, 3919660, -48306, -1362209, 3937738, 1400424, -846154, 1976782, ]; - diff --git a/crypto/mldsa/src/polynomial.rs b/crypto/mldsa/src/polynomial.rs index b419b61..89c7f69 100644 --- a/crypto/mldsa/src/polynomial.rs +++ b/crypto/mldsa/src/polynomial.rs @@ -1,18 +1,22 @@ //! Represents a polynomial over the ML-DSA ring. +use crate::aux_functions::{ + ZETAS, conditional_add_q, high_bits, low_bits, make_hint, montgomery_reduce, +}; +use crate::mldsa::{MLDSA44_POLY_W1_PACKED_LEN, MLDSA65_POLY_W1_PACKED_LEN, N, q}; +use bouncycastle_core::traits::Secret; use core::fmt; use core::fmt::{Debug, Display, Formatter}; use core::ops::{Index, IndexMut}; -use bouncycastle_core::traits::Secret; -use crate::mldsa::{N, MLDSA44_POLY_W1_PACKED_LEN, MLDSA65_POLY_W1_PACKED_LEN, q}; -use crate::aux_functions::{conditional_add_q, high_bits, low_bits, make_hint, montgomery_reduce, ZETAS}; /// A polynomial over the ML-DSA ring. /// Dev note: this doesn't strictly need to be pub ... ie there's no good reason for a caller to use this class directly, /// but in order to test the Debug and Display traits, you need STD, so those can't be tested from inline tests in this file /// and the real unit tests are in a different crate, so here we are. #[derive(Clone)] -pub struct Polynomial{ pub(crate) coeffs: [i32; N] } +pub struct Polynomial { + pub(crate) coeffs: [i32; N], +} /// Convenience function to avoid ".0" all over the place. impl Index for Polynomial { @@ -32,7 +36,7 @@ impl IndexMut for Polynomial { impl Polynomial { /// Create a new polynomial with all coefficients set to zero. pub const fn new() -> Self { - Self{ coeffs: [0i32; N] } + Self { coeffs: [0i32; N] } } pub(crate) fn conditional_add_q(&mut self) { @@ -40,7 +44,7 @@ impl Polynomial { *x = conditional_add_q(*x); } } - + pub(crate) fn reduce(&mut self) { for i in 0..N { self[i] = montgomery_reduce(self[i] as i64); @@ -84,15 +88,14 @@ impl Polynomial { // Fine that this is not constant-time (returns true early) because it is used in a rejection loop. // IE the early quit here leads to rejection and continuing to the top of the rejection loop, or failing the signature validation. // So the i32 that we just checked in a non-constant-time manner is about to get thrown away. - + // Note: this formulation of the check_norm function usually requires this bounds check // if bound > (q - 1) / 8 { // return true; // } // but since BOUND is a constant here, we'll just do a debug_assert to make sure the value is what we expect. debug_assert!(BOUND <= (q - 1) / 8); - - + let mut t: i32; for x in self.coeffs.iter() { t = *x >> 31; @@ -129,22 +132,21 @@ impl Polynomial { match POLY_W1_PACKED_LEN { MLDSA44_POLY_W1_PACKED_LEN => { - for i in 0..N/4 { - r[3 * i] = - ((self[4 * i]) as u8) | ((self[4 * i + 1] << 6) as u8); - r[3 * i + 1] = - ((self[4 * i + 1] >> 2) as u8) | ((self[4 * i + 2] << 4) as u8); - r[3 * i + 2] = - ((self[4 * i + 2] >> 4) as u8) | ((self[4 * i + 3] << 2) as u8); + for i in 0..N / 4 { + r[3 * i] = ((self[4 * i]) as u8) | ((self[4 * i + 1] << 6) as u8); + r[3 * i + 1] = ((self[4 * i + 1] >> 2) as u8) | ((self[4 * i + 2] << 4) as u8); + r[3 * i + 2] = ((self[4 * i + 2] >> 4) as u8) | ((self[4 * i + 3] << 2) as u8); } - }, + } // ML-DSA65 and 87 share a POLY_W1_PACKED_LEN value MLDSA65_POLY_W1_PACKED_LEN => { - for i in 0..N/2 { + for i in 0..N / 2 { r[i] = ((self[2 * i]) | (self[2 * i + 1] << 4)) as u8; } - }, - _ => { unreachable!() } + } + _ => { + unreachable!() + } } r diff --git a/crypto/mldsa/tests/bc_test_data.rs b/crypto/mldsa/tests/bc_test_data.rs index a504188..4ec2fdb 100644 --- a/crypto/mldsa/tests/bc_test_data.rs +++ b/crypto/mldsa/tests/bc_test_data.rs @@ -651,8 +651,6 @@ use bouncycastle_sha3::SHAKE256; // } // } - - /// This builds a "busted" mu where the ctx is absent (not 0-length, but actually not there) /// just for the sake of compatibility with the bc-test-data tests pub struct BustedMuBuilder { @@ -671,7 +669,7 @@ impl BustedMuBuilder { } /// This function requires the public key hash `tr`, which can be computed from the public key using [MLDSAPublicKey::compute_tr]. - pub fn do_init(tr: &[u8; 64], /*ctx: Option<&[u8]>*/) -> Result { + pub fn do_init(tr: &[u8; 64] /*ctx: Option<&[u8]>*/) -> Result { // let ctx = match ctx { // Some(ctx) => ctx, // None => &[] @@ -714,4 +712,4 @@ impl BustedMuBuilder { mu } -} \ No newline at end of file +} diff --git a/crypto/mldsa_lowmemory/benches/mldsa_benches.rs b/crypto/mldsa_lowmemory/benches/mldsa_benches.rs index 79ffd00..ec12a86 100644 --- a/crypto/mldsa_lowmemory/benches/mldsa_benches.rs +++ b/crypto/mldsa_lowmemory/benches/mldsa_benches.rs @@ -1,9 +1,11 @@ -use criterion::{Criterion, criterion_group, criterion_main}; use bouncycastle_core::key_material::{KeyMaterial256, KeyType}; -use std::hint::black_box; use bouncycastle_core::traits::Signature; -use bouncycastle_mldsa_lowmemory::{MLDSATrait, MLDSA44, MLDSA44_SIG_LEN, MLDSA65, MLDSA65_SIG_LEN, MLDSA87, MLDSA87_SIG_LEN}; use bouncycastle_hex as hex; +use bouncycastle_mldsa_lowmemory::{ + MLDSA44, MLDSA44_SIG_LEN, MLDSA65, MLDSA65_SIG_LEN, MLDSA87, MLDSA87_SIG_LEN, MLDSATrait, +}; +use criterion::{Criterion, criterion_group, criterion_main}; +use std::hint::black_box; fn bench_mldsa_keygen(c: &mut Criterion) { let mut group = c.benchmark_group("KeyGen"); @@ -18,11 +20,11 @@ fn bench_mldsa_keygen(c: &mut Criterion) { group.throughput(criterion::Throughput::Elements(seeds.len() as u64)); group.bench_function("ML-DSA-44_lowmemory", |b| { - b.iter(|| { - for seed in seeds.iter() { - black_box(MLDSA44::keygen_from_seed(seed)).unwrap(); - } - }) + b.iter(|| { + for seed in seeds.iter() { + black_box(MLDSA44::keygen_from_seed(seed)).unwrap(); + } + }) }); group.bench_function("ML-DSA-65_lowmemory", |b| { @@ -52,16 +54,16 @@ fn bench_mldsa_sign(c: &mut Criterion) { let seed = KeyMaterial256::from_bytes_as_type( &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let msg = b"The quick brown fox jumped over the lazy dog"; /*** ML-DSA-44 ***/ let (_mldsa44_pk, mldsa44_sk) = MLDSA44::keygen_from_seed(&seed).unwrap(); - // signing nonce; we'll increment each time - let mut rnd= [0u8; 32]; + let mut rnd = [0u8; 32]; group.throughput(criterion::Throughput::Elements(1_u64)); @@ -74,7 +76,6 @@ fn bench_mldsa_sign(c: &mut Criterion) { }) }); - /*** ML-DSA-65 ***/ let (_mldsa65_pk, mldsa65_sk) = MLDSA65::keygen_from_seed(&seed).unwrap(); @@ -87,7 +88,6 @@ fn bench_mldsa_sign(c: &mut Criterion) { }) }); - /*** ML-DSA-87 ***/ let (_mldsa87_pk, mldsa87_sk) = MLDSA87::keygen_from_seed(&seed).unwrap(); @@ -112,21 +112,21 @@ fn bench_mldsa_verify(c: &mut Criterion) { let seed = KeyMaterial256::from_bytes_as_type( &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let msg = b"The quick brown fox jumped over the lazy dog"; - /*** ML-DSA-44 ***/ let (mldsa44_pk, mldsa44_sk) = MLDSA44::keygen_from_seed(&seed).unwrap(); // Create a vec of 1000 different signatures to verify // use ctx to make them different (in addition to the signing nonce being different) - let mut sigs = Vec::< ([u8; MLDSA44_SIG_LEN], u128) >::with_capacity(1000); + let mut sigs = Vec::<([u8; MLDSA44_SIG_LEN], u128)>::with_capacity(1000); let mut ctx = 0u128; for _ in 0..1000 { - sigs.push( (MLDSA44::sign(&mldsa44_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx) ); + sigs.push((MLDSA44::sign(&mldsa44_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx)); ctx += 1 } @@ -136,22 +136,21 @@ fn bench_mldsa_verify(c: &mut Criterion) { b.iter(|| { for i in 0..sigs.len() { let (sig, ctx) = &sigs[i]; - black_box( MLDSA44::verify(&mldsa44_pk, msg, Some(&ctx.to_le_bytes()), sig).unwrap() ) + black_box(MLDSA44::verify(&mldsa44_pk, msg, Some(&ctx.to_le_bytes()), sig).unwrap()) } }) }); - /*** ML-DSA-65 ***/ let (mldsa65_pk, mldsa65_sk) = MLDSA65::keygen_from_seed(&seed).unwrap(); // Create a vec of 1000 different signatures to verify // use ctx to make them different (in addition to the signing nonce being different) - let mut sigs = Vec::< ([u8; MLDSA65_SIG_LEN], u128) >::with_capacity(1000); + let mut sigs = Vec::<([u8; MLDSA65_SIG_LEN], u128)>::with_capacity(1000); let mut ctx = 0u128; for _ in 0..1000 { - sigs.push( (MLDSA65::sign(&mldsa65_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx) ); + sigs.push((MLDSA65::sign(&mldsa65_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx)); ctx += 1 } @@ -161,22 +160,21 @@ fn bench_mldsa_verify(c: &mut Criterion) { b.iter(|| { for i in 0..sigs.len() { let (sig, ctx) = &sigs[i]; - black_box( MLDSA65::verify(&mldsa65_pk, msg, Some(&ctx.to_le_bytes()), sig).unwrap() ) + black_box(MLDSA65::verify(&mldsa65_pk, msg, Some(&ctx.to_le_bytes()), sig).unwrap()) } }) }); - /*** ML-DSA-87 ***/ let (mldsa87_pk, mldsa87_sk) = MLDSA87::keygen_from_seed(&seed).unwrap(); // Create a vec of 1000 different signatures to verify // use ctx to make them different (in addition to the signing nonce being different) - let mut sigs = Vec::< ([u8; MLDSA87_SIG_LEN], u128) >::with_capacity(1000); + let mut sigs = Vec::<([u8; MLDSA87_SIG_LEN], u128)>::with_capacity(1000); let mut ctx = 0u128; for _ in 0..1000 { - sigs.push( (MLDSA87::sign(&mldsa87_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx) ); + sigs.push((MLDSA87::sign(&mldsa87_sk, msg, Some(&ctx.to_le_bytes())).unwrap(), ctx)); ctx += 1 } @@ -186,7 +184,7 @@ fn bench_mldsa_verify(c: &mut Criterion) { b.iter(|| { for i in 0..sigs.len() { let (sig, ctx) = &sigs[i]; - black_box( MLDSA87::verify(&mldsa87_pk, msg, Some(&ctx.to_le_bytes()), sig).unwrap() ) + black_box(MLDSA87::verify(&mldsa87_pk, msg, Some(&ctx.to_le_bytes()), sig).unwrap()) } }) }); @@ -194,7 +192,6 @@ fn bench_mldsa_verify(c: &mut Criterion) { group.finish(); } - criterion_group!(benches, bench_mldsa_keygen, bench_mldsa_sign, bench_mldsa_verify); criterion_main!(benches); diff --git a/crypto/mldsa_lowmemory/src/aux_functions.rs b/crypto/mldsa_lowmemory/src/aux_functions.rs index a8ac1a2..11945c9 100644 --- a/crypto/mldsa_lowmemory/src/aux_functions.rs +++ b/crypto/mldsa_lowmemory/src/aux_functions.rs @@ -3,8 +3,7 @@ // use crate::matrix::{Matrix, Vector}; use crate::mldsa::{G, H, POLY_T0PACKED_LEN}; use crate::mldsa::{ - MLDSA44_GAMMA1, MLDSA44_GAMMA2, MLDSA65_GAMMA1, MLDSA65_GAMMA2, N, - POLY_T1PACKED_LEN, d, q, + MLDSA44_GAMMA1, MLDSA44_GAMMA2, MLDSA65_GAMMA1, MLDSA65_GAMMA2, N, POLY_T1PACKED_LEN, d, q, }; use crate::polynomial::Polynomial; use bouncycastle_core::traits::XOF; @@ -59,12 +58,11 @@ pub(crate) fn simple_bit_pack_t1(w: &Polynomial) -> [u8; POLY_T1PACKED_LEN] { output[5 * i + 1] = ((w[4 * i] >> 8) | (w[4 * i + 1] << 2)) as u8; output[5 * i + 2] = ((w[4 * i + 1] >> 6) | (w[4 * i + 2] << 4)) as u8; output[5 * i + 3] = ((w[4 * i + 2] >> 4) | (w[4 * i + 3] << 6)) as u8; - output[5 * i + 4] = (w[4 * i + 3] >> 2) as u8; + output[5 * i + 4] = (w[4 * i + 3] >> 2) as u8; } output } - /// As defined in Algorithm 17, this gives the length of a packed bitstring representing a polynomial /// whose coefficients have been rounded to \[-eta, eta], which is 32*bitlen(2*eta). pub const fn bitlen_eta(eta: usize) -> usize { @@ -166,7 +164,8 @@ pub(crate) fn bit_pack_t0(t0: &Polynomial) -> [u8; POLY_T0PACKED_LEN] { /// A variant of Algorithm 17 specific to packing z in the signature value in \[−𝛾1 + 1, 𝛾1]. pub(crate) fn bitpack_gamma1( z: &Polynomial, - out: &mut [u8; POLY_Z_PACKED_LEN]) { + out: &mut [u8; POLY_Z_PACKED_LEN], +) { let mut t: [u32; 4] = [0; 4]; match GAMMA1 { MLDSA44_GAMMA1 => { @@ -217,7 +216,7 @@ pub(crate) fn simple_bit_unpack_t1(v: &[u8; POLY_T1PACKED_LEN]) -> Polynomial { let mut w = Polynomial::new(); - for i in 0..N/4 { + for i in 0..N / 4 { w[4 * i] = ((v[5 * i] as i32) | ((v[5 * i + 1] as i32) << 8)) & 0x3FF; w[4 * i + 1] = (((v[5 * i + 1] as i32) >> 2) | ((v[5 * i + 2] as i32) << 6)) & 0x3FF; w[4 * i + 2] = (((v[5 * i + 2] as i32) >> 4) | ((v[5 * i + 3] as i32) << 4)) & 0x3FF; @@ -227,7 +226,6 @@ pub(crate) fn simple_bit_unpack_t1(v: &[u8; POLY_T1PACKED_LEN]) -> Polynomial { w } - /// A variant of Algorithm 19 BitUnpack specific to a=eta, b=eta /// Input: 𝑎, 𝑏 ∈ ℕ and a byte string 𝑣 of length 32 ⋅ bitlen (𝑎 + 𝑏). /// Output: A polynomial 𝑤 ∈ 𝑅 with coefficients in [𝑏 − 2𝑐 + 1, 𝑏], where 𝑐 = bitlen (𝑎 + 𝑏). @@ -344,9 +342,7 @@ pub(crate) fn bit_unpack_gamma1(v: &[u8]) -> Polynomial { } /// Part of unpacking the sig value -pub(crate) fn unpack_c_tilde< - const LAMBDA_over_4: usize, ->(sig: &[u8]) -> &[u8; LAMBDA_over_4] { +pub(crate) fn unpack_c_tilde(sig: &[u8]) -> &[u8; LAMBDA_over_4] { sig[..LAMBDA_over_4].try_into().unwrap() } /// Part of unpacking the sig value @@ -365,7 +361,8 @@ pub(crate) fn unpack_z_row< // skip to the start of the z's let pos = LAMBDA_over_4; let z = bit_unpack_gamma1::( - &sig[pos + idx * POLY_Z_PACKED_LEN..pos + (idx + 1) * POLY_Z_PACKED_LEN]); + &sig[pos + idx * POLY_Z_PACKED_LEN..pos + (idx + 1) * POLY_Z_PACKED_LEN], + ); // Perform the norm check from // Alg 8; Line 13 (first half) return [[ ||𝐳||∞ < 𝛾1 − 𝛽]] @@ -391,7 +388,6 @@ pub(crate) fn unpack_h_row< // skip over the other stuff in the encoded sig value let pos = LAMBDA_over_4 + l * POLY_Z_PACKED_LEN; - // This inlines Algorithm 21 HintBitUnpack(𝑦) // 2: Index ← 0 @@ -399,7 +395,7 @@ pub(crate) fn unpack_h_row< // let mut idx = 0usize; // This row calc is a bit weird because technically it's supposed to be done at the end // of the previous loop - let idx = if row == 0 { 0 } else { sig[pos + OMEGA as usize + row-1] as usize }; + let idx = if row == 0 { 0 } else { sig[pos + OMEGA as usize + row - 1] as usize }; // 3: for 𝑖 from 0 to 𝑘 − 1 do // ▷ reconstruct 𝐡[𝑖] @@ -736,12 +732,7 @@ pub(crate) fn make_hint(z: i32, r: i32) -> i32 { // By the powers of someone much more clever than me, this is equivalent. - if z <= GAMMA2 || z > q - GAMMA2 || (z == q - GAMMA2 && r == 0) - { - 0 - } else { - 1 - } + if z <= GAMMA2 || z > q - GAMMA2 || (z == q - GAMMA2 && r == 0) { 0 } else { 1 } } /// Algorithm 40 UseHint(ℎ, 𝑟) diff --git a/crypto/mldsa_lowmemory/src/low_memory_helpers.rs b/crypto/mldsa_lowmemory/src/low_memory_helpers.rs index d947bbe..f354d4b 100644 --- a/crypto/mldsa_lowmemory/src/low_memory_helpers.rs +++ b/crypto/mldsa_lowmemory/src/low_memory_helpers.rs @@ -2,10 +2,12 @@ //! and other intermediate values by never holding the whole thing in memory at once, but re-constructing //! what it needs in pieces, which generally means handling the matrices and vectors row-wise or entry-wise. -use bouncycastle_core::errors::SignatureError; -use crate::mldsa::{d}; -use crate::aux_functions::{bit_unpack_eta, bitlen_eta, expand_mask_poly, rej_ntt_poly, unpack_z_row}; +use crate::aux_functions::{ + bit_unpack_eta, bitlen_eta, expand_mask_poly, rej_ntt_poly, unpack_z_row, +}; +use crate::mldsa::d; use crate::polynomial::Polynomial; +use bouncycastle_core::errors::SignatureError; #[inline(always)] pub(crate) fn expandA_elem(rho: &[u8; 32], i: usize, j: usize) -> Polynomial { @@ -45,13 +47,14 @@ pub(crate) fn compute_wp_approx_row< const l: usize, const POLY_Z_PACKED_LEN: usize, const LAMBDA_over_4: usize, - const SIG_LEN: usize + const SIG_LEN: usize, >( rho: &[u8; 32], sig: &[u8; SIG_LEN], t1: &Polynomial, c: &Polynomial, - idx: usize) -> Result { + idx: usize, +) -> Result { // Algorithm 8: line 9: 𝐰′_approx ← NTT−1(𝐀_hat ∘ NTT(𝐳) − NTT(𝑐) ∘ NTT(𝐭1 ⋅ 2^𝑑)) // broken out for clarity: // NTT−1( @@ -95,7 +98,9 @@ pub(crate) fn compute_wp_approx_row< } pub(crate) fn compute_z_component< - const GAMMA1: i32, const GAMMA1_MASK_LEN: usize, const BETA: i32, + const GAMMA1: i32, + const GAMMA1_MASK_LEN: usize, + const BETA: i32, >( s1: &Polynomial, rho_p_p: &[u8; 64], @@ -115,10 +120,7 @@ pub(crate) fn compute_z_component< if z.check_norm(GAMMA1 - BETA) { Ok(None) } else { Ok(Some(z)) } } -pub(crate) fn compute_w0cs2_component< - const GAMMA2: i32, - const BETA: i32, ->( +pub(crate) fn compute_w0cs2_component( s2: &Polynomial, w: &Polynomial, c_hat: &Polynomial, @@ -129,7 +131,6 @@ pub(crate) fn compute_w0cs2_component< let mut cs2 = s2_hat; // rename cs2.inv_ntt(); - // Note: this could be further optimized by using the optimization described in // https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf section 5.1: // "instead of computing (r1, r0) = Decomposeq (w − cs2, α) @@ -142,9 +143,7 @@ pub(crate) fn compute_w0cs2_component< if w0cs2.check_norm(GAMMA2 - BETA) { None } else { Some(w0cs2) } } -pub(crate) fn compute_ct0_component< - const GAMMA2: i32, ->( +pub(crate) fn compute_ct0_component( t0_row: &Polynomial, c_hat: &Polynomial, ) -> Option { diff --git a/crypto/mldsa_lowmemory/src/mldsa.rs b/crypto/mldsa_lowmemory/src/mldsa.rs index 28f4386..efdcc98 100644 --- a/crypto/mldsa_lowmemory/src/mldsa.rs +++ b/crypto/mldsa_lowmemory/src/mldsa.rs @@ -309,26 +309,33 @@ //! is still larger). //! Contact us if you need such a thing implemented. -use core::marker::PhantomData; -use crate::aux_functions::{sample_in_ball, bitpack_gamma1, bitlen_eta, unpack_h_row, unpack_c_tilde}; -use crate::low_memory_helpers::{compute_ct0_component, compute_w0cs2_component, compute_w_row, compute_wp_approx_row, compute_z_component, s_unpack}; -use crate::mldsa_keys::{MLDSAPublicKeyTrait, MLDSAPublicKeyInternalTrait}; -use crate::mldsa_keys::{MLDSAPrivateKeyTrait, MLDSAPrivateKeyInternalTrait}; -use crate::{MLDSA44PublicKey, MLDSA44PrivateKey, MLDSA65PublicKey, MLDSA65PrivateKey, MLDSA87PublicKey, MLDSA87PrivateKey}; +use crate::aux_functions::{ + bitlen_eta, bitpack_gamma1, sample_in_ball, unpack_c_tilde, unpack_h_row, +}; +use crate::low_memory_helpers::{ + compute_ct0_component, compute_w_row, compute_w0cs2_component, compute_wp_approx_row, + compute_z_component, s_unpack, +}; +use crate::mldsa_keys::{MLDSAPrivateKeyInternalTrait, MLDSAPrivateKeyTrait}; +use crate::mldsa_keys::{MLDSAPublicKeyInternalTrait, MLDSAPublicKeyTrait}; +use crate::{ + MLDSA44PrivateKey, MLDSA44PublicKey, MLDSA65PrivateKey, MLDSA65PublicKey, MLDSA87PrivateKey, + MLDSA87PublicKey, +}; use bouncycastle_core::errors::SignatureError; -use bouncycastle_core::key_material::{KeyMaterial}; -use bouncycastle_core::traits::{RNG, SecurityStrength, XOF, Signature, Algorithm}; -use bouncycastle_rng::{HashDRBG_SHA512}; +use bouncycastle_core::key_material::KeyMaterial; +use bouncycastle_core::traits::{Algorithm, RNG, SecurityStrength, Signature, XOF}; +use bouncycastle_rng::HashDRBG_SHA512; use bouncycastle_sha3::{SHAKE128, SHAKE256}; - +use core::marker::PhantomData; // imports needed just for docs #[allow(unused_imports)] -use bouncycastle_core::traits::PHSignature; +use crate::hash_mldsa; #[allow(unused_imports)] use bouncycastle_core::key_material::KeyMaterial256; #[allow(unused_imports)] -use crate::hash_mldsa; +use bouncycastle_core::traits::PHSignature; /*** Constants ***/ /// @@ -354,7 +361,6 @@ pub const MLDSA_MU_LEN: usize = 64; pub(crate) const POLY_T0PACKED_LEN: usize = 416; pub(crate) const POLY_T1PACKED_LEN: usize = 320; - /* ML-DSA-44 params */ /// Length of the \[u8] holding a ML-DSA-44 public key. @@ -379,16 +385,15 @@ pub(crate) const MLDSA44_OMEGA: i32 = 80; pub(crate) const MLDSA44_C_TILDE: usize = 32; pub(crate) const MLDSA44_POLY_Z_PACKED_LEN: usize = 576; pub(crate) const MLDSA44_POLY_W1_PACKED_LEN: usize = 192; -pub(crate) const MLDSA44_S1_PACKED_LEN: usize = bitlen_eta(MLDSA44_ETA) * MLDSA44_l; // 384 bytes -pub(crate) const MLDSA44_S2_PACKED_LEN: usize = bitlen_eta(MLDSA44_ETA) * MLDSA44_k; // 384 bytes -pub(crate) const MLDSA44_T1_PACKED_LEN: usize = POLY_T1PACKED_LEN * MLDSA44_k; // 768 bytes -pub(crate) const MLDSA44_POLY_ETA_PACKED_LEN: usize = 32*3; -pub(crate) const MLDSA44_LAMBDA_over_4: usize = 128/4; +pub(crate) const MLDSA44_S1_PACKED_LEN: usize = bitlen_eta(MLDSA44_ETA) * MLDSA44_l; // 384 bytes +pub(crate) const MLDSA44_S2_PACKED_LEN: usize = bitlen_eta(MLDSA44_ETA) * MLDSA44_k; // 384 bytes +pub(crate) const MLDSA44_T1_PACKED_LEN: usize = POLY_T1PACKED_LEN * MLDSA44_k; // 768 bytes +pub(crate) const MLDSA44_POLY_ETA_PACKED_LEN: usize = 32 * 3; +pub(crate) const MLDSA44_LAMBDA_over_4: usize = 128 / 4; // Alg 32 // 1: 𝑐 ← 1 + bitlen (𝛾1 − 1) -pub(crate) const MLDSA44_GAMMA1_MASK_LEN: usize = 576; // 32*(1 + bitlen (𝛾1 − 1) ) - +pub(crate) const MLDSA44_GAMMA1_MASK_LEN: usize = 576; // 32*(1 + bitlen (𝛾1 − 1) ) /* ML-DSA-65 params */ @@ -414,18 +419,16 @@ pub(crate) const MLDSA65_OMEGA: i32 = 55; pub(crate) const MLDSA65_C_TILDE: usize = 48; pub(crate) const MLDSA65_POLY_Z_PACKED_LEN: usize = 640; pub(crate) const MLDSA65_POLY_W1_PACKED_LEN: usize = 128; -pub(crate) const MLDSA65_S1_PACKED_LEN: usize = bitlen_eta(MLDSA65_ETA) * MLDSA65_l; // 640 bytes -pub(crate) const MLDSA65_S2_PACKED_LEN: usize = bitlen_eta(MLDSA65_ETA) * MLDSA65_k; // 768 bytes -pub(crate) const MLDSA65_T1_PACKED_LEN: usize = POLY_T1PACKED_LEN * MLDSA65_k; // 1152 bytes -pub(crate) const MLDSA65_POLY_ETA_PACKED_LEN: usize = 32*4; -pub(crate) const MLDSA65_LAMBDA_over_4: usize = 192/4; +pub(crate) const MLDSA65_S1_PACKED_LEN: usize = bitlen_eta(MLDSA65_ETA) * MLDSA65_l; // 640 bytes +pub(crate) const MLDSA65_S2_PACKED_LEN: usize = bitlen_eta(MLDSA65_ETA) * MLDSA65_k; // 768 bytes +pub(crate) const MLDSA65_T1_PACKED_LEN: usize = POLY_T1PACKED_LEN * MLDSA65_k; // 1152 bytes +pub(crate) const MLDSA65_POLY_ETA_PACKED_LEN: usize = 32 * 4; +pub(crate) const MLDSA65_LAMBDA_over_4: usize = 192 / 4; // Alg 32 // 1: 𝑐 ← 1 + bitlen (𝛾1 − 1) pub(crate) const MLDSA65_GAMMA1_MASK_LEN: usize = 640; - - /* ML-DSA-87 params */ /// Length of the \[u8] holding a ML-DSA-87 public key. @@ -450,23 +453,20 @@ pub(crate) const MLDSA87_OMEGA: i32 = 75; pub(crate) const MLDSA87_C_TILDE: usize = 64; pub(crate) const MLDSA87_POLY_Z_PACKED_LEN: usize = 640; pub(crate) const MLDSA87_POLY_W1_PACKED_LEN: usize = 128; -pub(crate) const MLDSA87_S1_PACKED_LEN: usize = bitlen_eta(MLDSA87_ETA) * MLDSA87_l; // 672 bytes -pub(crate) const MLDSA87_S2_PACKED_LEN: usize = bitlen_eta(MLDSA87_ETA) * MLDSA87_k; // 768 bytes -pub(crate) const MLDSA87_T1_PACKED_LEN: usize = POLY_T1PACKED_LEN * MLDSA87_k; // 1024 bytes -pub(crate) const MLDSA87_POLY_ETA_PACKED_LEN: usize = 32*3; -pub(crate) const MLDSA87_LAMBDA_over_4: usize = 256/4; +pub(crate) const MLDSA87_S1_PACKED_LEN: usize = bitlen_eta(MLDSA87_ETA) * MLDSA87_l; // 672 bytes +pub(crate) const MLDSA87_S2_PACKED_LEN: usize = bitlen_eta(MLDSA87_ETA) * MLDSA87_k; // 768 bytes +pub(crate) const MLDSA87_T1_PACKED_LEN: usize = POLY_T1PACKED_LEN * MLDSA87_k; // 1024 bytes +pub(crate) const MLDSA87_POLY_ETA_PACKED_LEN: usize = 32 * 3; +pub(crate) const MLDSA87_LAMBDA_over_4: usize = 256 / 4; // Alg 32 // 1: 𝑐 ← 1 + bitlen (𝛾1 − 1) pub(crate) const MLDSA87_GAMMA1_MASK_LEN: usize = 640; - - // Typedefs just to make the algorithms look more like the FIPS 204 sample code. pub(crate) type H = SHAKE256; pub(crate) type G = SHAKE128; - /*** Pub Types ***/ /// The ML-DSA-44 algorithm. @@ -576,9 +576,28 @@ pub struct MLDSA< const SK_LEN: usize, const FULL_SK_LEN: usize, const SIG_LEN: usize, - PK: MLDSAPublicKeyTrait + MLDSAPublicKeyInternalTrait, - SK: MLDSAPrivateKeyTrait - + MLDSAPrivateKeyInternalTrait, + PK: MLDSAPublicKeyTrait + + MLDSAPublicKeyInternalTrait, + SK: MLDSAPrivateKeyTrait< + k, + l, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > + MLDSAPrivateKeyInternalTrait< + LAMBDA, + GAMMA2, + k, + l, + ETA, + S1_PACKED_LEN, + S2_PACKED_LEN, + PK_LEN, + SK_LEN, + >, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, @@ -620,9 +639,28 @@ impl< const SK_LEN: usize, const FULL_SK_LEN: usize, const SIG_LEN: usize, - PK: MLDSAPublicKeyTrait + MLDSAPublicKeyInternalTrait, - SK: MLDSAPrivateKeyTrait - + MLDSAPrivateKeyInternalTrait, + PK: MLDSAPublicKeyTrait + + MLDSAPublicKeyInternalTrait, + SK: MLDSAPrivateKeyTrait< + k, + l, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > + MLDSAPrivateKeyInternalTrait< + LAMBDA, + GAMMA2, + k, + l, + ETA, + S1_PACKED_LEN, + S2_PACKED_LEN, + PK_LEN, + SK_LEN, + >, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, @@ -641,38 +679,36 @@ impl< const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize, -> MLDSA< - PK_LEN, - SK_LEN, - FULL_SK_LEN, - SIG_LEN, - PK, - SK, - TAU, - LAMBDA, - GAMMA1, - GAMMA2, - k, - l, - ETA, - BETA, - OMEGA, - C_TILDE, - POLY_Z_PACKED_LEN, - POLY_W1_PACKED_LEN, - S1_PACKED_LEN, - S2_PACKED_LEN, - T1_PACKED_LEN, - POLY_ETA_PACKED_LEN, - LAMBDA_over_4, - GAMMA1_MASK_LEN, > + MLDSA< + PK_LEN, + SK_LEN, + FULL_SK_LEN, + SIG_LEN, + PK, + SK, + TAU, + LAMBDA, + GAMMA1, + GAMMA2, + k, + l, + ETA, + BETA, + OMEGA, + C_TILDE, + POLY_Z_PACKED_LEN, + POLY_W1_PACKED_LEN, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + POLY_ETA_PACKED_LEN, + LAMBDA_over_4, + GAMMA1_MASK_LEN, + > { /// Should still be ok in FIPS mode - pub fn keygen_from_os_rng() -> Result< - (PK, SK), - SignatureError, - > { + pub fn keygen_from_os_rng() -> Result<(PK, SK), SignatureError> { let mut seed = KeyMaterial::<32>::new(); HashDRBG_SHA512::new_from_os().fill_keymaterial_out(&mut seed)?; Self::keygen_internal(&seed) @@ -684,12 +720,7 @@ impl< /// the appropriate [SecurityStrength] for the requested ML-DSA parameter set. /// If you happen to have your seed in a larger KeyMaterial, you'll have to copy it using /// [KeyMaterial::from_key]. - pub(crate) fn keygen_internal( - seed: &KeyMaterial<32>, - ) -> Result< - (PK, SK), - SignatureError, - > { + pub(crate) fn keygen_internal(seed: &KeyMaterial<32>) -> Result<(PK, SK), SignatureError> { let sk = SK::from_keymaterial(seed)?; let pk = sk.derive_pk(); let pk = PK::new(pk.rho, pk.t1_packed); // stupid conversion, but it gets around these overly-generified rust types @@ -702,9 +733,28 @@ impl< const SK_LEN: usize, const FULL_SK_LEN: usize, const SIG_LEN: usize, - PK: MLDSAPublicKeyTrait + MLDSAPublicKeyInternalTrait, - SK: MLDSAPrivateKeyTrait - + MLDSAPrivateKeyInternalTrait, + PK: MLDSAPublicKeyTrait + + MLDSAPublicKeyInternalTrait, + SK: MLDSAPrivateKeyTrait< + k, + l, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > + MLDSAPrivateKeyInternalTrait< + LAMBDA, + GAMMA2, + k, + l, + eta, + S1_PACKED_LEN, + S2_PACKED_LEN, + PK_LEN, + SK_LEN, + >, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, @@ -723,32 +773,50 @@ impl< const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize, -> MLDSATrait for MLDSA< - PK_LEN, - SK_LEN, - FULL_SK_LEN, - SIG_LEN, - PK, - SK, - TAU, - LAMBDA, - GAMMA1, - GAMMA2, - k, - l, - eta, - BETA, - OMEGA, - C_TILDE, - POLY_Z_PACKED_LEN, - POLY_W1_PACKED_LEN, - S1_PACKED_LEN, - S2_PACKED_LEN, - T1_PACKED_LEN, - POLY_ETA_PACKED_LEN, - LAMBDA_over_4, - GAMMA1_MASK_LEN, -> { +> + MLDSATrait< + PK_LEN, + SK_LEN, + FULL_SK_LEN, + SIG_LEN, + PK, + SK, + LAMBDA, + GAMMA2, + k, + l, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + eta, + > + for MLDSA< + PK_LEN, + SK_LEN, + FULL_SK_LEN, + SIG_LEN, + PK, + SK, + TAU, + LAMBDA, + GAMMA1, + GAMMA2, + k, + l, + eta, + BETA, + OMEGA, + C_TILDE, + POLY_Z_PACKED_LEN, + POLY_W1_PACKED_LEN, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + POLY_ETA_PACKED_LEN, + LAMBDA_over_4, + GAMMA1_MASK_LEN, + > +{ /*** Key Generation and PK / SK consistency checks ***/ /// Imports a secret key from a seed. @@ -764,10 +832,7 @@ impl< fn keygen_from_seed_and_encoded( seed: &KeyMaterial<32>, encoded_sk: &[u8; SK_LEN], - ) -> Result< - (PK, SK), - SignatureError, - > { + ) -> Result<(PK, SK), SignatureError> { let (pk, sk) = Self::keygen_internal(seed)?; let sk_from_bytes = SK::sk_decode(encoded_sk); @@ -787,10 +852,7 @@ impl< /// (in which case a keygen_from_seed is run and then the pk's compared). /// /// Returns either `()` or [SignatureError::ConsistencyCheckFailed]. - fn keypair_consistency_check( - pk: &PK, - sk: &SK, - ) -> Result<(), SignatureError> { + fn keypair_consistency_check(pk: &PK, sk: &SK) -> Result<(), SignatureError> { // This is maybe a computationally heavy way to compare them, but it works let derived_pk = sk.derive_pk(); if derived_pk.compute_tr() == pk.compute_tr() { @@ -858,10 +920,7 @@ impl< /// This implements FIPS 204 Algorithm 7 with line 6 removed; a modification that is allowed by both /// FIPS 204 itself, as well as subsequent FAQ documents. /// This mode uses randomized signing (called "hedged mode" in FIPS 204) using an internal RNG. - fn sign_mu( - sk: &SK, - mu: &[u8; 64], - ) -> Result<[u8; SIG_LEN], SignatureError> { + fn sign_mu(sk: &SK, mu: &[u8; 64]) -> Result<[u8; SIG_LEN], SignatureError> { let mut out: [u8; SIG_LEN] = [0u8; SIG_LEN]; Self::sign_mu_out(sk, mu, &mut out)?; Ok(out) @@ -883,7 +942,11 @@ impl< Self::sign_mu_deterministic_out(sk, mu, rnd, output) } - fn sign_mu_deterministic(sk: &SK, mu: &[u8; 64], rnd: [u8; 32]) -> Result<[u8; SIG_LEN], SignatureError> { + fn sign_mu_deterministic( + sk: &SK, + mu: &[u8; 64], + rnd: [u8; 32], + ) -> Result<[u8; SIG_LEN], SignatureError> { let mut out = [0u8; SIG_LEN]; let bytes_written = Self::sign_mu_deterministic_out(sk, mu, rnd, &mut out)?; debug_assert_eq!(bytes_written, SIG_LEN); @@ -898,7 +961,6 @@ impl< rnd: [u8; 32], output: &mut [u8; SIG_LEN], ) -> Result { - // I have tried to keep this as clean as possible for correspondence with the FIPS, // but I have moved things around so that I can use unnamed scopes to limit how many // stack variables are alive at the same time. @@ -949,11 +1011,17 @@ impl< } // 11-15: derive c_tilde without materializing y_hat or w as full vectors. - let sig_val_c_tilde = { // scope for hash + let sig_val_c_tilde = { + // scope for hash let mut hash = H::new(); hash.absorb(mu); for row in 0..k { - let mut w = compute_w_row::(&sk.rho(), &rho_p_p, kappa, row); + let mut w = compute_w_row::( + &sk.rho(), + &rho_p_p, + kappa, + row, + ); w.high_bits::(); hash.absorb(&w.w1_encode::()); } @@ -985,7 +1053,10 @@ impl< // maybe because re-computing the intermediates adds more to the widest point of the alg? // &sk.compute_s1_row(col), &s_unpack::(&s1_packed, col), - &rho_p_p, &c_hat, kappa, col, + &rho_p_p, + &c_hat, + kappa, + col, )? { Some(z) => z, None => { @@ -1005,26 +1076,30 @@ impl< // 19-28 (hint path): recompute rows as needed and write the packed hint directly. let mut hint_count = 0usize; for row in 0..k { - let mut w = compute_w_row::(&sk.rho(), &rho_p_p, kappa, row); - let mut tmp = - match compute_w0cs2_component::( - // [Optimization Note]: - // This is one of the places that a row of s1 can be re-computed instead of unpacked from the compressed form. - // &sk.compute_s2_row(row), - &s_unpack::(&s2_packed, row), - &w, &c_hat) { - Some(tmp) => tmp, - None => { - rejected = true; - break; - } - }; + let mut w = + compute_w_row::(&sk.rho(), &rho_p_p, kappa, row); + let mut tmp = match compute_w0cs2_component::( + // [Optimization Note]: + // This is one of the places that a row of s1 can be re-computed instead of unpacked from the compressed form. + // &sk.compute_s2_row(row), + &s_unpack::(&s2_packed, row), + &w, + &c_hat, + ) { + Some(tmp) => tmp, + None => { + rejected = true; + break; + } + }; let ct0 = match compute_ct0_component::( // [Optimization Note]: // This is one of the places that a row of s1 can be re-computed instead of unpacked from the compressed form. // &sk.compute_t0_row(row), &c_hat) { - &sk.compute_t0_row(row, &s1_packed, &s2_packed), &c_hat) { + &sk.compute_t0_row(row, &s1_packed, &s2_packed), + &c_hat, + ) { Some(ct0) => ct0, None => { rejected = true; @@ -1064,19 +1139,27 @@ impl< Ok(SIG_LEN) } - fn sign_mu_deterministic_from_seed(seed: &KeyMaterial<32>, mu: &[u8; 64], rnd: [u8; 32]) -> Result<[u8; SIG_LEN], SignatureError> { + fn sign_mu_deterministic_from_seed( + seed: &KeyMaterial<32>, + mu: &[u8; 64], + rnd: [u8; 32], + ) -> Result<[u8; SIG_LEN], SignatureError> { let mut out = [0u8; SIG_LEN]; SK::from_keymaterial(&seed)?; Self::sign_mu_deterministic_out(&SK::from_keymaterial(&seed)?, mu, rnd, &mut out)?; Ok(out) } - fn sign_mu_deterministic_from_seed_out(seed: &KeyMaterial<32>, mu: &[u8; 64], rnd: [u8; 32], output: &mut [u8; SIG_LEN]) -> Result { + fn sign_mu_deterministic_from_seed_out( + seed: &KeyMaterial<32>, + mu: &[u8; 64], + rnd: [u8; 32], + output: &mut [u8; SIG_LEN], + ) -> Result { SK::from_keymaterial(&seed)?; Self::sign_mu_deterministic_out(&SK::from_keymaterial(&seed)?, mu, rnd, output) } - /// To be used for deterministic signing in conjunction with the [MLDSA44::sign_init], [MLDSA44::sign_update], and [MLDSA44::sign_final] flow. /// Can be set anywhere after [MLDSA44::sign_init] and before [MLDSA44::sign_final] fn set_signer_rnd(&mut self, rnd: [u8; 32]) { @@ -1085,28 +1168,26 @@ impl< /// Alternative initialization of the streaming signer where you have your private key /// as a seed and you want to delay its expansion as late as possible for memory-usage reasons. - fn sign_init_from_seed(seed: &KeyMaterial<32>, ctx: Option<&[u8]>) -> Result { + fn sign_init_from_seed( + seed: &KeyMaterial<32>, + ctx: Option<&[u8]>, + ) -> Result { let (_pk, sk) = Self::keygen_from_seed(seed)?; - Ok( - Self { - _phantom: PhantomData, - mu_builder: MuBuilder::do_init(&sk.tr(), ctx)?, - signer_rnd: None, - sk: None, - seed: Some(seed.clone()), - pk: None } - ) + Ok(Self { + _phantom: PhantomData, + mu_builder: MuBuilder::do_init(&sk.tr(), ctx)?, + signer_rnd: None, + sk: None, + seed: Some(seed.clone()), + pk: None, + }) } /// Algorithm 8 ML-DSA.Verify_internal(𝑝𝑘, 𝑀′, 𝜎) /// Internal function to verify a signature 𝜎 for a formatted message 𝑀′ . /// Input: Public key 𝑝𝑘 ∈ 𝔹32+32𝑘(bitlen (𝑞−1)−𝑑) and message 𝑀′ ∈ {0, 1}∗ . /// Input: Signature 𝜎 ∈ 𝔹𝜆/4+ℓ⋅32⋅(1+bitlen (𝛾1−1))+𝜔+𝑘. - fn verify_mu_internal( - pk: &PK, - mu: &[u8; 64], - sig: &[u8; SIG_LEN], - ) -> bool { + fn verify_mu_internal(pk: &PK, mu: &[u8; 64], sig: &[u8; SIG_LEN]) -> bool { // 1: (𝜌, 𝐭1) ← pkDecode(𝑝𝑘) // Already done -- the pk struct is already decoded @@ -1137,19 +1218,27 @@ impl< sig, &pk.unpack_t1_row(row), &c, - row) + row, + ) } { Ok(wp_approx) => wp_approx, // means the norm check on z failed Err(_) => return false, }; - let h_i - = match unpack_h_row:: - (row, &sig) { - Some(h_i) => h_i, - // means there were more than OMEGA bits set in the hint - None => return false, + let h_i = match unpack_h_row::< + GAMMA1, + k, + l, + OMEGA, + LAMBDA_over_4, + POLY_Z_PACKED_LEN, + SIG_LEN, + >(row, &sig) + { + Some(h_i) => h_i, + // means there were more than OMEGA bits set in the hint + None => return false, }; // 10: 𝐰1′ ← UseHint(𝐡, 𝐰'_approx) @@ -1175,9 +1264,28 @@ pub trait MLDSATrait< const SK_LEN: usize, const FULL_SK_LEN: usize, const SIG_LEN: usize, - PK: MLDSAPublicKeyTrait + MLDSAPublicKeyInternalTrait, - SK: MLDSAPrivateKeyTrait - + MLDSAPrivateKeyInternalTrait, + PK: MLDSAPublicKeyTrait + + MLDSAPublicKeyInternalTrait, + SK: MLDSAPrivateKeyTrait< + k, + l, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > + MLDSAPrivateKeyInternalTrait< + LAMBDA, + GAMMA2, + k, + l, + ETA, + S1_PACKED_LEN, + S2_PACKED_LEN, + PK_LEN, + SK_LEN, + >, const LAMBDA: i32, const GAMMA2: i32, const k: usize, @@ -1185,8 +1293,9 @@ pub trait MLDSATrait< const S1_PACKED_LEN: usize, const S2_PACKED_LEN: usize, const T1_PACKED_LEN: usize, - const ETA: usize -> : Sized { + const ETA: usize, +>: Sized +{ /// Imports a secret key from a seed. fn keygen_from_seed(seed: &KeyMaterial<32>) -> Result<(PK, SK), SignatureError>; /// Imports a secret key from both a seed and an encoded_sk. @@ -1198,10 +1307,7 @@ pub trait MLDSATrait< fn keygen_from_seed_and_encoded( seed: &KeyMaterial<32>, encoded_sk: &[u8; SK_LEN], - ) -> Result< - (PK, SK), - SignatureError, - >; + ) -> Result<(PK, SK), SignatureError>; /// Given a public key and a secret key, check that the public key matches the secret key. /// This is a sanity check that the public key was generated correctly from the secret key. /// @@ -1210,10 +1316,7 @@ pub trait MLDSATrait< /// (in which case a keygen_from_seed is run and then the pk's compared). /// /// Returns either `()` or [SignatureError::ConsistencyCheckFailed]. - fn keypair_consistency_check( - pk: &PK, - sk: &SK, - ) -> Result<(), SignatureError>; + fn keypair_consistency_check(pk: &PK, sk: &SK) -> Result<(), SignatureError>; /// This provides the first half of the "External Mu" interface to ML-DSA which is described /// in, and allowed under, NIST's FAQ that accompanies FIPS 204. /// @@ -1267,10 +1370,7 @@ pub trait MLDSATrait< /// This implements FIPS 204 Algorithm 7 with line 6 removed; a modification that is allowed by both /// FIPS 204 itself, as well as subsequent FAQ documents. /// This mode uses randomized signing (called "hedged mode" in FIPS 204) using an internal RNG. - fn sign_mu( - sk: &SK, - mu: &[u8; 64], - ) -> Result<[u8; SIG_LEN], SignatureError>; + fn sign_mu(sk: &SK, mu: &[u8; 64]) -> Result<[u8; SIG_LEN], SignatureError>; /// Performs an ML-DSA signature using the provided external message representative `mu`. /// This implements FIPS 204 Algorithm 7 with line 6 removed; a modification that is allowed by both /// FIPS 204 itself, as well as subsequent FAQ documents. @@ -1357,16 +1457,15 @@ pub trait MLDSATrait< /// Can be set anywhere after [MLDSA44::sign_init] and before [MLDSA44::sign_final] fn set_signer_rnd(&mut self, rnd: [u8; 32]); /// An alternate way to start the streaming signing mode by providing a private key seed instead of an expanded private key - fn sign_init_from_seed(seed: &KeyMaterial<32>, ctx: Option<&[u8]>) -> Result; + fn sign_init_from_seed( + seed: &KeyMaterial<32>, + ctx: Option<&[u8]>, + ) -> Result; /// Algorithm 8 ML-DSA.Verify_internal(𝑝𝑘, 𝑀′, 𝜎) /// Internal function to verify a signature 𝜎 for a formatted message 𝑀′ . /// Input: Public key 𝑝𝑘 ∈ 𝔹32+32𝑘(bitlen (𝑞−1)−𝑑) and message 𝑀′ ∈ {0, 1}∗ . /// Input: Signature 𝜎 ∈ 𝔹𝜆/4+ℓ⋅32⋅(1+bitlen (𝛾1−1))+𝜔+𝑘. - fn verify_mu_internal( - pk: &PK, - mu: &[u8; 64], - sig: &[u8; SIG_LEN], - ) -> bool; + fn verify_mu_internal(pk: &PK, mu: &[u8; 64], sig: &[u8; SIG_LEN]) -> bool; } impl< @@ -1374,9 +1473,28 @@ impl< const SK_LEN: usize, const FULL_SK_LEN: usize, const SIG_LEN: usize, - PK: MLDSAPublicKeyTrait + MLDSAPublicKeyInternalTrait, - SK: MLDSAPrivateKeyTrait - + MLDSAPrivateKeyInternalTrait, + PK: MLDSAPublicKeyTrait + + MLDSAPublicKeyInternalTrait, + SK: MLDSAPrivateKeyTrait< + k, + l, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > + MLDSAPrivateKeyInternalTrait< + LAMBDA, + GAMMA2, + k, + l, + ETA, + S1_PACKED_LEN, + S2_PACKED_LEN, + PK_LEN, + SK_LEN, + >, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, @@ -1395,33 +1513,34 @@ impl< const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize, -> Signature for MLDSA< - PK_LEN, - SK_LEN, - FULL_SK_LEN, - SIG_LEN, - PK, - SK, - TAU, - LAMBDA, - GAMMA1, - GAMMA2, - k, - l, - ETA, - BETA, - OMEGA, - C_TILDE, - POLY_Z_PACKED_LEN, - POLY_W1_PACKED_LEN, - S1_PACKED_LEN, - S2_PACKED_LEN, - T1_PACKED_LEN, - POLY_ETA_PACKED_LEN, - LAMBDA_over_4, - GAMMA1_MASK_LEN, -> { - +> Signature + for MLDSA< + PK_LEN, + SK_LEN, + FULL_SK_LEN, + SIG_LEN, + PK, + SK, + TAU, + LAMBDA, + GAMMA1, + GAMMA2, + k, + l, + ETA, + BETA, + OMEGA, + C_TILDE, + POLY_Z_PACKED_LEN, + POLY_W1_PACKED_LEN, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + POLY_ETA_PACKED_LEN, + LAMBDA_over_4, + GAMMA1_MASK_LEN, + > +{ fn keygen() -> Result<(PK, SK), SignatureError> { Self::keygen_from_os_rng() } @@ -1433,7 +1552,12 @@ impl< Ok(out) } - fn sign_out(sk: &SK, msg: &[u8], ctx: Option<&[u8]>, output: &mut [u8; SIG_LEN]) -> Result { + fn sign_out( + sk: &SK, + msg: &[u8], + ctx: Option<&[u8]>, + output: &mut [u8; SIG_LEN], + ) -> Result { let mu = MuBuilder::compute_mu(&sk.tr(), msg, ctx)?; let bytes_written = Self::sign_mu_out(sk, &mu, output)?; @@ -1441,15 +1565,14 @@ impl< } fn sign_init(sk: &SK, ctx: Option<&[u8]>) -> Result { - Ok( - Self { - _phantom: PhantomData, - mu_builder: MuBuilder::do_init(&sk.tr(), ctx)?, - signer_rnd: None, - sk: Some(sk.clone()), - seed: None, - pk: None } - ) + Ok(Self { + _phantom: PhantomData, + mu_builder: MuBuilder::do_init(&sk.tr(), ctx)?, + signer_rnd: None, + sk: Some(sk.clone()), + seed: None, + pk: None, + }) } fn sign_update(&mut self, msg_chunk: &[u8]) { @@ -1466,17 +1589,28 @@ impl< let mu = self.mu_builder.do_final(); if self.sk.is_none() && self.seed.is_none() { - return Err(SignatureError::GenericError("Somehow you managed to construct a streaming signer without a private key, impressive!")) + return Err(SignatureError::GenericError( + "Somehow you managed to construct a streaming signer without a private key, impressive!", + )); } - if output.len() < SIG_LEN { return Err(SignatureError::LengthError("Output buffer insufficient size to hold signature")) } + if output.len() < SIG_LEN { + return Err(SignatureError::LengthError( + "Output buffer insufficient size to hold signature", + )); + } let output_sized: &mut [u8; SIG_LEN] = output[..SIG_LEN].as_mut().try_into().unwrap(); if self.sk.is_some() { if self.signer_rnd.is_none() { Self::sign_mu_out(&self.sk.unwrap(), &mu, output_sized) } else { - Self::sign_mu_deterministic_out(&self.sk.unwrap(), &mu, self.signer_rnd.unwrap(), output_sized) + Self::sign_mu_deterministic_out( + &self.sk.unwrap(), + &mu, + self.signer_rnd.unwrap(), + output_sized, + ) } } else if self.seed.is_some() { let rnd = if self.signer_rnd.is_some() { @@ -1487,13 +1621,17 @@ impl< rnd }; Self::sign_mu_deterministic_from_seed_out(&self.seed.unwrap(), &mu, rnd, output_sized) - } else { unreachable!() } + } else { + unreachable!() + } } fn verify(pk: &PK, msg: &[u8], ctx: Option<&[u8]>, sig: &[u8]) -> Result<(), SignatureError> { let mu = MuBuilder::compute_mu(&pk.compute_tr(), msg, ctx)?; - if sig.len() < SIG_LEN { return Err(SignatureError::LengthError("Signature value is not the correct length.")) } + if sig.len() < SIG_LEN { + return Err(SignatureError::LengthError("Signature value is not the correct length.")); + } if Self::verify_mu_internal(pk, &mu, &sig[..SIG_LEN].try_into().unwrap()) { Ok(()) } else { @@ -1502,15 +1640,14 @@ impl< } fn verify_init(pk: &PK, ctx: Option<&[u8]>) -> Result { - Ok( - Self { - _phantom: Default::default(), - mu_builder: MuBuilder::do_init(&pk.compute_tr(), ctx)?, - signer_rnd: None, - sk: None, - seed: None, - pk: Some(pk.clone()) } - ) + Ok(Self { + _phantom: Default::default(), + mu_builder: MuBuilder::do_init(&pk.compute_tr(), ctx)?, + signer_rnd: None, + sk: None, + seed: None, + pk: Some(pk.clone()), + }) } fn verify_update(&mut self, msg_chunk: &[u8]) { @@ -1520,9 +1657,14 @@ impl< fn verify_final(self, sig: &[u8]) -> Result<(), SignatureError> { let mu = self.mu_builder.do_final(); - assert!(self.pk.is_some(), "Somehow you managed to construct a streaming verifier without a public key, impressive!"); + assert!( + self.pk.is_some(), + "Somehow you managed to construct a streaming verifier without a public key, impressive!" + ); - if sig.len() < SIG_LEN { return Err(SignatureError::LengthError("Signature value is not the correct length.")) } + if sig.len() < SIG_LEN { + return Err(SignatureError::LengthError("Signature value is not the correct length.")); + } if Self::verify_mu_internal(&self.pk.unwrap(), &mu, &sig[..SIG_LEN].try_into().unwrap()) { Ok(()) } else { @@ -1531,7 +1673,6 @@ impl< } } - /// Implements parts of Algorithm 2 and Line 6 of Algorithm 7 of FIPS 204. /// Provides a stateful version of [MLDSATrait::compute_mu_from_pk] and [MLDSATrait::compute_mu_from_tr] /// that supports streaming @@ -1548,7 +1689,11 @@ pub struct MuBuilder { impl MuBuilder { /// Algorithm 7 /// 6: 𝜇 ← H(BytesToBits(𝑡𝑟)||𝑀′, 64) - pub fn compute_mu(tr: &[u8; 64],msg: &[u8], ctx: Option<&[u8]>) -> Result<[u8; 64], SignatureError> { + pub fn compute_mu( + tr: &[u8; 64], + msg: &[u8], + ctx: Option<&[u8]>, + ) -> Result<[u8; 64], SignatureError> { let mut mu_builder = MuBuilder::do_init(&tr, ctx)?; mu_builder.do_update(msg); let mu = mu_builder.do_final(); @@ -1559,7 +1704,10 @@ impl MuBuilder { /// This function requires the public key hash `tr`, which can be computed from the public key /// using [MLDSAPublicKeyTrait::compute_tr]. pub fn do_init(tr: &[u8; 64], ctx: Option<&[u8]>) -> Result { - let ctx = match ctx { Some(ctx) => ctx, None => &[] }; + let ctx = match ctx { + Some(ctx) => ctx, + None => &[], + }; // Algorithm 2 // 1: if |𝑐𝑡𝑥| > 255 then diff --git a/crypto/mldsa_lowmemory/src/mldsa_keys.rs b/crypto/mldsa_lowmemory/src/mldsa_keys.rs index 66b70aa..ac50f73 100644 --- a/crypto/mldsa_lowmemory/src/mldsa_keys.rs +++ b/crypto/mldsa_lowmemory/src/mldsa_keys.rs @@ -1,14 +1,30 @@ -use crate::aux_functions::{bit_pack_eta, bit_pack_t0, bitlen_eta, power_2_round, rej_bounded_poly, simple_bit_pack_t1, simple_bit_unpack_t1}; +use crate::aux_functions::{ + bit_pack_eta, bit_pack_t0, bitlen_eta, power_2_round, rej_bounded_poly, simple_bit_pack_t1, + simple_bit_unpack_t1, +}; +use crate::low_memory_helpers::{expandA_elem, s_unpack}; use crate::mldsa::{H, N, POLY_T0PACKED_LEN}; +use crate::mldsa::{ + MLDSA44_ETA, MLDSA44_FULL_SK_LEN, MLDSA44_GAMMA2, MLDSA44_LAMBDA, MLDSA44_PK_LEN, + MLDSA44_S1_PACKED_LEN, MLDSA44_S2_PACKED_LEN, MLDSA44_SK_LEN, MLDSA44_k, MLDSA44_l, +}; +use crate::mldsa::{ + MLDSA44_T1_PACKED_LEN, MLDSA65_T1_PACKED_LEN, MLDSA87_T1_PACKED_LEN, POLY_T1PACKED_LEN, +}; +use crate::mldsa::{ + MLDSA65_ETA, MLDSA65_FULL_SK_LEN, MLDSA65_GAMMA2, MLDSA65_LAMBDA, MLDSA65_PK_LEN, + MLDSA65_S1_PACKED_LEN, MLDSA65_S2_PACKED_LEN, MLDSA65_SK_LEN, MLDSA65_k, MLDSA65_l, +}; +use crate::mldsa::{ + MLDSA87_ETA, MLDSA87_FULL_SK_LEN, MLDSA87_GAMMA2, MLDSA87_LAMBDA, MLDSA87_PK_LEN, + MLDSA87_S1_PACKED_LEN, MLDSA87_S2_PACKED_LEN, MLDSA87_SK_LEN, MLDSA87_k, MLDSA87_l, +}; use crate::{ML_DSA_44_NAME, ML_DSA_65_NAME, ML_DSA_87_NAME}; -use crate::mldsa::{MLDSA44_LAMBDA, MLDSA44_GAMMA2, MLDSA44_ETA, MLDSA44_PK_LEN, MLDSA44_SK_LEN, MLDSA44_FULL_SK_LEN, MLDSA44_k, MLDSA44_l, MLDSA44_S1_PACKED_LEN, MLDSA44_S2_PACKED_LEN}; -use crate::mldsa::{MLDSA65_LAMBDA, MLDSA65_GAMMA2, MLDSA65_ETA, MLDSA65_PK_LEN, MLDSA65_SK_LEN, MLDSA65_FULL_SK_LEN, MLDSA65_k, MLDSA65_l, MLDSA65_S1_PACKED_LEN, MLDSA65_S2_PACKED_LEN}; -use crate::mldsa::{MLDSA87_LAMBDA, MLDSA87_GAMMA2, MLDSA87_ETA, MLDSA87_PK_LEN, MLDSA87_SK_LEN, MLDSA87_FULL_SK_LEN, MLDSA87_k, MLDSA87_l, MLDSA87_S1_PACKED_LEN, MLDSA87_S2_PACKED_LEN}; -use crate::mldsa::{POLY_T1PACKED_LEN, MLDSA44_T1_PACKED_LEN, MLDSA65_T1_PACKED_LEN, MLDSA87_T1_PACKED_LEN}; -use crate::low_memory_helpers::{expandA_elem, s_unpack}; use bouncycastle_core::errors::SignatureError; use bouncycastle_core::key_material::{KeyMaterial, KeyMaterialTrait, KeyType}; -use bouncycastle_core::traits::{Secret, SecurityStrength, SignaturePrivateKey, SignaturePublicKey, XOF}; +use bouncycastle_core::traits::{ + Secret, SecurityStrength, SignaturePrivateKey, SignaturePublicKey, XOF, +}; use core::fmt; use core::fmt::{Debug, Display, Formatter}; @@ -17,21 +33,56 @@ use core::fmt::{Debug, Display, Formatter}; use crate::mldsa::MLDSATrait; use crate::polynomial::Polynomial; - /* Pub Types */ /// ML-DSA-44 Public Key pub type MLDSA44PublicKey = MLDSAPublicKey; /// ML-DSA-44 Private Key -pub type MLDSA44PrivateKey = MLDSASeedPrivateKey; +pub type MLDSA44PrivateKey = MLDSASeedPrivateKey< + MLDSA44_LAMBDA, + MLDSA44_GAMMA2, + MLDSA44_k, + MLDSA44_l, + MLDSA44_ETA, + MLDSA44_S1_PACKED_LEN, + MLDSA44_S2_PACKED_LEN, + MLDSA44_T1_PACKED_LEN, + MLDSA44_PK_LEN, + MLDSA44_SK_LEN, + MLDSA44_FULL_SK_LEN, +>; /// ML-DSA-65 Public Key pub type MLDSA65PublicKey = MLDSAPublicKey; /// ML-DSA-65 Private Key -pub type MLDSA65PrivateKey = MLDSASeedPrivateKey; +pub type MLDSA65PrivateKey = MLDSASeedPrivateKey< + MLDSA65_LAMBDA, + MLDSA65_GAMMA2, + MLDSA65_k, + MLDSA65_l, + MLDSA65_ETA, + MLDSA65_S1_PACKED_LEN, + MLDSA65_S2_PACKED_LEN, + MLDSA65_T1_PACKED_LEN, + MLDSA65_PK_LEN, + MLDSA65_SK_LEN, + MLDSA65_FULL_SK_LEN, +>; /// ML-DSA-87 Public Key pub type MLDSA87PublicKey = MLDSAPublicKey; /// ML-DSA-87 Private Key -pub type MLDSA87PrivateKey = MLDSASeedPrivateKey; +pub type MLDSA87PrivateKey = MLDSASeedPrivateKey< + MLDSA87_LAMBDA, + MLDSA87_GAMMA2, + MLDSA87_k, + MLDSA87_l, + MLDSA87_ETA, + MLDSA87_S1_PACKED_LEN, + MLDSA87_S2_PACKED_LEN, + MLDSA87_T1_PACKED_LEN, + MLDSA87_PK_LEN, + MLDSA87_SK_LEN, + MLDSA87_FULL_SK_LEN, +>; /// An ML-DSA public key. #[derive(Clone)] @@ -41,7 +92,9 @@ pub struct MLDSAPublicKey : SignaturePublicKey { +pub trait MLDSAPublicKeyTrait: + SignaturePublicKey +{ /// Algorithm 23 pkDecode(𝑝𝑘) /// Reverses the procedure pkEncode. /// Input: Public key 𝑝𝑘 ∈ 𝔹32+32𝑘(bitlen (𝑞−1)−𝑑). @@ -57,7 +110,12 @@ pub trait MLDSAPublicKeyTrait [u8; 64]; } -pub(crate) trait MLDSAPublicKeyInternalTrait { +pub(crate) trait MLDSAPublicKeyInternalTrait< + const k: usize, + const T1_PACKED_LEN: usize, + const PK_LEN: usize, +> +{ /// Not exposing a constructor publicly because you should have to get an instance either by /// running a keygen, or by decoding an existing key. fn new(rho: [u8; 32], t1_packed: [u8; T1_PACKED_LEN]) -> Self; @@ -69,12 +127,11 @@ pub(crate) trait MLDSAPublicKeyInternalTrait Polynomial; } -impl MLDSAPublicKeyTrait for MLDSAPublicKey { +impl + MLDSAPublicKeyTrait for MLDSAPublicKey +{ fn pk_decode(pk: &[u8; PK_LEN]) -> Self { - Self { - rho: pk[..32].try_into().unwrap(), - t1_packed: pk[32..].try_into().unwrap() - } + Self { rho: pk[..32].try_into().unwrap(), t1_packed: pk[32..].try_into().unwrap() } } fn compute_tr(&self) -> [u8; 64] { @@ -85,19 +142,30 @@ impl MLDSAPubli } } -impl MLDSAPublicKeyInternalTrait for MLDSAPublicKey { +impl + MLDSAPublicKeyInternalTrait + for MLDSAPublicKey +{ fn new(rho: [u8; 32], t1_packed: [u8; T1_PACKED_LEN]) -> Self { Self { rho, t1_packed } } - fn rho(&self) -> &[u8; 32] { &self.rho } + fn rho(&self) -> &[u8; 32] { + &self.rho + } fn unpack_t1_row(&self, row: usize) -> Polynomial { - simple_bit_unpack_t1(&self.t1_packed[row * POLY_T1PACKED_LEN .. (row + 1) * POLY_T1PACKED_LEN].try_into().unwrap()) + simple_bit_unpack_t1( + &self.t1_packed[row * POLY_T1PACKED_LEN..(row + 1) * POLY_T1PACKED_LEN] + .try_into() + .unwrap(), + ) } } -impl SignaturePublicKey for MLDSAPublicKey { +impl SignaturePublicKey + for MLDSAPublicKey +{ /// Algorithm 22 pkEncode(𝜌, 𝐭1) /// Encodes a public key for ML-DSA into a byte string. /// Input:𝜌 ∈ 𝔹32, 𝐭1 ∈ 𝑅𝑘 with coefficients in [0, 2bitlen (𝑞−1)−𝑑 − 1]. @@ -122,15 +190,24 @@ impl Signature } fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != PK_LEN { return Err(SignatureError::DecodingError("Provided key bytes are the incorrect length")) } + if bytes.len() != PK_LEN { + return Err(SignatureError::DecodingError( + "Provided key bytes are the incorrect length", + )); + } let sized_bytes: [u8; PK_LEN] = bytes[..PK_LEN].try_into().unwrap(); Ok(Self::pk_decode(&sized_bytes)) } } -impl Eq for MLDSAPublicKey { } +impl Eq + for MLDSAPublicKey +{ +} -impl PartialEq for MLDSAPublicKey { +impl PartialEq + for MLDSAPublicKey +{ fn eq(&self, other: &Self) -> bool { let self_encoded = self.encode(); let other_encoded = other.encode(); @@ -138,7 +215,9 @@ impl PartialEq } } -impl fmt::Debug for MLDSAPublicKey { +impl fmt::Debug + for MLDSAPublicKey +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let alg = match k { 4 => ML_DSA_44_NAME, @@ -150,7 +229,9 @@ impl fmt::Debug } } -impl Display for MLDSAPublicKey { +impl Display + for MLDSAPublicKey +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let alg = match k { 4 => ML_DSA_44_NAME, @@ -162,8 +243,6 @@ impl Display fo } } - - /// General trait for all ML-DSA private keys types. pub trait MLDSAPrivateKeyTrait< const k: usize, @@ -174,7 +253,8 @@ pub trait MLDSAPrivateKeyTrait< const PK_LEN: usize, const SK_LEN: usize, const FULL_SK_LEN: usize, -> : SignaturePrivateKey { +>: SignaturePrivateKey +{ /// New from KeyMaterial. Can throw a SignatureError if the KeyMaterial does not contain sufficient entropy. fn from_keymaterial(seed: &KeyMaterial<32>) -> Result; @@ -244,7 +324,6 @@ pub struct MLDSASeedPrivateKey< K: [u8; 32], } - impl< const LAMBDA: i32, const GAMMA2: i32, @@ -257,7 +336,21 @@ impl< const SK_LEN: usize, const PK_LEN: usize, const FULL_SK_LEN: usize, -> Drop for MLDSASeedPrivateKey { +> Drop + for MLDSASeedPrivateKey< + LAMBDA, + GAMMA2, + k, + l, + eta, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > +{ fn drop(&mut self) { // seed is a KeyMaterialSized which will zeroize itself self.rho.fill(0u8); @@ -278,7 +371,22 @@ impl< const PK_LEN: usize, const SK_LEN: usize, const FULL_SK_LEN: usize, -> Secret for MLDSASeedPrivateKey {} +> Secret + for MLDSASeedPrivateKey< + LAMBDA, + GAMMA2, + k, + l, + eta, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > +{ +} impl< const LAMBDA: i32, @@ -292,7 +400,21 @@ impl< const PK_LEN: usize, const SK_LEN: usize, const FULL_SK_LEN: usize, -> Debug for MLDSASeedPrivateKey { +> Debug + for MLDSASeedPrivateKey< + LAMBDA, + GAMMA2, + k, + l, + eta, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let alg = match k { 4 => ML_DSA_44_NAME, @@ -300,12 +422,7 @@ impl< 8 => ML_DSA_87_NAME, _ => panic!("Unsupported key length"), }; - write!( - f, - "MLDSASeedPrivateKey {{ alg: {}, pub_key_hash (tr): {:x?} }}", - alg, - self.tr(), - ) + write!(f, "MLDSASeedPrivateKey {{ alg: {}, pub_key_hash (tr): {:x?} }}", alg, self.tr(),) } } @@ -321,7 +438,21 @@ impl< const PK_LEN: usize, const SK_LEN: usize, const FULL_SK_LEN: usize, -> Display for MLDSASeedPrivateKey { +> Display + for MLDSASeedPrivateKey< + LAMBDA, + GAMMA2, + k, + l, + eta, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let alg = match k { 4 => ML_DSA_44_NAME, @@ -329,12 +460,7 @@ impl< 8 => ML_DSA_87_NAME, _ => panic!("Unsupported key length"), }; - write!( - f, - "MLDSASeedPrivateKey {{ alg: {}, pub_key_hash (tr): {:x?} }}", - alg, - self.tr(), - ) + write!(f, "MLDSASeedPrivateKey {{ alg: {}, pub_key_hash (tr): {:x?} }}", alg, self.tr(),) } } @@ -350,13 +476,27 @@ impl< const PK_LEN: usize, const SK_LEN: usize, const FULL_SK_LEN: usize, -> MLDSASeedPrivateKey { +> + MLDSASeedPrivateKey< + LAMBDA, + GAMMA2, + k, + l, + eta, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > +{ /// Create a new MLDSASeedPrivateKey from a 32-byte KeyMaterial. /// Seed SecurityStrength must match algorithm security strength: 128-bit (ML-DSA-44), 192-bit (ML-DSA-65), or 256-bit (ML-DSA-87), /// otherwise it throws a SignatureError::KeyGenError("SecurityStrength". pub fn new(seed: &KeyMaterial<32>) -> Result { if !(seed.key_type() == KeyType::Seed || seed.key_type() == KeyType::BytesFullEntropy) - || seed.key_len() != 32 + || seed.key_len() != 32 { return Err(SignatureError::KeyGenError( "Seed must be 32 bytes and KeyType::Seed or KeyType::BytesFullEntropy.", @@ -368,7 +508,7 @@ impl< } let (rho, rho_prime, K) = Self::compute_rhos_and_K(&seed); - Ok(Self { seed: seed.clone(), rho, rho_prime, K}) + Ok(Self { seed: seed.clone(), rho, rho_prime, K }) } fn compute_rhos_and_K(seed: &KeyMaterial<32>) -> ([u8; 32], [u8; 64], [u8; 32]) { @@ -393,12 +533,7 @@ impl< (rho, rho_prime, K) } - fn compute_t_row( - &self, - idx: usize, - s1_packed: &[u8], - s2_packed: &[u8], - ) -> Polynomial { + fn compute_t_row(&self, idx: usize, s1_packed: &[u8], s2_packed: &[u8]) -> Polynomial { debug_assert!(idx < k); // [Optimization Note]: @@ -456,7 +591,21 @@ impl< const PK_LEN: usize, const SK_LEN: usize, const FULL_SK_LEN: usize, -> SignaturePrivateKey for MLDSASeedPrivateKey { +> SignaturePrivateKey + for MLDSASeedPrivateKey< + LAMBDA, + GAMMA2, + k, + l, + eta, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > +{ /// Encodes the private key seed. fn encode(&self) -> [u8; SK_LEN] { debug_assert_eq!(SK_LEN, /* seed */ 32); @@ -497,13 +646,38 @@ impl< const PK_LEN: usize, const SK_LEN: usize, const FULL_SK_LEN: usize, -> MLDSAPrivateKeyTrait -for MLDSASeedPrivateKey { +> + MLDSAPrivateKeyTrait< + k, + l, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > + for MLDSASeedPrivateKey< + LAMBDA, + GAMMA2, + k, + l, + eta, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > +{ fn from_keymaterial(seed: &KeyMaterial<32>) -> Result { Self::new(seed) } - fn seed(&self) -> &KeyMaterial<32> { &self.seed } + fn seed(&self) -> &KeyMaterial<32> { + &self.seed + } fn tr(&self) -> [u8; 64] { let pk: MLDSAPublicKey = self.derive_pk(); @@ -520,10 +694,9 @@ for MLDSASeedPrivateKey::new(self.rho.clone(), t1_packed) @@ -556,25 +729,23 @@ for MLDSASeedPrivateKey : Sized +>: Sized { fn rho(&self) -> &[u8; 32]; fn K(&self) -> &[u8; 32]; @@ -624,8 +795,32 @@ impl< const PK_LEN: usize, const SK_LEN: usize, const FULL_SK_LEN: usize, -> MLDSAPrivateKeyInternalTrait -for MLDSASeedPrivateKey { +> + MLDSAPrivateKeyInternalTrait< + LAMBDA, + GAMMA2, + k, + l, + eta, + S1_PACKED_LEN, + S2_PACKED_LEN, + PK_LEN, + SK_LEN, + > + for MLDSASeedPrivateKey< + LAMBDA, + GAMMA2, + k, + l, + eta, + S1_PACKED_LEN, + S2_PACKED_LEN, + T1_PACKED_LEN, + PK_LEN, + SK_LEN, + FULL_SK_LEN, + > +{ fn rho(&self) -> &[u8; 32] { &self.rho } @@ -634,10 +829,7 @@ for MLDSASeedPrivateKey Polynomial { + fn compute_s1_row(&self, idx: usize) -> Polynomial { debug_assert!(idx < l); rej_bounded_poly::(&self.rho_prime, &(idx as u16).to_le_bytes()) } @@ -646,15 +838,15 @@ for MLDSASeedPrivateKey(&s1_i, &mut s1_packed[idx * bitlen_eta(eta)..(idx + 1) * bitlen_eta(eta)]); + bit_pack_eta::( + &s1_i, + &mut s1_packed[idx * bitlen_eta(eta)..(idx + 1) * bitlen_eta(eta)], + ); } s1_packed } - fn compute_s2_row( - &self, - idx: usize, - ) -> Polynomial { + fn compute_s2_row(&self, idx: usize) -> Polynomial { debug_assert!(idx < k); rej_bounded_poly::(&self.rho_prime, &((idx + l) as u16).to_le_bytes()) } @@ -663,17 +855,15 @@ for MLDSASeedPrivateKey(&s2_i, &mut s2_packed[idx * bitlen_eta(eta)..(idx + 1) * bitlen_eta(eta)]); + bit_pack_eta::( + &s2_i, + &mut s2_packed[idx * bitlen_eta(eta)..(idx + 1) * bitlen_eta(eta)], + ); } s2_packed } - fn compute_t0_row( - &self, - idx: usize, - s1_packed: &[u8], - s2_packed: &[u8], - ) -> Polynomial { + fn compute_t0_row(&self, idx: usize, s1_packed: &[u8], s2_packed: &[u8]) -> Polynomial { let mut t0 = self.compute_t_row(idx, s1_packed, s2_packed); for j in 0..N { (_, t0[j]) = power_2_round(t0[j]); @@ -682,12 +872,7 @@ for MLDSASeedPrivateKey Polynomial { + fn compute_t1_row(&self, idx: usize, s1_packed: &[u8], s2_packed: &[u8]) -> Polynomial { let mut t1 = self.compute_t_row(idx, s1_packed, s2_packed); for j in 0..N { (t1[j], _) = power_2_round(t1[j]); @@ -696,4 +881,3 @@ for MLDSASeedPrivateKey for Polynomial { @@ -32,7 +34,7 @@ impl IndexMut for Polynomial { impl Polynomial { /// Create a new polynomial with all coefficients set to zero. pub const fn new() -> Self { - Self{ coeffs: [0i32; N] } + Self { coeffs: [0i32; N] } } pub(crate) fn conditional_add_q(&mut self) { @@ -128,29 +130,28 @@ impl Polynomial { // then it's free to optimize all of the computation into CPU registers and skip, in this case, // several hundred physical memory writes. // So while it looks odd to use a scope variable in a low-memory implementation, it's way faster - // and I'm not convinced that it uses any more physical memory. + // and I'm not convinced that it uses any more physical memory. let mut r = [0u8; POLY_W1_PACKED_LEN]; match POLY_W1_PACKED_LEN { MLDSA44_POLY_W1_PACKED_LEN => { - for i in 0..N/4 { - r[3 * i] = - ((self[4 * i]) as u8) | ((self[4 * i + 1] << 6) as u8); - r[3 * i + 1] = - ((self[4 * i + 1] >> 2) as u8) | ((self[4 * i + 2] << 4) as u8); - r[3 * i + 2] = - ((self[4 * i + 2] >> 4) as u8) | ((self[4 * i + 3] << 2) as u8); + for i in 0..N / 4 { + r[3 * i] = ((self[4 * i]) as u8) | ((self[4 * i + 1] << 6) as u8); + r[3 * i + 1] = ((self[4 * i + 1] >> 2) as u8) | ((self[4 * i + 2] << 4) as u8); + r[3 * i + 2] = ((self[4 * i + 2] >> 4) as u8) | ((self[4 * i + 3] << 2) as u8); } - }, + } // ML-DSA65 and 87 share a POLY_W1_PACKED_LEN value MLDSA65_POLY_W1_PACKED_LEN => { - for i in 0..N/2 { + for i in 0..N / 2 { r[i] = ((self[2 * i]) | (self[2 * i + 1] << 4)) as u8; } - }, - _ => { unreachable!() } + } + _ => { + unreachable!() + } } - + r } @@ -234,11 +235,7 @@ impl Polynomial { } } - - pub(crate) fn use_hint( - &mut self, - h: &Polynomial, - ) { + pub(crate) fn use_hint(&mut self, h: &Polynomial) { for i in 0..N { self[i] = use_hint::(self[i], h[i]); } @@ -270,7 +267,7 @@ impl Display for Polynomial { /// of expressions of the form c = a * b (mod q). /// The output is not necessarily less than q in absolute value, but it is less than 2q in absolute value pub(crate) fn montgomery_reduce(a: i64) -> i32 { - debug_assert!(a > - ((q as i64) <<31) && a < ((q as i64) <<31)); + debug_assert!(a > -((q as i64) << 31) && a < ((q as i64) << 31)); // 2: 𝑡 ← ((𝑎 mod 2^32) ⋅ QINV) mod 2^32 let t: i32 = (a as i32).wrapping_mul(q_inv); @@ -279,7 +276,6 @@ pub(crate) fn montgomery_reduce(a: i64) -> i32 { ((a - ((t as i64) * (q as i64))) >> 32) as i32 } - pub(crate) fn conditional_add_q(a: i32) -> i32 { a + ((a >> 31) & q) } @@ -287,16 +283,16 @@ pub(crate) fn conditional_add_q(a: i32) -> i32 { #[test] /// These are the results it's giving; I'm not sure if these are "correct" or not. fn test_conditional_add_q() { - assert_eq!(conditional_add_q(-q -1), -1); + assert_eq!(conditional_add_q(-q - 1), -1); assert_eq!(conditional_add_q(-q), 0); - assert_eq!(conditional_add_q(-q -2), -2); - assert_eq!(conditional_add_q(-q +1), 1); - assert_eq!(conditional_add_q(-1), q-1); + assert_eq!(conditional_add_q(-q - 2), -2); + assert_eq!(conditional_add_q(-q + 1), 1); + assert_eq!(conditional_add_q(-1), q - 1); assert_eq!(conditional_add_q(0), 0); assert_eq!(conditional_add_q(1), 1); - assert_eq!(conditional_add_q(q -1), q-1); + assert_eq!(conditional_add_q(q - 1), q - 1); assert_eq!(conditional_add_q(q), q); - assert_eq!(conditional_add_q(q +1), q+1); + assert_eq!(conditional_add_q(q + 1), q + 1); } /// Constants for NTT @@ -327,4 +323,4 @@ const ZETAS: [i32; 256] = [ 472078, -426683, 1723600, -1803090, 1910376, -1667432, -1104333, -260646, -3833893, -2939036, -2235985, -420899, -2286327, 183443, -976891, 1612842, -3545687, -554416, 3919660, -48306, -1362209, 3937738, 1400424, -846154, 1976782, -]; \ No newline at end of file +]; diff --git a/crypto/mldsa_lowmemory/tests/bc_test_data.rs b/crypto/mldsa_lowmemory/tests/bc_test_data.rs index d9be448..b754cb5 100644 --- a/crypto/mldsa_lowmemory/tests/bc_test_data.rs +++ b/crypto/mldsa_lowmemory/tests/bc_test_data.rs @@ -8,7 +8,6 @@ use bouncycastle_sha3::SHAKE256; #[allow(unused_imports)] #[allow(dead_code)] - #[cfg(test)] // mod bc_test_data { // use std::{fs}; @@ -630,8 +629,6 @@ use bouncycastle_sha3::SHAKE256; // } // } - - /// This builds a "busted" mu where the ctx is absent (not 0-length, but actually not there) /// just for the sake of compatibility with the bc-test-data tests pub struct BustedMuBuilder { @@ -650,7 +647,7 @@ impl BustedMuBuilder { } /// This function requires the public key hash `tr`, which can be computed from the public key using [MLDSAPublicKey::compute_tr]. - pub fn do_init(tr: &[u8; 64], /*ctx: Option<&[u8]>*/) -> Result { + pub fn do_init(tr: &[u8; 64] /*ctx: Option<&[u8]>*/) -> Result { // let ctx = match ctx { // Some(ctx) => ctx, // None => &[] @@ -693,4 +690,4 @@ impl BustedMuBuilder { mu } -} \ No newline at end of file +} diff --git a/crypto/mldsa_lowmemory/tests/hash_mldsa_tests.rs b/crypto/mldsa_lowmemory/tests/hash_mldsa_tests.rs index d208e9c..17907fe 100644 --- a/crypto/mldsa_lowmemory/tests/hash_mldsa_tests.rs +++ b/crypto/mldsa_lowmemory/tests/hash_mldsa_tests.rs @@ -1,22 +1,26 @@ use bouncycastle_core::key_material::{KeyMaterial256, KeyType}; use bouncycastle_core::traits::{Hash, Signature}; +use bouncycastle_hex as hex; use bouncycastle_mldsa_lowmemory::{HashMLDSA44_with_SHA512, MLDSA44_SIG_LEN}; use bouncycastle_sha2::SHA512; -use bouncycastle_hex as hex; #[cfg(test)] mod hash_mldsa_tests { use super::*; use bouncycastle_core::key_material::{KeyMaterial256, KeyType}; - use bouncycastle_core::traits::{Hash}; + use bouncycastle_core::traits::Hash; use bouncycastle_core_test_framework::signature::TestFrameworkSignature; - use bouncycastle_mldsa_lowmemory::{HashMLDSA44_with_SHA256, HashMLDSA44_with_SHA512, HashMLDSA65_with_SHA256, HashMLDSA65_with_SHA512, HashMLDSA87_with_SHA256, HashMLDSA87_with_SHA512, MLDSA44PrivateKey, MLDSA44PublicKey, MLDSA65PrivateKey, MLDSA65PublicKey, MLDSA87PrivateKey, MLDSA87PublicKey, MLDSATrait, MLDSA44, MLDSA65, MLDSA87}; - use bouncycastle_mldsa_lowmemory::{MLDSA44_PK_LEN, MLDSA44_SK_LEN, MLDSA44_SIG_LEN}; - use bouncycastle_mldsa_lowmemory::{MLDSA65_PK_LEN, MLDSA65_SK_LEN, MLDSA65_SIG_LEN}; - use bouncycastle_mldsa_lowmemory::{MLDSA87_PK_LEN, MLDSA87_SK_LEN, MLDSA87_SIG_LEN}; + use bouncycastle_mldsa_lowmemory::{ + HashMLDSA44_with_SHA256, HashMLDSA44_with_SHA512, HashMLDSA65_with_SHA256, + HashMLDSA65_with_SHA512, HashMLDSA87_with_SHA256, HashMLDSA87_with_SHA512, MLDSA44, + MLDSA44PrivateKey, MLDSA44PublicKey, MLDSA65, MLDSA65PrivateKey, MLDSA65PublicKey, MLDSA87, + MLDSA87PrivateKey, MLDSA87PublicKey, MLDSATrait, + }; + use bouncycastle_mldsa_lowmemory::{MLDSA44_PK_LEN, MLDSA44_SIG_LEN, MLDSA44_SK_LEN}; + use bouncycastle_mldsa_lowmemory::{MLDSA65_PK_LEN, MLDSA65_SIG_LEN, MLDSA65_SK_LEN}; + use bouncycastle_mldsa_lowmemory::{MLDSA87_PK_LEN, MLDSA87_SIG_LEN, MLDSA87_SK_LEN}; use bouncycastle_sha2::SHA512; - #[test] fn core_framework_signature() { let tf = TestFrameworkSignature::new(false, true); @@ -43,13 +47,18 @@ mod hash_mldsa_tests { // bc-java only supports HashML-DSA with SHA512, not with SHA256, so can't cross-test that. let seed = KeyMaterial256::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f").unwrap(), + &hex::decode("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f") + .unwrap(), KeyType::Seed, - ).unwrap(); - let rnd: [u8; 32] = hex::decode("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f").unwrap()[..32].try_into().unwrap(); + ) + .unwrap(); + let rnd: [u8; 32] = + hex::decode("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f") + .unwrap()[..32] + .try_into() + .unwrap(); let msg = b"The quick brown fox"; - // HashML-DSA-44_with_SHA512 let expected_sig = hex::decode("8fbf0813a2bbe17e6a8bae1bbabc8704c59fe8910b8125426b6983eb50bb26c8b6249722fdea7c26d731d7ca34ff100be306d6e7d11367e521e783eaf799cd8c235e45c663abf632aad1543c5faf13220af0eb06c7a0e7f0d1a6385dbc7fd10e58ed905850c9f9692ee8ca6642dcaa2bb1c6fea12bcbdc59d5a19c78ad1ec952dd4f22e651b2a42035b63cf5b510ab95cf0c9a9fd77389d3fae9b42b123199c84a881ff30d7955c9841f5319d93a2c531d4d26bc6341f07c42acda0f5ec4cf70932dee570292699128d23f13ebc7d79bea2ff7ca352369e8b765e4e2fbcb2476f67b8cc8c84690be164e08c34be160806435993be3dce5455338f14eb9f3918fd70b3753d374cdd84c350654d626881a0757a20244b86e7b5eba61a517e75f60e8658795133079e72b8bd4ce9fce5c6af2a94988bb3141b38e8498d9f01a5cea3f2e24f5f4b6f64e2105010d9efe12693241149f115ca2a4086c456a9c852ade47f07f0a78eaad4ed4a67a18ffb12f9f9eaa151b5973010f021c7f11a79df404b637fa4a777b3ef7dc724f191baac9dcf1a5e376978c146c944c1f8f510412c05c872551e625b50426dc0433f89b89e67e6a6bcac4c1ab86c2da13cc0c52911319889cbecfde58c5af586ff0b802aebc18b13014f5d189af1fe335a8fc3b37d90cbfaa89d7f6db2d9960787a49c7c632e339c75d3e618d55971885d4b45f58db4c9a0fd50ababadde1ad2423178e0aa26e6f3d16f6b6f03f5dcb2e2eb54ca4aac44fabc92f6b4eea194174e15f5c26801cbb8519e04fc8bfbc8ddb63a3cfbe4ba2b92c7a38f3c64a1702ee785ccb745d3a6f5853521796526c1dfc2b0bfb774a2b1812524e6ab5f15137e22dcf70136274cb0181cb277303478d9a5153f56e9624ea9d2f838a9bc054e080973a86e174c72fa4bb78c01598ed3f5115939fa172537d8799ada93af028b437048b0ae1b412fda490b3a5a292552927cf3ac540b1c67a97c2a7a94a6217a7a3fb7526c00a0d2a13e64aed1449c4029c4f9ef7b7c783929c37713c7cec1d55d1371dbe6ed00782e143e2ffb74cef8bec56c18e37e707e1a7e1fb04cc0243f0002de7644e8780f215910754985ce1cf6b4e16c0656e2b9fe55fd4fa4340a4de5b01624afbc819902b90a17f0b8d55841f2d3b41e43bc2727b3584ab49db5548169c5e207ace157469cc2d712e885e67735afbee9d5874b9bbac6a2d88cf8f957537c137e44b105202942ecd3cfdd792b2657f025d48c4ea172052c7f33ef8f44e808b8888ca755414eb191a1c4cfed2ec6ab9dcf8aa1451b1640b09f0022349091d19665fa3ca2d5f6ab9d883c0f03fabfe9565c7fc2a536ea73758fde6490f4de2e138f39a628175f2860e8694bdb9c2045d218c78b29243ec2b40e5bebbe2688985e337b528df5549f4adc5a36dd04f7045bcc436676cc6c8b58b0e0205b7e1bea512749102883e4a65600dbc0744b03f2445950eeb536cdd8a88cb90d069c4205e4a0df830170c73779245729d896d14730dccce05a2f1cab706e9929cc1ace014727d793b1f1f8b572bc7a760b15b325c5fa4b1511f253567caebaafe7acc0cc400e470cce9ed5121caba5371038906d8ee1643f336146ac6c743c2cc36912195da57aa1e557ee4040997583dfa77e0bbad48ff901ccf4f28b32b350f2383812a5bb59211f8a90aefda3eef487de26746303676d5727a4ee39dd5a2d8e0072fcd4dab6e0af099aee6b379283272c3e56b5a55b5b399832482ce311a3a629ea2e01cf4c236ca4bc807898fbce977521fb75ff02699f81a26bb69c7a69d46edbe4575ca2f11c361b269b918f7826c61496b815390efa51b92bc70b83c3fb1f311be5b23d7cf6fcf2d4877c3e7d439c4bac5aef81348688f97fd34b32c3cb798feb38197c6754527a75cdb38e28647de8fec0d77cf3786cb5d339f6569ca879d941d88c8cc1194443c40c0ea86d5d4cad5f7db683effde3339bfd63ad5cfb1caba26521e3c9c6d93d9c58e38431e40eab5f7cb2158c8f48e771f551e940a8607af3fd44aad01bdb9a04418aa03aefeceeef5bffed53cb37919d280f8f8d73965b02ca4515d26d33ae3afc97c779b72656ef34399e6508bdc9017bd17d17ed675db7294fee98bf8fed1d84154949dfad1dba8168ee1f6d8828f80ad5a8c11aceffde97886fe2440f26b74436a8534f5ac3de9fb61f3bd6c7ec5c761aaf0036be004a9d5d952b8719afd5cc6da5081632e1a10398fc7d7edabe522e75ea774819b1f2f558c46c276eb6419504a4f9d1226544ebc4dccfa76cf26ad90661e9f78d563472e78cbed3833655983e9458aa71dcdb44fbe13295606bfe7a02715044589652c641585e3950086e40e30885934b92e302ced1a94e95fffa9402afe1f359569a394019d5265862dce4b828b657e43591d199b3500394f871155debc78922305c366350868bd81b06608a44ae383aacb8c0761bbf8bc7a1ee1b9bc7f5a9173544f9987c9b15706a50a193c84dea3317b71e04369a52c32cc3d0eafa918eededa4dd321b1ba99a668c436f16f7f2f1a1ffe847f86a6a1c39b857c118b848593265042eb4a1ba8a50303ad7034d2ab4960bdde975dbc3fa632777b8ff5c541af07e63ee05defa4aed3fda7a69a67191617f92dac21e511db12fa95a5fe1ca37f184e02f58b835faa8ceadd8bfbd938626a7565007a5e022b97debe1732835560e74bfd58c0eb0624fb36703d5aa05a71256cc432bc3850f7b982048c3329f717317e9a755440d1e6d3934dab952e23a993d15fad17534bc848060b51a15e670766c6bd3649957bf89e8fa34950fb1870089a5a9e82af440cd2571f2edaf68d4c1ff4a82c30d7e0b1ee60483fbfc3eeff73c97c7ec9d07444d05624cebbe408f2d2fe6cb43c17d64f135b113538035d0ab73e9822b804b607e88ae999a035ee22d7fda883c817ee5a027208bc22046585f24451f76dfc6e9da9e62085de03a323de7b7ba09cfe6bf1e3b1643dda9d1b798edc54741084595af65b36b9a323a90edefbd37e9038b68991846cb5ecc442785aa7fe6993cf3cda097c3417d234aeac8540e12f810a07fd78548708a72092ff1c4b59f9f8c4023e89a344ded87915b65cfb5547a57cca97c33c861b04125550648434e960c144dc7cefb12459b314da4d6cfdab29e2f4354dbe9ca93970964816c366924c84fd1e7f592cdd8fb37264d359d508bff7b2fd342d80375f87fd76bdc5932517aebe6aed1a7e27632e980b63ec70af947130ab190de8bb309ad1528a51a5142215181b252b2f345f6a72aaabcaea1114152f344c5764656a6c89a2a7b7b9badce5050a2661738f99b5babdbec4cccfdd35677b84b9c8d9deedf4f9fc00000000000000000000000000000000000000000e21303c").unwrap(); @@ -61,7 +70,6 @@ mod hash_mldsa_tests { let sig = HashMLDSA44_with_SHA512::sign_ph_deterministic(&sk, None, &ph, rnd).unwrap(); assert_eq!(&sig, expected_sig.as_slice()); - // HashML-DSA-65_with_SHA512 let expected_sig = hex::decode("cb99a9fd2063ddda7114cf99b577b7d9a6e7540ca225d84e5b04c28e30a4a09c6ec470a596a1efa809a42250487d908676b8a50df1a032c1c4c5124e989ce795a44faf0bd5e46627b1272d99b065d38c60148892bdc93159c828cc7e60996fd1825993fb001a901d7cbfb5a24b05446ce0f4ba5629434224646d10dcf4a55c851a22c690ebc443fea0fe2a7858d5e175b1e0a9115b3431ebeb78ab670f6f79c0f94d60fc2658b24a9ef06f51434aa4dc1b0797cf905dea13d5a1519e6483dd60dd33eee62a2898d3179d1b459cf316cc7ab2a0be94ec676f1b7e35b5ee123bf17fa39aa188210d2906991beeaa5e63516debd90504dadf4673de1ebc67a2b7e399b30485a4ebe37c9e7dce4c885076d3741c7841b319fb6b5fc228392935b0d20fe1ec8a4441ea53e47940816f8ead499d73702be1ed6d4f99c5f48d82acf60d1b08c4fc7d66c0cbfa93c4880977e0fde301dcc038b0cd354f6ba7b14191ed925f25cc1168ae1b48849b6f24e2911e8a4046bfa1b3e2be62369a730096c79d9f460e79adbafe4e9c723123df5d872cad3fe1553df2f6f49ee7f5278b75c445a3aa4fb16836faa8f6e766d457f803ffb11d32ca9de876ad0b8733a16cbd91d319489b738c9af693266c115af3be2afc29e2c6f669a133aa7b22aa6a84a7adbfe0dac48871b3f41ad20f78f003761b729eeb8a6c05cba15df2491b882e9699025cf2483151a6fc6e0839fc13c4529b3a5a67c0fbaedbbed2aaa764d5b936a94e3e281bb465b2b2f837b396c96c75bd3e58b8b344c13094eeb3105eddb41b7d1e8fd0f05a127e4d306c6d011a8d7da26438ba50bcaa11cd7136a738c1562c4a5681b3ae5870c21838f0fd1b79d20528726adf64fe3c85bd92632e720cc6c9fbdf37c6d293ffaf7ad2e01284d66ef48b6c25b9503f61ba967031bdb462528eb6b02566385a7f51bd0f92404c43c2eeb325c76190e121ab57d308f6749ac612c138664f198a477a1eb59d2cdd0ab217a2f3e79120d9c09936a8671ffe35ab87130909f84a9beaf8733b86498736be36052a6852ef2320226369120c20c1bc4cb676a9a31dbe346601d5166db023829fe000e2be7d7f9ee29ea4de25ad3fb66dc2cce9669d2c7aeb2bedbf24c117fd40a563172246fee9ac79bde567d09032d25b54ad017c367dff2f69c55115f142724bcee8da2095efc81611e5f357aa5b5a46513e86ed1e28266a9d110433fc4f69b7e965abb6d781d69936b1eefac7a5efec7478d3b1b3e3181bb3f415311510d6284349f63586bfbeb5e0ffa6d89d518a2a12997d0622387fcb267844a9c7281f04a34379038d1b8db1050058c8b57072b4c6bcc582a734730529e5e301dff85bfb90d7e6a6214c3414caaff452b11adacf7dad839516ad2d6dc2b7e8c9273ad0229b004a303c2771e744cb227f7dd999c08094cc70849152557ec3e90797710cf88996db05970f457c7c32a219033ffa71d8f11a422d2bd6a71becf07b9694149bbbcc1bc773c94f170d7702086099c53d0a24b8780d586cee313df06d5cd4ba04925a6f85390bf8a9e93f1251a84e34802cea764e7b8c3e50ee500cc77ca4e265cd2e7514db01a502e054cd407c5369008390d239c62e42dec5f628da94e71a97dfc86e3f916fe66d13a8c72102ffd03171293a6be503768eb418c4e6e66b7836244354bca0f7076683364130219c19ad843397c307f0c05c05fa521226bda6ea6768a3f473e5304964feaaa78c2b6a50bc666a4ed0ed655702239ce85fb86b7a2d8520b0257260faf830b681b86b11cc0cf43d63d77f6d2c8c84f4fb55a6ba70a32e389d167b4ecd07bf909707d3e72da5411e0136320e0460b70e0a39469260ea51370b4cec27f82ad86940725584b7a2a370cc9af96ad607bb1855f9631bd796b34cfc1971c23174d54375535422f5965170e84b78e89d4bd9094e9996e018cd8872ade216ff5c4679174cc24d9ad112e5e2be28f9792a1a5716969dacadc1ede4911a8cb7f6fd9fa35d68974d0481c736a265f1c74397cec2eb1235d725b0241875d6e413632496ab62ced9e922c955a7d09e9dbaba4ca6642a56ed1617088298d497257c5be1f7ea55d72560c919785d24395873efbfab048506fd88489aff60c1846419a43e77cd3689d2913b9845c2d1249440aa143e0043036efb56a8877e1218ff693d4e95f8c86dc0b38af1d41c651dc681680bfd3742127bebfe32acadd8cda346b40374fd7aefa84072e52b51832b79ee5aba35562c161f53234093472b65785ab638fd56c0219deb1c19c97feac2e833f5105538fc81acdffe51dee05ac4fbc583be22c62d45aad7263736981a9fc5472f30465bb4ae1f677bfe53342a573befe34baf9b8b5e3b64e3cdc994f0b7cba4ec6342ffb0ebfeadf01eecd63bd6496b534747f0379505626f1068e997fd61effcb3574e372b030dbba4a14e47e28b38e4f8ff910bc589756255863400f1bc638ec227eb05d49f9227f59c463c2162ee107ba3f6151cb09220287b90d27f9843b74db9d22848d197d4124aa20cb2ccc673344646ed87b1fd9e16d674b6d7ddb8f7921f5de5c045b9c13362442c0eeab3ea35573a720c68fd640ccc7a7b3e630a9b7c799686e051666976581e69fe79c4275e308fc7a60f69021e2c501811269acc05fbaf82f12a0535da36134aad9def3a8523c6f6edccfa3523c02f63bf590deea39fd30b3bdbd2deb9a4a076b19262781a5f549943e09f7995b594980f838b1ffd801c0a3b69f5a007975f72cc01d64291e85b3159623f210819f44f773375a2434b3b479b9004fdb8d6100481f64a2386de41677da5b1e7aeef840fda0e0f9a01dfdbf52cb18f60d459029bd536c22da9af2777dfa5093c032c4a62fff604fb66e9d0d3a249e8a6596d47b7d658492b3dd7fa14d507a5dd08927bd118e889e5ccc940e484233d245aa2cf67394e4fd15e5e129d3955d4ac6e230c974414cad06ad301da92fc6453abbef3eb14647e088b9c6ac74c3517f9d6ffd24eeb62d3f591aa34f828c1ba902efdbe322160326e4d46eef78726cae9c6e68643e2dfa259ef0e761f5142e06bdd02c5f516d101fc4171391ec338c427ab89c757a3847a928f1cfffe40a9fa6276c7d08b27f9910cc02f14f60d0fcca7cf518e7f0a6f546892b38592744fd4c670e6e68912b0ff2de7e5a907bf67f33a75f16ace28927eb375e5c694a712c122ccefd72b3d755bef017fb7f1ce17e366a8993a1b8d0aa14c3eaffeb78e778a192d3d80e37dcc4344bf4de73c6ef7523f53fb04232ac97aa64ab76b115405adfeeeb5fbf97f448dae8ce4dd26e68f8aaafb9cdce8d38522976fd18c80f7e3f12dc459f6c8c43dfa3b1ce0cc4d7b67236e63a20ec156117e0893b8aaed7d9b5c9d3751589e38591533c944049bcac38a7585d4dd3016ce70ac1f0d5a4d656e611d87f5ba65839aedabfb1820ce60e2e02c33ba16e02dc21ec349c1da32a54a460baea2a73f43cef1d8877d9320098dd543f786bef664ba8216d263dca871760926a405a25caf226b85a95382386fa5a2144723c3aa2ceee4a69d4f3f8473facea0fdcb38c5f8a83ac087301c4e95de8023351a258870f6fe4be5f9e713fd84ec28fdfb1737016affe39b29daeeb8ddedb5a1025885a7c77e54c4c556944bc6fa0dcfe1147d8be50c262970e645254e38ffe1b4a2c8583cb4769b313e37b86ba2c572cbb374d61ff294c62c9320f28af2e2ac62ea6d3a564f0ba53e79d4f870306cc8c524ecc2f13cf9eab683a483f65aa99249ab8437ed759b664cf71123ab2774892680c8aa0948e0f4a320a45583d672a4d70b7ac3e2fd42302a6f572fd5d5873f80f68b6da6a47d0e3361cbe30071345406e992439911a20df8c82875992ca4a45f8934d3e45ad202341a58520c12ad83e22da9161588688aef5483c9f15c9d8a0a5c7c4dfbc9fc0369d6727fc4ac6e532dcbb8bec20a552c4acfaae9db33fff348041ea2887c0e8d5c9b798032ada7a2c0bfe814e2535fabf01bceac486106f16ea2df69d2eaacb7d4b02e50c3352c821eddb503075278ee4eaf779d6c3cfd2b77c388b97c66abe59b507a111de824211cb57c1ce7a8fa25309061cd3847ee67508bb6354686057b3518a3a33de389919398a6f5609779a5cf709355fcd6be7ed78c5c83951489ea7cf4fbb7c3ec210abca5263736dc462b600132f206bcb3009c6c261769745b7a9d5b691ffe858bae747c710217de7ba66431526bd6e63fb9d6f36e828d88b32fe9212ede700e41d94040a9312961a4071907c2161cf9e5b15b426aa25074ee0363563e1e215a3c2b44173e27704ec8e788ea6b1a9ec4465ac6d74b78d6564cb67ba378f419a0d65214a488ad2120be6b72c58054580cafc3ab2b6224b23af3c248920bf601285f2b9cce1793904b84e8070315c4479eebc003b4f3cbd37c1f0895614d22950695c864ddd8ea4ca20d472f44860a991969d797f5d502bac7d8797639313afa2244f43874c3758cc4f7231500d8bf1052f7e0d370650f946beaba47dc78ed963019f7ed67e93b69993d0947b159d4dd0eb88526242a3542749dbaeef1fa1361db6e7a9193b0c2d0e3e5e6f6fb232580b2b8c111acc3fc233b8d90e500000000000000000000000000000000090c181e2227").unwrap(); @@ -73,7 +81,6 @@ mod hash_mldsa_tests { let sig = HashMLDSA65_with_SHA512::sign_ph_deterministic(&sk, None, &ph, rnd).unwrap(); assert_eq!(&sig, expected_sig.as_slice()); - // HashML-DSA-87_with_SHA512 let expected_sig = hex::decode("54b340f2f8318713194c4a7fa5381a4bc09af874ce020573c2da381b156b84643209a5506c2d31049cc71db7552acfd32185fa5755b4bcfbc8570c148a15e487a8be1ebe7f7cf735689cd49ace98831144dae634d50ffeab8fca9963077ff25f534f23af50d86b9131f4293fe638452389d1df255bb9a9e011cb6987f45f4a51d85d907b839378d2fa1d4ac23f6736eb2941d9faca5c174025cfb88ca43c24ca0d774391fd02784a7e0b1064f9e9f5b736ad0c9b9b3410c15a2c24dd178a7ff04d52b4985a7fb2c6375002546667cbc79c759b61f54087c3cf49d1c5014f66d4d6b1bbe7b30a5dc26bd4d667bf5f970452806bd43c8e195aa7219f073776c4a05fd886197158fc694a5be8a057d57ce499175672000d677c3c20f4b814cf3f340335127dc5c7d9359eebacca82386ec1ea0c4b8735151437ef7f33b9f276b5d95344305d336798936a1edab987ff50569d9410aa245192d1d71732b2e8b90ec275ef7c293bb982bb73cf1b46dbb585daa4c89feca3b197c8cd29eec186b1a724f16deebf498e6a22deed4b47c980bdace1a05fe7f9c42fdaea8caf11a9d4a84949a4a3be6c7fe6e8c0cd721fe238558bb158c5a40203024cfef40f27afb216ba61dbd3af379b86bf675f6cecc6cf5acde4e76b63b62b6760802ba7497689bf24580659b17c15195bb9b8f55547dfdc04171eae5356817800880bd47de17396171af06408b73f87c8f9ead1124c13899618518eeba5eba9ac0fc39b615611d25ccb1a11e83226d42bc3bbb0eff64cf6e666227c2a3d551edf1e04565ea33e5b8c8c9885e153dcdcb3608e90ff2251700bcd2111bf5e292c29f69dc80a4dbd47b9e0368ecdf0925dba0d27c9b6f82aa6f7ff7e8385d3d0017b5ca65e039c2a8913bece73baf10a413be5de60729b29614d1c35928b91831ff2c1e6d24be82b56e446584c2a2a18ced134676eb887a9bf0026934147e4f70b9d30ea95b432301e2280981a6a8628c9d52ca5f91f5e2e20b58ee09abc035e079b508b565b7de0d221c80c022f83e5835747e2b5de4d5070af101657e253f3e26caa1238462a151149e66ad8d435fde6fe0d08bf5cf9ef9ecbe280ff5715f03401994cf37d25aef7e100db66c86ea84bf738145e2e9a13317bf7649371d6c21f79ea599e86e2f25879e512b5b7aa9f6e84e85eb20aeedfafd605d69a674c662e921a54c28110fd4b457f8058aa1c781379a6720e420a7ecd949c2027ce629808c9ab26efc951e3a1fd3ff3241303376191d3d9e1409ac56f6871e13a012f65d80d4f566133919ce3372c47e5be464cc70dabe9fa201fcdc59f8e8c311f8f43d40bbee23d563da37f82b1dd7feafd112020d5ffdd3301e440722d5bda145048a52d10b43418cdef434901e3fcbb2e931352c2a675bea9bbc5d6eddf96a0ebc7d71648f211bcbe02ef26a22f489428dfb38473be6ffc7cb2703c3e4aaa9c27f6e0b933638ff432cb91146180e9368aa2cce8416768a3fe8984ae3910f14888c64cf3f1e1222904831aec32b6d3b2d2244218452c44441e20d27f342b9cd60d603f0fbb7879752cc4553e6dc9176515b90bc0d933d6d4da2c405e5d4475798acb57e419c25f2d7af10557ed48e1f493ee55303bbf5824ba7447f4f41e2767da3d288d2beb067181cdf1bb98664608776134c351561e761d222c8906df68a04de76b99358d76b538db244cba491000c6dd61373f3ce6d62fc4f4b158ccf9f6260ea02e19b9697d946d21264846e4cf7d78f5fc0e9de819ef654c3e1d820ccdf45cd0a600806813d5ffdbd6f0c64fd1928df7d92f21b20a6593a71d418a0a480a7beca0abfc3cb732cb93e3a0ed51a06b5cfa782601ee6174a35ff188a7af57426fe0129a1039d76c9b6d523873272cc7cd90f042948bdaa4f2b690be247564938f185c51ae63a6e54e618f6787164fc09275d4b7b201d06de3bd4b57c4909c0c901f39742a6f5301d4c5a2d8e314b5009082bc292a9b39f61c45c88160f93ef2988ba9d7a80d5f52360e331cc828100e17af7ed4aa3491298355bae804e3af7418299bab44f09b171562ae098b0d507b0bfede06f75fe6daab51f6dcb9ccbd38da9b123dc6cc5b775399696bea6c5768e875d341eb173aa6d63d85f150c5039d843234c67c3cdf1c101b3b019711adb42acd8ed03ae6c7aa44c35a845263877023a3b7b4679c4797f43e4980f27e18e30e0cb088b8e9586aea971fdaf6bfb9ddef3ae7598932cd4b15bf9be8c0c3778f7aa609c86d583f7facdaaeb41404a07d3bbe225792e76c2ef86dd68ba3b945d7b849cdf87c2ccef534597464901fefa1441723d601ade276380b97d2426fcd19fc90c09aac5852599b955f1084c79ade067bbf764b4d2ae597e8b87a600e79f84796a12f61047568612ea279baf9e3feffa3d16de35ac00aa010c551ebf7c27f8484b1cfcc47959ad20ae180c92cc121f0d298bbac47ae482d4fab23087df6fac3b8e026c39faf921ba1e53d6a776832a4b96da9875a682d626399ded7f577e1e88011b9e14a2ed73d3d7db2ac67844e3017613a237991fabd91b7df66948e2f8bf1324dcf45ac3fc2983ab749c62ea5bd1db3caf8e7958686a1c7b7cbeaa88d4bacbbba0ea21b74c9d47fdc61df30fe021adc5129d3b82a7c81778deb908b3f2bed5519c124ec1395a222ba7e54dac2df1656c318f66546485d1037c34ae70ee64f678ca6a1f1930e235c5a14658e98dba421e0c3ab342d6f2045c35d70bb712ed9a7890f9471c43c376ce8effe0f4f263ab307973557c38c2b6dcc137c9f7b42048f78acad85f0d5ee9efc570139475628bc6a02c4ff431bfd4c9d9e7307ddf6bf348ca778618fde825f1f8bf286e70a2bb6d784602a83400cbae753b9fa35f59bf9770a26dd8c04cf46a7e5e9435ff26ab3719f8ca685ad321de859d3a56819d47ceec489e9bddaa85ac0fd75b831b96b374b9effe1425c4f6ca49a66858b5563033bb91a383f91a85220c088209614975bf509a91a58d36fd027425d01f2516cf87a50f7928981b1367f29cbf8ca313e4a7ce130bbcfe95775ff3b410c0c4ccb0b2e6ff154235ecb28694c16ea728ffc0a7bec0b84cf01b0605f1d32be08c70a794e73dad1c5a1498e8ba9bdb020ad7beb959a0c70b93e3c02d8d068611b2465e096f9b08acc49b90bf697b197f1dd00b0452a06ffecc35627e031143e9beee4b292a130f0e526e82eba33be227e813c3ad47acfba9399418d2910ece7e14db125b5f1e7c4431599024ffa3e82d020702d3f65338b9df5fb03c0795b892a8e0fb494bca5f0127bafa303532524baad8031259511d863ebd8d58afe810b37a612b99c4514bb5d0d22615fa0ca833804c7bf06605720f3f18ff3d257678a4ed048f6c5c21897a9c810192d80a24696a0a99a88675352b934d6d4ef884ef5702927d499525744ce004c56e5d231f5bd1520e679cbad48741cab40707bbd651cb65940f635b83c94a76c462418e6059919fdad24fd55c32680848f97ba89ca383506ce8b5b1d0165af06e0d7b51694aa5607f1dd78cdcaaf87f700019fba62ba17f6609b993a44c839210fb266ea437bf88c69cf7dc3159b93dd30e995249094b7460670892f2da18d47e34a01b212277f5cfd8aaa07f090c3390ab7a56425c322cb130fb7c5bd7dfd602ad7c586a21ab0bc03a89ec49ce08f1cf920cf25d07561996673ea5f261e122616753d0a49fb7416c4dd8070f5a95b9c0fe6d11abe1f8aaec1c620ac3033ed6d1e5c29f773184f9f10790bae64d1f6a21bff248c6773acb075827e7193fe9d40584b6533afab5cb1f4c8a7d6c4adce7a2e634ef907020f06a13be3c8586fd7e65a745c345b3efede788b8c04623872461652f0b04239c19b5968c23e1a3e41529b7c58690bb9d749e6d462ccef13baaceeaf6013f9538e82f47553b01011b3e599b8ebabd150c1f5776193d18dac011d47e7da75c2c2e28e96105d20ae7d2c77f0eb19cfae34a8d18580bec72823d2f50122f06de21c6f21859fa90abb2a4f6bd07b377bd40c0e93a84b16f4d0b469d5d0168b3b632c3006ff6432331cb4da52b2f69e5304905b1903a6d1cc2305296107148eed143d9ae5069757cd91541b83658e82370ea6ec36b9811e6c35081e11c1380e59315f9ad94cc25087c071429c0e92fac8a2c1a53dd52ee18ebd281deef9048225572c765de65e50d6a3c9f4be09bc8617c9b7666c0322b73d81c333e50f8ba470ea4c7ab0b2c2aa972eb67a68a0e7fde93e75b09d81558fb61adea9d7f74a3532baf1b099d78e35402e95968f325331118c69c9176a9e90b11977b2ee7b4036c702e92894aae27da2c2074191e791db8fae4f85245fff7375519ba86627cbb38489d2afce34b0a2f76e52c2dc828b139b79ff9e5dff83e14b294a839fc8f688a60d2893eee9c9425d2fd49912476d05222800b936e3458b971c870f4c6cfec89ca70e91e5000a8fcc84f763cadbb56103af4bdea1276bccfbb228818f76667f85f63bc10b22105b2067c52ab52fa513bad6fbb0b1462f11b8cff7231942765f2e4eb225a73af6ed4873166badee6e8a2cb6ceba09691a0b8c0da29946b82fd07e4f484e66fa89b3912283a9c877d4b40e6c9e9ca256447c9d2d5c6b40790694706d6ad88f0da66ffab7cade6322989e8197c3d3bdac3ccdf16a4f59fd02f0ad3ffe3bdc77f8d83d21491808de9880111a91bee85225ec89f5d0f585c82d0c5dbe448a7fb1ab79d4a993aedae36a02abf5970970971eaf674761d299be56177f17c3889db7a4ad539df3d4f0a4f5a76212809ad3e18124e24799a55e6c28ceda011120bee72b695a17268913320a40201fef32e554e8c90d78eedeb90b44769fd54ffd1acf58135bbd5d927f82a99a747cf1503e9702a0fa72ddabf25e1f67948456947bd98aaf04136aa815901d94103c0377f4d4dfa1e9c3075d2e63f0f0f9167068c1345786f3c159ecdf694c1509da518e26bb22dccf6c14b4bc13b75ab00f71aca9b09b25247497c4dd29af1484290bca60864f7bebcc69627f4a3467e29751a01ff0a4e7c1fbc363b20ecec477061a9cf326823aed9adc396f4f12d15cc806f6e14b5ceca6b0dd3729c60e91ca7b34fc9368aaab98111fb8b33817e843090b5c8418cd9617f2e61f238f0258ddffb13413092cb67dfbb04188e8770ad09753deffa9e83f2ba3d72efcd5b8c8cb1ff8910eb53fbdd96ef6342f358f5c3d08f5c863123f6de0454e8c358abba2bcff97c563ecc59175f8314ffbc082ca893d5383dceacbda304450c7c9553f5aa0f1e0a41b8a50b1f03d689904f446cf56f2ca1202bd24f153c06efd63558407318d12eb933a0d68dbf9164e1a487161ed78c58eab5649ad84fb3b42494e797fdabd19857b786177deeb3b84896f0f31f4a71041bbdb39c2723ea6a82fb61882c4770cba23f3d009220f2c15fdd6ea0fa2d473f41c7d5527d498e131435b11844d3f285da458c86d80eda63609a6fd83b0ed004f7f553e3a2787922c881139e2f40819f4a1f29dffb7b42bccb38238b17fc63c18d2931c2c6bc45a418eedd10c3799ad5a993a54647b8537752fbc456e00330fca1dcf249c4614cd16715521a98503f80e4e97b36015fef9bdf38424a9ce2ffd9441c8cad34757da186f2ba4ebb39c664e33a6fc9df721da3b94e2bc9ff9cab1dbfe5aa07a7c7c7a715b8bd97997578428e9c89a0c8569049f942f54a0a63a000b412849a5897d2fa8b79c479bdf17e9ee8869c8e62c952c91b9c52acfc20a78993d9f93ab523975beecc1d52c01dd18b88821719012979c21818143adf4e89b60a4f21631e0023c6c25c9236d9ccaea6c44eae4507bdcffdb83c719005293e5f0d4232f3d3497b63b6f5464d78378a65b5cf677a4dd2a3f9c072c101f0207ecb99ddad33c333ec425d3f4065b3c02e9b441dfe7b15c2647f5ef6074b0c67ddde60c6d82e9f7d5a60fc429fb77b433ec71305e9939ae60ff395f2a05a413ae2cc5d6bd78c6ff2cb38334e0dacdfa36b247cd21bfbae48c8e9ac6d3012067c9721bcb946acb2bfc8004f08b5c69f7ef86bb2fb982e2a0ffc1d408c85819500eac5d02d13832b5edaa3bcc9477d4749eb7929cc66e8a47d5378b268ec26832906be7ceadddefa1c449fadda6b371950dc66343e27c74b62fa265cf7a2e9c81b19cce51a1d0b72c03dac45b825c2569841885460ccccbde6e9fe88bdb2acacbed6f18e7e77c1680f8ab792f2d1b08d67e36c194947e22f6862bd24003d1e139f0fcc2a7784ae420e3e03943e3de2d6d6627ee3d6ccfa4c14155ff8428a2ef31b420df2988f8c77072cf53ae91b3ca0f7f42c14b8a88b2e2ba94a55834dd2da785d6b2095664e4cbf1b94796aac2c0e3a1ba3c070804336848a0b5e558a50812b0b1fc0207769ca4db0a8296a9adbabbbddaf417193236698390b0f9fe0d192d404953ade7ebf2415998dadde9ea153b3e757ef52989ced5fb00000000000000000000000000000000050b151f2930363b").unwrap(); @@ -98,7 +105,8 @@ fn test_streaming_api() { let seed = KeyMaterial256::from_bytes_as_type( &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let rnd = [1u8; 32]; @@ -109,12 +117,13 @@ fn test_streaming_api() { let expected_ph: [u8; 64] = SHA512::new().hash(msg).try_into().unwrap(); let mut expected_sig = [0u8; MLDSA44_SIG_LEN]; let bytes_written = HashMLDSA44_with_SHA512::sign_ph_deterministic_out( - &expected_sk, ctx, &expected_ph, rnd, &mut expected_sig).unwrap(); + &expected_sk, ctx, &expected_ph, rnd, &mut expected_sig, + ) + .unwrap(); assert_eq!(bytes_written, MLDSA44_SIG_LEN); HashMLDSA44_with_SHA512::verify(&expected_pk, msg, ctx, &expected_sig).unwrap(); // END expected values - // test the streaming API from sk let mut s = HashMLDSA44_with_SHA512::sign_init(&expected_sk, ctx).unwrap(); @@ -123,7 +132,6 @@ fn test_streaming_api() { let sig = s.sign_final().unwrap(); assert_eq!(&sig, &expected_sig); - // test the streaming API from seed let mut s = HashMLDSA44_with_SHA512::sign_init_from_seed(&seed, ctx).unwrap(); @@ -132,10 +140,9 @@ fn test_streaming_api() { let sig = s.sign_final().unwrap(); assert_eq!(&sig, &expected_sig); - // test the streaming verifier let mut v = HashMLDSA44_with_SHA512::verify_init(&expected_pk, ctx).unwrap(); v.verify_update(msg); v.verify_final(&expected_sig).unwrap(); -} \ No newline at end of file +} diff --git a/crypto/mldsa_lowmemory/tests/mldsa_key_tests.rs b/crypto/mldsa_lowmemory/tests/mldsa_key_tests.rs index 4117319..fbeabd7 100644 --- a/crypto/mldsa_lowmemory/tests/mldsa_key_tests.rs +++ b/crypto/mldsa_lowmemory/tests/mldsa_key_tests.rs @@ -5,13 +5,16 @@ mod mldsa_key_tests { use bouncycastle_core::key_material::{KeyMaterial256, KeyType}; use bouncycastle_core::traits::{Signature, SignaturePrivateKey, SignaturePublicKey}; - use bouncycastle_core_test_framework::signature::{TestFrameworkSignatureKeys}; - use bouncycastle_mldsa_lowmemory::{MLDSA44PrivateKey, MLDSA44PublicKey, MLDSA65PrivateKey, MLDSA65PublicKey, MLDSA87PrivateKey, MLDSA87PublicKey, MLDSAPrivateKeyTrait, MLDSAPublicKeyTrait, MLDSATrait, MLDSA44, MLDSA65, MLDSA87}; - use bouncycastle_mldsa_lowmemory::{MLDSA44_PK_LEN, MLDSA44_SK_LEN, MLDSA44_SIG_LEN}; - use bouncycastle_mldsa_lowmemory::{MLDSA65_PK_LEN, MLDSA65_SK_LEN, MLDSA65_SIG_LEN}; - use bouncycastle_mldsa_lowmemory::{MLDSA87_PK_LEN, MLDSA87_SK_LEN, MLDSA87_SIG_LEN}; + use bouncycastle_core_test_framework::signature::TestFrameworkSignatureKeys; use bouncycastle_hex as hex; - + use bouncycastle_mldsa_lowmemory::{ + MLDSA44, MLDSA44PrivateKey, MLDSA44PublicKey, MLDSA65, MLDSA65PrivateKey, MLDSA65PublicKey, + MLDSA87, MLDSA87PrivateKey, MLDSA87PublicKey, MLDSAPrivateKeyTrait, MLDSAPublicKeyTrait, + MLDSATrait, + }; + use bouncycastle_mldsa_lowmemory::{MLDSA44_PK_LEN, MLDSA44_SIG_LEN, MLDSA44_SK_LEN}; + use bouncycastle_mldsa_lowmemory::{MLDSA65_PK_LEN, MLDSA65_SIG_LEN, MLDSA65_SK_LEN}; + use bouncycastle_mldsa_lowmemory::{MLDSA87_PK_LEN, MLDSA87_SIG_LEN, MLDSA87_SK_LEN}; #[test] fn core_framework_tests() { @@ -25,9 +28,11 @@ mod mldsa_key_tests { #[test] fn encode_decode() { let seed = KeyMaterial256::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), + &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (pk1, sk1) = MLDSA44::keygen_from_seed(&seed).unwrap(); let pk1_bytes = pk1.encode(); @@ -44,9 +49,11 @@ mod mldsa_key_tests { #[test] fn seed() { let seed = KeyMaterial256::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), + &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (_pk, sk) = MLDSA44::keygen_from_seed(&seed).unwrap(); @@ -55,7 +62,6 @@ mod mldsa_key_tests { #[test] fn test_eq() { - // MLDSA-44 let (pk, sk) = MLDSA44::keygen().unwrap(); @@ -78,7 +84,6 @@ mod mldsa_key_tests { bytes[17] ^= 0x01; assert_ne!(sk, MLDSA44PrivateKey::from_bytes(&bytes).unwrap()); - // MLDSA-65 let (pk, sk) = MLDSA65::keygen().unwrap(); @@ -101,7 +106,6 @@ mod mldsa_key_tests { bytes[17] ^= 0x01; assert_ne!(sk, MLDSA65PrivateKey::from_bytes(&bytes).unwrap()); - // MLDSA-87 let (pk, sk) = MLDSA87::keygen().unwrap(); @@ -132,7 +136,6 @@ mod mldsa_key_tests { let (pk65, sk65) = MLDSA65::keygen().unwrap(); let (pk87, sk87) = MLDSA87::keygen().unwrap(); - /*** MLDSAPublicKey ***/ // fmt @@ -155,8 +158,6 @@ mod mldsa_key_tests { let pk_str = format!("{:?}", pk87); assert!(pk_str.contains("MLDSAPublicKey { alg: ML-DSA-87, pub_key_hash (tr):")); - - /*** MLDSAPrivateKey ***/ // fmt let sk_str = format!("{}", sk44); @@ -178,4 +179,4 @@ mod mldsa_key_tests { let sk_str = format!("{:?}", sk87); assert!(sk_str.contains("MLDSASeedPrivateKey { alg: ML-DSA-87, pub_key_hash (tr):")); } -} \ No newline at end of file +} diff --git a/crypto/mldsa_lowmemory/tests/mldsa_tests.rs b/crypto/mldsa_lowmemory/tests/mldsa_tests.rs index 78d3b43..db9bb51 100644 --- a/crypto/mldsa_lowmemory/tests/mldsa_tests.rs +++ b/crypto/mldsa_lowmemory/tests/mldsa_tests.rs @@ -1,18 +1,21 @@ /// This performs tests using the public interfaces of the crate. #[cfg(test)] mod mldsa_tests { + use crate::{MLDSA44_KAT1, MLDSA65_KAT1, MLDSA87_KAT1}; use bouncycastle_core::errors::SignatureError; - use bouncycastle_core::key_material::{KeyMaterial256, KeyType, KeyMaterialTrait}; - use bouncycastle_core::traits::{Signature, SignaturePrivateKey, SignaturePublicKey, RNG}; + use bouncycastle_core::key_material::{KeyMaterial256, KeyMaterialTrait, KeyType}; + use bouncycastle_core::traits::{RNG, Signature, SignaturePrivateKey, SignaturePublicKey}; use bouncycastle_core_test_framework::DUMMY_SEED_1024; use bouncycastle_core_test_framework::signature::*; use bouncycastle_hex as hex; - use bouncycastle_mldsa_lowmemory::{MLDSA44PrivateKey, MLDSA44PublicKey, MLDSA65PrivateKey, MLDSA65PublicKey, MLDSA87PrivateKey, MLDSA87PublicKey, MuBuilder, Polynomial, MLDSA44, MLDSA65, MLDSA87, MLDSA_TR_LEN}; - use bouncycastle_mldsa_lowmemory::{MLDSA44_PK_LEN, MLDSA44_SK_LEN, MLDSA44_SIG_LEN}; - use bouncycastle_mldsa_lowmemory::{MLDSA65_PK_LEN, MLDSA65_SK_LEN, MLDSA65_SIG_LEN}; - use bouncycastle_mldsa_lowmemory::{MLDSA87_PK_LEN, MLDSA87_SK_LEN, MLDSA87_SIG_LEN}; - use bouncycastle_mldsa_lowmemory::{MLDSATrait, MLDSAPublicKeyTrait, MLDSAPrivateKeyTrait}; - use crate::{MLDSA44_KAT1, MLDSA65_KAT1, MLDSA87_KAT1}; + use bouncycastle_mldsa_lowmemory::{ + MLDSA_TR_LEN, MLDSA44, MLDSA44PrivateKey, MLDSA44PublicKey, MLDSA65, MLDSA65PrivateKey, + MLDSA65PublicKey, MLDSA87, MLDSA87PrivateKey, MLDSA87PublicKey, MuBuilder, Polynomial, + }; + use bouncycastle_mldsa_lowmemory::{MLDSA44_PK_LEN, MLDSA44_SIG_LEN, MLDSA44_SK_LEN}; + use bouncycastle_mldsa_lowmemory::{MLDSA65_PK_LEN, MLDSA65_SIG_LEN, MLDSA65_SK_LEN}; + use bouncycastle_mldsa_lowmemory::{MLDSA87_PK_LEN, MLDSA87_SIG_LEN, MLDSA87_SK_LEN}; + use bouncycastle_mldsa_lowmemory::{MLDSAPrivateKeyTrait, MLDSAPublicKeyTrait, MLDSATrait}; #[test] fn test_framework_signature() { @@ -42,10 +45,11 @@ mod mldsa_tests { fn rfc9881_keygen() { // note: same seed for MLDSA44, MLDSA65, MLDSA87 let seed = KeyMaterial256::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), + &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap(), KeyType::Seed, - ).unwrap(); - + ) + .unwrap(); /* MLDSA44 */ let expected_pk_bytes: [u8; MLDSA44_PK_LEN] = hex::decode("d7b2b47254aae0db45e7930d4a98d2c97d8f1397d1789dafa17024b316e9bec94fc9946d42f19b79a7413bbaa33e7149cb42ed5115693ac041facb988adeb5fe0e1d8631184995b592c397d2294e2e14f90aa414ba3826899ac43f4cccacbc26e9a832b95118d5cb433cbef9660b00138e0817f61e762ca274c36ad554eb22aac1162e4ab01acba1e38c4efd8f80b65b333d0f72e55dfe71ce9c1ebb9889e7c56106c0fd73803a2aecfeafded7aa3cb2ceda54d12bd8cd36a78cf975943b47abd25e880ac452e5742ed1e8d1a82afa86e590c758c15ae4d2840d92bca1a5090f40496597fca7d8b9513f1a1bda6e950aaa98de467507d4a4f5a4f0599216582c3572f62eda8905ab3581670c4a02777a33e0ca7295fd8f4ff6d1a0a3a7683d65f5f5f7fc60da023e826c5f92144c02f7d1ba1075987553ea9367fcd76d990b7fa99cd45afdb8836d43e459f5187df058479709a01ea6835935fa70460990cd3dc1ba401ba94bab1dde41ac67ab3319dcaca06048d4c4eef27ee13a9c17d0538f430f2d642dc2415660de78877d8d8abc72523978c042e4285f4319846c44126242976844c10e556ba215b5a719e59d0c6b2a96d39859071fdcc2cde7524a7bedae54e85b318e854e8fe2b2f3edfac9719128270aafd1e5044c3a4fdafd9ff31f90784b8e8e4596144a0daf586511d3d9962b9ea95af197b4e5fc60f2b1ed15de3a5bef5f89bdc79d91051d9b2816e74fa54531efdc1cbe74d448857f476bcd58f21c0b653b3b76a4e076a6559a302718555cc63f74859aabab925f023861ca8cd0f7badb2871f67d55326d7451135ad45f4a1ba69118fbb2c8a30eec9392ef3f977066c9add5c710cc647b1514d217d958c7017c3e90fd20c04e674b90486e9370a31a001d32f473979e4906749e7e477fa0b74508f8a5f2378312b83c25bd388ca0b0fff7478baf42b71667edaac97c46b129643e586e5b055a0c211946d4f36e675bed5860fa042a315d9826164d6a9237c35a5fbf495490a5bd4df248b95c4aae7784b605673166ac4245b5b4b082a09e9323e62f2078c5b76783446defd736ad3a3702d49b089844900a61833397bc4419b30d7a97a0b387c1911474c4d41b53e32a977acb6f0ea75db65bb39e59e701e76957def6f2d44559c31a77122b5204e3b5c219f1688b14ed0bc0b801b3e6e82dcd43e9c0e9f41744cd9815bd1bc8820d8bb123f04facd1b1b685dd5a2b1b8dbbf3ed933670f095a180b4f192d08b10b8fabbdfcc2b24518e32eea0a5e0c904ca844780083f3b0cd2d0b8b6af67bc355b9494025dc7b0a78fa80e3a2dbfeb51328851d6078198e9493651ae787ec0251f922ba30e9f51df62a6d72784cf3dd205393176dfa324a512bd94970a36dd34a514a86791f0eb36f0145b09ab64651b4a0313b299611a2a1c48891627598768a3114060ba4443486df51522a1ce88b30985c216f8e6ed178dd567b304a0d4cafba882a28342f17a9aa26ae58db630083d2c358fdf566c3f5d62a428567bc9ea8ce95caa0f35474b0bfa8f339a250ab4dfcf2083be8eefbc1055e18fe15370eecb260566d83ff06b211aaec43ca29b54ccd00f8815a2465ef0b46515cc7e41f3124f09efff739309ab58b29a1459a00bce5038e938c9678f72eb0e4ee5fdaae66d9f8573fc97fc42b4959f4bf8b61d78433e86b0335d6e9191c4d8bf487b3905c108cfd6ac24b0ceb7dcb7cf51f84d0ed687b95eaeb1c533c06f0d97023d92a70825837b59ba6cb7d4e56b0a87c203862ae8f315ba5925e8edefa679369a2202766151f16a965f9f81ece76cc070b55869e4db9784cf05c830b3242c8312").unwrap() @@ -60,7 +64,11 @@ mod mldsa_tests { // run keygen from seed let (derived_pk, derived_sk) = MLDSA44::keygen_from_seed(&seed).unwrap(); let sk_bytes = derived_sk.encode(); - assert_eq!(&sk_bytes, &*hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap()); + assert_eq!( + &sk_bytes, + &*hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap() + ); assert_eq!(derived_pk.encode(), expected_pk_bytes.as_slice()); // also test the `impl Eq` @@ -74,15 +82,13 @@ mod mldsa_tests { let mut wrong_sk_bytes = sk_bytes.clone(); wrong_sk_bytes[4..8].copy_from_slice(&[0u8, 0u8, 0u8, 0u8]); match MLDSA44::keygen_from_seed_and_encoded(&seed, &wrong_sk_bytes) { - Err(SignatureError::KeyGenError(_)) => {/* good */ }, + Err(SignatureError::KeyGenError(_)) => { /* good */ } _ => panic!("sk_from_seed_and_encoded should fail with InvalidSignature"), } // check that it outputs to the full encoding correctly assert_eq!(derived_sk.encode_full_sk(), &*hex::decode("d7b2b47254aae0db45e7930d4a98d2c97d8f1397d1789dafa17024b316e9bec939ce0f7f77f8db5644dcda366bfe4734bd95f435ff9a613aa54aa41c2c694c04329a07b1fabb48f52a309f11a1898f848e2322ffe623ec810db3bee33685854a88269da320d5120bfcfe89a18e30f7114d83aa404a646b6c997389860d12522ee0006e2384819186619b260d118664d4a62822184482402898146148a6614c4248a19208c2382951244808a125c2083108c47120140914836c18a78084106ec9c07022b56408b0610c070498124451886959004622932041062e42b64c01164914284c41a85180460a5116515a0820022244dc9849d13251e13065d3c08592a85112a1640039220946621cc70cd9086dd0062652408580443091062c50c80924c5841a966d4a982c99066da4443220a7645a326e11b57020926124138e04852c0a4872c8a051d3082a99208058242024074e59148810a46460c06de0b28d1b1909203422c024410943710a212061a2015222521b80809a340013934dd3322922170a9892691a14512027219cc02062a2814818691a854d8344695b2041031242cb184601a90d0c023183b0215a224ac89205d9906904306a4b064ad2b2011c404081423252327254a6405a18100c321292c2805212625c82280bb46c03428d53100c14010ee1365288842491020a63462620062911c228d0204802b36ca236095a8648cbb4618b4662c440821a890910024d24b24520122524c90588288cc9c04d5948220a276ec134644c90605b445082864943880443b28c603080a2882d84a46d8ca629d0c68442064689885100a98d01498de4380da4068dd3947142b26c1a84611ba32842b42808a0711ac531e0a04c013765242862142890091061d940221b3360090292d02481200408491844a3222d5c8844149808a446610195640b390a0c9450ca406ad2b220c0380182308e13b908918084148829c0189112350da02422e20406d9c2850428121cc989180272d24029c20812d8062a9994719bb8682384291a2289144511dc82445096450c4484c0b2049aa60543862c44326e88442120a84c9a3070e3b82d63268803254903438c48a809ca147253344e1243081ba704593022d99480e234228142129c302a9434266104452426281346094a326d11280918b82562281113410d41b21190844c8b1212a2c688c9c030220606d2188e848630904452128831d9207113c52843060e033060cca6845826524c88011ef72562c85ffa43acfa49217f2b172d7bbc14620e6d980a71aabbdf0c45e9a206ecb1423fee15decc17601300149d9223cd6e6c6e1fa8e41fc7c64938ab68905fd3dcda50d87082e7d0d71d1bc9b2b84c85523ca8fe6cad294adf83be15b108ff721d0cc87bc3dd3a7590184b0e845663a91fc9e1c3c53a61d867420b04f092355753bc65a06368fd41295fd09924132c6f91f67964c142674a725c343914c4cecf58c074bcaf4558c97bf7911e07aa6d0938f2ee2bb3c1a8c595d635e84342fdea01dc24b211ad2fc281cf77e59110c7abc54bf0c86d480b9be276471dc9d603cee98cfdab3e9fcfb703793560549ea4450fa7b33fb9169c44b4d25fb9c457f49791cd3da03eac96095813c105132ccda4e63e49228cd23d8a1f37856f142d93b90db09f82af89258c63aab8047a80c036c9357ea2046f8dc6354f0c5295f342bb417d3cfeb0b1fd33622c29e14cbbd92e1363c65ebd4504b7512329b9670e32e1b2c67a54e7f1a55f8b9f9ea04e8ca3a705e62a3c5e637374afb7aeb6ddea612cde28f01a202d7aa4e34722d27dd3f9b89894d019fd5d4d7119efe3723bba104cb8bb0981e074de3afe200daaaead826cc45f244dbf431afab34efbdf782474d2fd57118f646214934ed99cba3b003e8d67a3836f6f19fc41910ce5163ee3ae99eb84d514eb761e63684ea56f9791d2dd4aac6e6168b948c817f75a222acb0e8cdc03cc4afe8f67157e1a363b7faeff9f172b98913677c5a1dd085e9ee4c22052c1af58193116673dcd3bfc5f34b855dcc6c77885649e9e71f43d4aea0f4b72ca7eda0578ba13d31a658d2d060a9a66ff69ed1be7997a2fb1d2723d38f9bfabe18f8e7b3cda906e4e9b5e942c8eaeb296070ebfd364947a940cc978bed66b37749e6d5dcd7be8c494440e2b84cecfefb98c0bedfb3c41e3359d2cd7197fbe720c48aa6c6b6465c1ee63e3569c2adc744491370b7f7826fe0b77a1d19d64101d032b918106b42d2ef73747e5601fe4ba50f23ede521f031a817d15294a43722e8378784b6db0cf1ba9e8ae911d9201b9ce9cc3019c6f5c27cb98da26144b64225a7c932b30f761e78a2d59a1d8b83ec6344a2f6dd47e765706d00bf4a79a6a926c3ba91d812c8f2c797ab1796709e5d16856778293529f0286d015c3b5399619642a333e9e593d6e3f5353994208e9e6a332851d7f652522a928b917e27e2d6d42137dfe2ebfa6fb1c67b26c0254528685f7ebdbe315a68eaa2da769e8a9f42d3e60007c71330926b2c0012d83ead4e4fd1ed872ccd1972201d2b027f3545ac2d30cd78bc1d740feccbc6fc2a0446c6e30eac51f5a69098aa2d447f2085b4e4e4b92ccc26921d2de478518cd090ce267aea2d27ada57fd88b4976d89fb843cdccf49a76ca2679e6801bfa7fb031896fb50629704b9923936bb5dd385311121cadfb11995e59b73034cf67ed03ab813867648d025828087e949a9afd16b95d72d99b1edca257aac132ffb7a0709aed5a9c0ff05fb0f2bbf28409eed7b5f5801be964ced019e1cb7851d3851f10290674e19ffb008b301c4acf641a2bb14216e1d69cabf52b5ef227496b0f30799a855d117fad3744a6fa33503ea798b52ddd7ee5426609dbfcd3f0c13b164d6c051f7ed4a119719a712e388d328402081ff1354b554d2c237afed3b151c4ba8e9f4bdeb8499a3066e26bbc69e8af089dec71731d1dc529eab17ef7374734c0fe475494c83836bdd34a03b9bc89914716061bfb98ec6e61c3ed4438edcaf25243c647086b9ea7018b0d9a8a0b00cecb00abde2498d69c2336101a772cbe4f571523f51bd05882cdf358b849cc140aa1faf22423a12851ce0e33fd48975a4959fa5c5fe418c93908191ab6e741b77bfe02cbd698ee795c466d615619e6441382c6eac01834ee9ab73cea80bbe235c78da91bd79b6f82f899785d68700d393e675c2224d6b7a1ad21320495679adaed70167b50866713a53109db7b6f7d81304ecdfd83b319b1ef248306b45ad29e7ddcc863dac56048b5d69ea175011f7614c00a86a863cde1872a8932878b9ac7e1ac5bda4997b72064f0cd75f4c814e034de11acb9013cf7ea926b4e7eaace070c7ba2188efad2e431e1223d45dd05c4d8403c2e45cee6413ecbe7527e873e455c4e610a61839aacc0bd56d2483e78f298b66a478eb2f558cbafca86be847baeb02c5b216c8cd88fea4df249b09e670a20703abac24b0a91abc4a5646601442ba10becfd30993880051d07f56a05a9379e7a8e6befee3f22faa106398f7706006e42e9be1ef89d25c272f11a95095c587d713732284de9dbd3c7217b0689e21d8eb0ff69668").unwrap()); - - /* MLDSA65 */ let expected_pk_bytes: [u8; MLDSA65_PK_LEN] = hex::decode("48683d91978e31eb3dddb8b0473482d2b88a5f625949fd8f58a561e696bd4c27d05b38dbb2edf01e664efd81be1ea893688ce68aa2d51c5958f8bbc6eb4e89ee67d2c0320954d57212cac7229ff1d6eaf03928bd51511f8d88d847736c7de2730d5978e5410713160978867711bf5539a0bfc4c350c2be572baf0ee2e2fb16ccfea08028d99ac49aebb75937ddce111cdab62fff3cea8ba2233d1e56fbc5c5a1e726de63fadd2af016b119177fa3d971a2d9277173fce55b67745af0b7c21d597dbeb93e6a32f341c49a5a8be9e825088d1f2aa45155d6c8ae15367e4eb003b8fdf7851071949739f9fff09023eaf45104d2a84a45906eed4671a44dc28d27987bb55df69e9e8561f61a80a72699503865fed9b7ee72a8e17a19c408144f4b29afef7031c3a6d8571610b42c9f421245a88f197e16812b031159b65b9687e5b3e934c5225ae98a79ba73d2b399d73510effad19e53b8450f0ba8fce1012fd98d260a74aaaa13fae249a006b1c34f5ba0b882f26378222fb36f2283c243f0ffeb5f1bb414a0a70d55e3d40a56b6cbc88ae1f03b7b2882d98deea28e145c9dedfd8eaf1cef2ed94a8b050f8964f46d1ea0d0c2a43e0dda6182adbf4f6ed175b6742257859bf22f3a417ecf1f9d89317b5e539d587af16b9e1313e04514ffa64ba8b3ff2b8321f8811cb3fb022c8f644e70a4b80a2fbfee604abb7379091ea8e6c5c74dfc0283666b40c0793870028204a136bf5da9568eb798d349038bdb0c11e03445e7847cb5069c75cf28ac601c7799d958210ddbcb226e51afef9f1de47b073873d6d3f97456bede085082e74a298b2cd48f4b3093155f366c8fa601c6af858dfa32c08491b2a29887f90335949a5d6edaa679882a3a95d6bf6d970a221f4b9d3d8cbf384af81aac95e2b3294e04789ac83727a5dc04559f96af41d8a053516feeeebc52746eb6ab2819e09108710d835f011fa63065872ad334d5cdffb2b2310507e92fc993ae317da97f4f309cdaf0f67ed99d90215576083849f953b246d7fedb3fdb67679850a5ad404e64147fb7cf4f6aeddd05afb4b834968d1fe88014960dce5d942236526e12a478d69e5fbe6970310b308c06845018cfc7b2ab430a13a6b1ac7bb02cccbb3d911ac2f11068613fbe029bfdce02cf5cd38950ed72c83944edfbc75615af87f864c051f3c55456c5412863a40c06d1dab562bdff0571b8d3c3917bbd300880bba5e998239b95fa91b7d6416d4f398b3adbcd30983ed3592b4d9ef7d4236fd00f50d98aa53a235ac4172720f77d96172672980cfe8ff7a5a702783edc2ba31b2259015a112fc7f468a9c2f9464039002d30ef678b4cb798bc116216bf7a9a7c18ba03b7b58fd07515d3115049d3614be7a07e744300750df1d2c58753389059eafc3d785ccdd31c07648bedc03a5c3b8ad46d064d59c13d57374729fc4e295362e2a5191204530428bc1522afa28ff5fe1655e304ca5bc8c27ad0e0c6a39dd4df28956c14b38cc93682cefe402bbd5e82d29c464e44eb5d37b48fc568dfe0cc6e8e16baea05e5135590f19294e73e8367b0216dbb815030b9de55913f08039c42351c59e5515dd5af8e089a15e625e8f6dee639386c46497d7a263288774de581a7de9629b41b4424141f978fb8331208efdec3c6e0de39bc57063f3dcd6c470373c08891ea29cbc7cc6d6483b8889083ace86aa7b51b1c2cfe6e2ad18d97ce36fbc56ea42fae97e6a7ac114864478c366df1ebb1e7b11a9098504fd5975bdf1f49dc70002b63c1739a9d263fbad4073f6a9f6c2b8af4b4c332a103a0cffa5deeb2d062ca3c215fd360026be7c5164f4a4424ef74948804d66f46487732c8202c795478647b4ea71d627c086024cca354a41f0877b38f19b3774ad2095c8da53b069e21c76ae2d2007e16719ed40080d334f7da52e9f5a5990439caf083a95b833f02ad10a08c1a6d0f260c007285bd4a2f47703a5aef465287d253b18ac22514316210ff566814b10f87a293d6f199d3c3959990d0c1268b4f50d5f9fcefbbf237bd0c28b80182d6659741f14f10bfbb21bba12ab620aa2396f56c0686b4ea9017990224216b2fe8ad76c4a9148eef9a86a3635a6aa77bc1dcfb6fba59a77dfda9b7530dc0ca8648c8d973738e01bab8f08b4905e84aa4641bd602410cd97520265f2f231f2b35e15eb2fa04d2bd94d5a77abaf1e0e161010a990087f5b46ea988b2bc0512fda0fa923dadd6c45c5301d09483673265b5ab2e10f4ba520f6bbad564a5c3d5e27bdb080f7d20e13296a3181954c39c649c943ebe17df5c1f7aae0a8fe126c477585a5d4d648a0d008b6af5e8cd31be69a9296d4f3fd25ed86f221e4b93f65f5929967533624b9235750c30707550b58536d109a7131c5a5bbe4a5715567c12534aec7660761eebb9fae2891c774589b80e566ad557ddef7367196b7227ea9870ef09ddfec79d6b9319a6879b5205d76bf7aba5acf33afb59d17fc54e68383d6be5a08e9b66da53dcde008bb294b8582bd132cdcc49959fdbc21e52721880c8ad0352c79f03a43bbd84c4cdfdc6c529005e1e7cd9a349a7168a35569ba5dea818968d5a91466bd6e64e20bf62417198afc4e81c28dd77ed4028232398b52fbde86bc84f475b9016710ce2aabc11a06b4dbac901ec16cf365ca3f2d53813948a693a0f93e79c46ca5d5a6dca3d28ca50ad18bd13fca55059dd9b185f79f9c47196a4e81b2104bc460a051e02f2e8444f").unwrap() .try_into().unwrap(); @@ -93,12 +99,14 @@ mod mldsa_tests { assert_eq!(pk_bytes.len(), expected_pk_bytes.len()); assert_eq!(pk_bytes, expected_pk_bytes.as_slice()); - // run keygen from seed let (derived_pk, derived_sk) = MLDSA65::keygen_from_seed(&seed).unwrap(); let sk_bytes = derived_sk.encode(); - assert_eq!(&sk_bytes, &*hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap()); - + assert_eq!( + &sk_bytes, + &*hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap() + ); assert_eq!(derived_pk.encode(), expected_pk_bytes.as_slice()); // also test the `impl Eq` @@ -112,15 +120,13 @@ mod mldsa_tests { let mut wrong_sk_bytes = sk_bytes.clone(); wrong_sk_bytes[4..8].copy_from_slice(&[0u8, 0u8, 0u8, 0u8]); match MLDSA65::keygen_from_seed_and_encoded(&seed, &wrong_sk_bytes) { - Err(SignatureError::KeyGenError(_)) => {/* good */ }, + Err(SignatureError::KeyGenError(_)) => { /* good */ } _ => panic!("sk_from_seed_and_encoded should fail with InvalidSignature"), } // check that it outputs to the full encoding correctly assert_eq!(derived_sk.encode_full_sk(), &*hex::decode("48683d91978e31eb3dddb8b0473482d2b88a5f625949fd8f58a561e696bd4c27d853fa69b8199023e8cd678dd9fabf9047646ffd0cb3cc7f795805a71e70d2371b0563e3cd3346149c8c9ebcf23b0a4e5a900eea9c6562790a7c63e38663daa2dddb6e480dc405a1e701948b74841ef5cc1c3f2bf327972e9510510cd5375ecc0855717711872221862381000424778061475007501717035504515125471838046175722244108868608646012747567180870666864332444122043638667502823634244322057364106455547722755681433614625508206437685468754353751068718333805475052580752818843811087260202008588301836113828212061711578768788878643754601657155084718866072732880664741856762180318276641578245025646643113504364780126673143011660655864718368863503847861101202356116137860785321240075478823043666116604255418285605367785638434430632610770731784272141116530385276867460150823735320766107504681248066603032652312445408800318088767217307182472151278011654474866172233380866064468352158420368011802118183317735453488100448653674370577258833460384232856810060426042584560235682051838638432421224245645858677145728504788717180618836086864156508116502646700608266227383172407257300727288620667588682607064020330343663155464245345667187345658370225084685628807036708462371710065717584778708655537822351446772856730322870014332061715845526632502651334777380355164313473510662751757402468881706743468186017652453330872104343401032287635155265081307745444168154183636411204026873043677712808846355453006245810458365124842780345166635843785601465115742321436685224777313450178362420550006484471234408800604735405783336308210615225207248851348637067622588571265673476816464684258708122705500838320023208066345336003346857247063554003577122752307142536874374570056643224482852072183330205337334077278055253063525040673346131807280717248377634573185851602333443625164338160858773462428830070365853755007552315037021324630437086806361503030043586357080211066473463522620330438021085287578321078867480856347436734284058466841437005510873426447721127384736526472577144704178644260247118740812216605847178137067680817058185585471363421075580163583585184403847110338742628247741365544270734635777500662562684202124683864616646031225388845400845734464754472560546166846630880638271563287183840652247681160662130330186802801384630505657238758365723230688046122606651675570532413227673517080153001628460134887701118815571315464311704732882856368234555041862765631111687505104254414427852211171788153685157447166255365583630250285576875327137103723705714761713651841242366444664143520521085157033363860258426628148110546268173038756433216588568663632813406254012040886547886171657623726234867030115115632050753502122108426531435567111525720106853630150557586058784314313278788087384788637881813873426178388524667733506021151464238232680135440783475385535752832335187601152134325773333655188615816168241842212230841448151201103024777242544366067717707603014525403500183873237735265086357113734481605277456553730085837785035121115480628850180268138652053468013207241803213005723864076427114101838525510632607104865176833828572762354518735083132886376661426311675033112553764176031433177212234418a82e4f5c9ea0faf99eb04d78a7332711117c33f18eca21f8743376ada5219804a7ed9a5557fcd67a3550b3a4b8c588629c021475fa3d56d5d6cfbb1a09bda8d14de622ddff16d8bc99b14278a8af1d76bed157672dd9c32316f97e8daadef8d9da69586725567fb96b59990d4bf0bc9c195b90b74295f5675b24257c2710c175b0153f2911328c2eb7abb9ad46e70a8b53c39ea642cee4b3cb42620e863ce8b650ce8adcd923721a1687023c673a8cbb6b03d51cd197e8c346ebadce93950f88cee201db9e320843e29f300d9a19500d70a4caf272c69e4eef69fbb8a55efd7ca2bed990d2d3b582848f9c45c2abc54cfc47d34f06c0ffa56fcd762ab9cba9146d7725218963b240d72b6d22c93171fbd47788b76e72042def0878d23df631a1a1e5a6027686de5b4a10e91069c8f2ba0259b04d6409da96567ca52da497026e583a0ecefc1f01e6b988e21f9767a2b7e1672deb9a1e2a3fcc863aa91517c334620601b4fe79730e934935f4b6fbc4e32695145c2b5f6a127fecc0a277451ebc3fd523444f9ee7c9c34534f356db544fc31c1bfde5f65c77ea2f7c2eae4c55ebaf104271c566fd4ebac71c7a62c74952817ae675504d9599b1b762b6aca168a83248c9d9adb0ceb1556e5759490bbc0c7900795ad72123038b662f64f106a9993681a25d59af7bc97a235be9284c5bc45a6c90cb1c2999c663d96b478e2307f85548957d65740e2673e9ebd1352829038f462b8fd3b5681da55c0252523853525ea0ad647e71ac2c5a8893e603ac97e56c04ceb2f26f5c5b4b6d94ab811380fd00f2208fe86535086aebfd35c29120624c04fbb6113929d9c556350253766c209fdba83c95fccd342a28099355d00bc863f4eef596eb0b42ebcc7c79491cceae205ea0b8059fbb8a5726c5949d2b15e7e29c51fc9b02ee1a4fc357b5f1bef9c4add46a2a920c2fbf08a37eb1514bfa15110a4392a74c6f13c50c5cffd97531098d7cd23b60eb35c4a428b46c55386e1010c4ba7f70e4c7ecb7575f3063a71e84dfdcf09a58b2cdb0f99f27ed378610d25cbad7bfa6ba0d59189cfe88eab9b46d7e6db0307eabe4198e99bd71f779ab66581e0912fc7b1d2585245e9a12687a975cd5e8e1dcc045d5f891c4c685db07cf81e77389b363eb6bdfe39b27ff84c97eefee162e3b451fe6914719cb6436d855960ff915d7cea6adeafdfc1c05786c49f923a474ffdfc3153a06e6ed0b0ad220d72524434d5273c0aab6dde4e91476d581a2695a60de6d9f44d77aa08266e938eeb4a9597c9b64986059e49262a4eab2454e14015ad0536c42733a5d77d7995c2a20446009ebfe5632c80c08ed2b97af35066489f597eb1b1f11f04f60e0c9040159c44ab3e60e0a15229d191228bed17bbc3ac939b3c67cee135f352c27216c9c31f72a3e87040c5f619306eb0b6cca2a9ce7b22a1694d00ca9c05e315126457f26ce84f9617241860782f864b473d84017491902b1bdc8cdc5800dd46127fb80a71c095b473a562529b3b1e7e437e158a5f6666e9974d005b062c2309e6dce98f9b658c6e3f9a216d58c8c9142bd1c8c85a9da872ebbfad3fea9d9aba2b68c0e8f19c6ff5f00584d45daf9d6c9d69ed04b8da8d687258b77807927612c530446fea7697ae3f926698929bc6a5a8cf3e2024c0f0c5ee57b5869bf981881caf9e3665fc7f7efc678929f87a56eaa42ea4d1ff6691822dd79a47096b776d1d8f01456e5873b0738406c382c573ae9cde2d9e7f231b6cc5c676e7cf43963373013a58075381ff0949be084546d72e4f8a3e5fe4aa5091add234e2afe0030b1b663ae9d2d32410986b9402aaaf2465b74a5e2d0bc38e3a92bbddd8a1fed7b948c23cce6f8c08fe356835ba65b0f984068616ef48138efd89bf357a54d2ebbf376cbdcc69c5f1f61c64d2794bc06ccb9abdf66e25085d8c830e2ae3b0fe0f07a7af8b9320bf342970997d67d7c12593a8fbfade635aac53083a7022c47d5f77a52b57b598da9392ae6d86afc46fc06455181b9c75a646dc21f81e4bf213753de737fd2a140027920add35a223f9f5f4465ceb60c03ed0455a333a5cc83adbf43f1f42c2ccb8328c21c7ab7faed2b21cfade2da55223aaab2af9b41c7332341746341b39aa2f43815650f5480511424cfa6901779c4d18b638cc0287aaaf31680338d20b17c7449fdc6a278a8d96a82ee4c4eca40125e2d65290071c7aef1be6a991598fb9d59512523bcd4b38c566b8e80a73ae333e134414327ef1d83c47c49dfe7936df1338a5e247787868fc84fdcb95ac89c185c4bb5fd57b2338ac42b41c10a823df39624f36b15a2f067584e06ca2e08ccaff1618fe01dd06df3512e0b724dec8506da24215acacc2c51b82ad8d302002fb41068b1da4f8bb147987b3516bad5dbddf01318fd3fa9bc43702ac498c719d95f2e841b622a5e4848a3c5c262959992ea7a7d72ca8a368028f497dfad93355cbb1bb9786d14ff2cf590317848f95856427110dda36f5192a816ce9c8816cc7bbfc804efc40085a3850b89f1e7fe5656dba410f906a97c32336c1ae7e81737a83e087354e428da8538d948dbf5dfacb59dd2b5fd3bc803f4ba432c9a739df2cfa9ed9484320f97edff1a48c6b86b3002cfb772dd5e562bc4c3d683ed964b6199fa0514b0790d958095b7b85c6be875fbb559e1930146ccea63a388a194fe09c3dea03be52de27e901017afe809af630a7382bf5c4cd4d1b8f41579fb4348ede4ca05f4cd3f139a31b2544e516dbe4086b9bb4b2bed47e2d230982dd5192429d377b7c0745cc068e2f5a4aa04c7ff87209ed1259976a0fc9b25e9e851d4e3502c02c85d6dff029e211d01ebf0e9e7188d568f8437d813b0f122f2fb17603b693ed9c38f17cfd50b815e6d9dfc0ed2ccf19f6399274a1420f235a59d8bf724345e14e45d9e4be8934dfc3fa92678db61d7118bf53cb8a2225b335f7eae50e3f941237628db76d8ea38f77a72af3a26c81fe43523b335535a5d1db7c38f341082bb5734d089e8ae309cfda3a0bcb5cd5b097113c8edf9616aa4f6e6631b9125276fb3f680a34341c3db668dc6cad45fc93b2708ca2af75ccce734fd191c50089dad53982fddae02531ff93e1f21ff395fc0a12874edf06b6f9647e95a7324586c71dfd91d901d621858190fecd00ccd110bbac59f96cb884c3c93994748a56f41283bfc41fb89052153a894588c3cb9017f3d66326c985637e575acb812346342654025d602de3ba940c19ac1a633dffda977b529b8013e19c1d6d0680f4dae62c924450ae66aab82f21473061dab3d62b247f907e3551939ad3f5465e9d08a82bfea17eea1b6b2b923757477f993000b2f43b70f28aaab1fe9a26ad1fd3361616c0b0e242fe76604b7033a1f30e97e28f526ca3c880fe2b8d9d1b0c9ff188b31cb9d97425acab9b216d98a6ae355e583da71e8864ee3d16b0759796190ef545c1e62bfef92af6ca147b13244d6c892fc8ef223ab3f43f924c2f466097ee8").unwrap()); - - /* MLDSA87 */ let expected_pk_bytes: [u8; MLDSA87_PK_LEN] = hex::decode("9792bcec2f2430686a82fccf3c2f5ff665e771d7ab41b90258cfa7e90ec97124a73b323b9ba21ab64d767c433f5a521effe18f86e46a188952c4467e048b729e7fc4d115e7e48da1896d5fe119b10dcddef62cb307954074b42336e52836de61da941f8d37ea68ac8106fabe19070679af6008537120f70793b8ea9cc0e6e7b7b4c9a5c7421c60f24451ba1e933db1a2ee16c79559f21b3d1b8305850aa42afbb13f1f4d5b9f4835f9d87dfceb162d0ef4a7fdc4cba1743cd1c87bb4967da16cc8764b6569df8ee5bdcbffe9a4e05748e6fdf225af9e4eeb7773b62e8f85f9b56b548945551844fbd89806a4ac369bed2d256100f688a6ad5e0a709826dc4449e91e23c5506e642361ef5a313712f79bc4b3186861ca85a4bab17e7f943d1b8a333aa3ae7ce16b440d6018f9e04daf5725c7f1a93fad1a5a27b67895bd249aa91685de20af32c8b7e268c7f96877d0c85001135a4f0a8f1b8264fa6ebe5a349d8aecad1a16299ccf2fd9c7b85bace2ced3aa1276ba61ee78ed7e5ca5b67cdd458a9354030e6abbbabf56a0a2316fec9dba83b51d42fd3167f1e0f90855d5c66509b210265dc1e54ec44b43ba7cf9aef118b44d80912ce75166a6651e116cebe49229a7062c09931f71abd2293f76f7efc3215ba97800037e58e470bdbbb43c1b0439eaf79c54d93b44aac9efe9fbe151874cfb2a64cbee28cc4c0fe7775e5d870f1c02e5b2e3c5004c995f24c9b779cb753a277d0e71fd425eb6bc2ca56ce129db51f70740f31e63976b50c7312e9797d78c5b1ac24a5fa347cc916e0a83f5c3b675cd30b81e3fa10b93444e07397571cce98b28da51db9056bc728c5b0b1181e2fbd387b4c79ab1a5fefece37167af772ddad14eb4c3982da5a59d0e9eb173ec6315091170027a3ab5ef6aa129cb8585727b9358a28501d713a72f3f1db31714286f9b6408013af06045d75592fc0b7dd47c73ed9c75b11e9d7c69f7cadfc3280a9062c5273c43be1c34f87448864cea7b5c97d6d32f59bd5f25384653bb5c4faa45bea8b89402843e645b6b9269e2bd988ddacb033328ffb060450f7df080053e6969b251e875ecec32cfc592840d69ab69a75e06b379c535d95266b082f4f09c93162b33b0d9f7307a4eaaa52104437fed66f8ee3eabbd45d67b25a8133f496468b52baffdbfad93eef1a9818b5e42ec722788a3d8d3529fc777d2ba570801dfae01ec88302837c1fb9e0355727645ee1046c3f915f6ae82dad4fb6b0356a46518ffc834155c3b4fe6dafa6cc8a5ccf53c73a0849d8d44f7dcf72754e70e1b7dfb447bb4ef49d1a718f6171bbce200950e0ce926106b151a3e871d5ce49731bd6650a9b0ca972da1c5f136d44820ea6383c08f3b384cf2338e789c513f618cc5694a6f0cee104511e1ed7c5f23a1ebfd8a0db8424553240156dbf622831b0c643d1c551b6f3f7a98d29b85c2de05a65fa615eee16495bd90737672115b53e91c5d90028cf3f1a93953a153de53b44084e9ccff6b736693926daefebb2d77aa5ad689b92f31686669df16d1715cc58f7a2cfb72dd1a51e92f825993a74022be7e9eb6054654457094d14928f20215e7b222ac56b51adbec8d8bdb6983979a7e3a21b44b5d1518ca97d0b5195f51ed6a24350c89747e1edea51b448e3e9147054ce927873c90db394d86888e07dff177593d6f79e152302204aeb03be2386af3e24078bd028b1689f5e147c9f452c8ceb02ec59cc9db63a03576ceeafe98239023897da0236630a53c0de7f435a19869792fab36e7b9e635760f09069e6432e700035ac2a02879fff0a1e1bec522047193d94eb5df1efd53eea1144ca78940852f5ec9727904b366ede4f5e2d331fad5fc282ea2c47e923142771c3dd75a87357487def99e5f18e9d9ed623c175d02888c51f82c07a80d54716b3c3c2bdbe2e9f0a9bbaaebeb4d52936876406f5c00e8e4bbd0a5ec05797e6207c5ab6c88f1a688421bd05a114f4d7de2ac241fa0e8bedff47f762ddcbeaa91004f8d31e85095c81054994ad3826e344ba96040810fc0b2ad1de48cfade002c62e5a49a0731ab38344bc1636df16bf607d56855e56d684003c718e4bad9e5a099979fcddeeb1c4a7776cd37a3417cb0e184e29ef9bc0e87475ba663be09e00ab562eb7c0f7165f969a9b42414198ccf1bff2a2c8d689a414ece7662927665689e94db961ebaec5615cbc1a7895c6851ac961432ff1118d4607d32ef9dc732d51333be4b4d0e30ddea784eca8be47e741be9c19631dc470a52ef4dc13a4f3633fd434d787c170977b417df598e1d0dde506bb71d6f0bc17ec70e3b03cdc1965cb36993f633b0472e50d0923ac6c66fdf1d3e6459cc121f0f5f94d09e9dbcf5d690e23233838a0bacb7c638d1b2650a4308cd171b6855126d1da672a6ed85a8d78c286fb56f4ab3d21497528045c63262c8a42af2f9802c53b7bb8be28e78fe0b5ce45fbb7a1af1a3b28a8d94b7890e3c882e39bc98e9f0ad76025bf0dd2f00298e7141a226b3d7cee414f604d1e0ba54d11d5fe58bccea6ad77ad2e8c1caacf32459014b7b91001b1efa8ad172a523fb8e365b577121bf9fd88a2c60c21e821d7b6acb47a5a995e40caced5c223b8fe6de5e18e9d2e5893aefebb7aae7ff1a146260e2f110e939528213a0025a38ec79aabc861b25ebc509a4674c132aaacb7e0146f14efd11cfcaf4caa4f775a716ce325e0a435a4d349d720bcf137450afc45046fc1a1f83a9d329777a7084e4aadae7122ce97005930528eb3c7f7f1129b372887a371155a3ba201a25cbf1dcb64e7cdee092c3141fb5550fe3d0dd82e870e578b2b46500818113b8f6569773c677385b69a42b77dcba7acffd95fd4452e23aaa1d37e1da2151ea658d40a3596b27ac9f8129dc6cf0643772624b59f4f461230df471ca26087c3942d5c6687df6082835935a3f87cb762b0c3b1d0dda4a6533965bef1b7b8292e254c014d090fed857c44c1839c694c0a64e3fad90a11f534722b6ee1574f2e149d55d744de4887024e08511431c062750e16c74ab9f3242f2db3ffb12a8d6107faa229d6f6373b07f36d3932b3bdb04c19dd64eadd7f93c3c564c358a1c81dcf1c9c31e5b06568f97544c17dc15698c5cb38983a9afc42783faa773a52c9d8260690be9e3156aa5bc1509dea3f69587695cd6ff172ba83e6a6d8a7d6bbebbbcda3672731983f89bc5831dc37c3f3c5c56facc697f3cb20bd5dbadbd702e54844ac2f626901fe159db93dfd4773d8fe73562b846c1fc856d1802762840ebc72d7988bde75cbca70d319d32ce0cc0253bb2ad455723ee0c7f4736ce6e6665c5aca32a481c53839bc259167b013d0423395eeb9aaaee3206149a7d550d67fc5fdfe4a8a5c35d2510b664379ab8f72855a2af47abce2a632048eaf89e5cb4a88debc53a595103acce4f1cff18acff07afe1eb5716aa1e40b63134c3a3ae9579fa87f515be093c2d29db6d6b65c93661e00636b592704d093cc6716c2342eb1853d48c85c63ac8a2854462c7b77e7e3bd1eac5bca28ffaa00b5d349f8a547ad875b96a8c2b2910c9301309a3f9138a5693111f55b3c009ca947c39dfc82d98eb1caa4a9cbe885f786fa86e55be062222f8ba90a974073326b31212aece0a34a60").unwrap() .try_into().unwrap(); @@ -131,12 +137,14 @@ mod mldsa_tests { assert_eq!(pk_bytes.len(), expected_pk_bytes.len()); assert_eq!(pk_bytes, expected_pk_bytes.as_slice()); - // run keygen from seed let (derived_pk, derived_sk) = MLDSA87::keygen_from_seed(&seed).unwrap(); let sk_bytes = derived_sk.encode(); - assert_eq!(&sk_bytes, &*hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap()); - + assert_eq!( + &sk_bytes, + &*hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap() + ); assert_eq!(derived_pk.encode(), expected_pk_bytes.as_slice()); // also test the `impl Eq` @@ -150,27 +158,28 @@ mod mldsa_tests { let mut wrong_sk_bytes = sk_bytes.clone(); wrong_sk_bytes[4..8].copy_from_slice(&[0u8, 0u8, 0u8, 0u8]); match MLDSA87::keygen_from_seed_and_encoded(&seed, &wrong_sk_bytes) { - Err(SignatureError::KeyGenError(_)) => {/* good */ }, + Err(SignatureError::KeyGenError(_)) => { /* good */ } _ => panic!("sk_from_seed_and_encoded should fail with InvalidSignature"), } // check that it outputs to the full encoding correctly assert_eq!(derived_sk.encode_full_sk(), &*hex::decode("9792bcec2f2430686a82fccf3c2f5ff665e771d7ab41b90258cfa7e90ec97124d8e9ee4e90a16c602f5ec9bc38517dc30e329d5ab27673bd85f4c9b0300f776389886750b57c24db3fc012e61ede59753337374fa7124991549af243496d0637cb3be05a5948235bf79875f896d8fe0cab30c84948db4d6315aaaf160ac6243664220148161109112c94028922452c62b84500452a08967090126e149370d446108444515896910ca92982b241c90871c428680496894840859b226d1c28645912419cb891840489449005cb3462a086904026922099291305695c3468a4328e19269259461009a44923424d1236615810650128901a334c998631d3a249098225431428c0388103154d5b2886088748233152942225c3c04da49821984020d14286cb40705bb0719c962cc112065346090c450214466e91b42154b08ce446429a208c0121251341055a402213c90ca0184052c230cb342c4bc8681ba4604984846330294aa0695b8004d2380a14264ce2b2448ba211244649c414520b427103b210922880012488e308110a052819c481002022dc446842122244002ac9266a0c8731e0c04499148418360d11374222188c63b2910c9808a1a0010892440413245c987182847184325251b0319c422e1aa82802089101c0890bc7058a246522c2644c88915c826813a56450208621040291944448223022394a02988409a28819192944488c22950ca104720487701221104206841b498589064ad33608dbc04058b6510ca7098c24619990648cc2905b249010a34903256143328a119844c8b22004384110472c19c6441c252c048830d946699b20001b46825aa4805ba0491890250026800bc2315a407254c620c1b03124b14d10952814000aa0c84d54a28823988160900402162c13214091868d08c291911426d0b40c09c66051442e04112600291193c20863a431220028c114080c402c4114069c20725422068b084da148691030411c284944188ecc9648d942501b06490c458823040d20302e23852c14073040b6854cc02044862019006c540248cc886c59063249148404c750134928e40609d3c610c8284c23394452a464cca8494438320a898400342c22858d1031090932651c898c40402921850009a16d84c064e2022d48044012098ee0422e93440812106a01840592308acb348ea2262e5c86110b3508181000023426242389d1840024466013b249242846180271a03890891444d3962da31840232721c0185043c80441428d5c264144a26d48120e4032250b14820a482ecb828803a3601b25268cb82024b08598042108a72c833864543289010401234984029569d1a44d13a40c91460d6194809038455cc65001172053c6289b1810411268901221c01084421692538229812649d8a4059a2624240329e04026d20248112468119989981485c9200d50128c1c0810021000009528c1289059b485d314650a406e11296518c24c213465d830691030521931668c188ac8c0084c9830a3a62041162218052e22252a64b8250ab30163208409800919280e021101a39411e3986c58202109411060362208067112c2855aa085c0c6845c3806cbb669148484532282a1a640cc8600c42622a0a808983472d4204143c4904816681b16521a370250204248488a201141e2006cc0c20c14064911314d19060a8946091b816544c800820670001672cc24508a42899c969064287092b268982662619440c11689d842641a214e62906421c8248b286d5c4292a0c64d0c8580cc884dd4428d42348a0b0451c32686242581123506a04404c894815bb4311c08065c240803276a20c225e1809019b46da3460c4b186050c62c1b922d111504a2000421482ed81606d2108a83a22508310d093851d948490b164c2332251919024a4409d1b2210b832c23258593168544a0441b83500222724b04809b146521936018130ad9460d224561c8b440a1422d02b8090014449bb6110b978c40104a82146ada90051c028e0c1972a3b48d24305011870964c628e4189298b46c61165140460e1c3248da205188368a23b1218290281a1532e2186192048e13b690131368c984684c406d0b330081464dd2380c049681a4885002908522b004d3a471d28010ca964051a641a48428e008520b308cd2380a0c2951c38209ca2091d83692a3a628924222a216011a348637d9a659169881ec21cf4811869d1d7f139f0537e96f1184585405fd17808af1e06239d3b34e5aca8bf1369677b447ac718ac47d850c4d77b0be31dc9f508e3978f24274ab0185f727abdff59f4490371bf04610e364e64ec875ef9d20dc94077e1e166327a879b8ab516160b2a3f77437b9b3cc7d17aeaddc84db62746a35ac096f782f62a7f01aa6d6693deec90b23c66985a02307e0a1cae598a67324dba0f52f22432275e93257065c3b7e5e1cfe1dfd4d0df086df21243414a2d27e20230a829be4eb4c82c16d35f78b0e5e198332e00074bb64612fab17d4c8971cb68e5edab0369f1157b3469abd8384e2d9553f1b78e786e1ee9d0b98d39f83ccecf37d1ebd3a9d63aec766164a10171a4fd8c63daf182c421258c5f529aa55cb7ebae2e1652315e1f71e8a74131410d03247ede11d34db91f6f08aa2478fd789679c04949f71bc0171e07e3a8bb5753dbbdaa411a6350ab46eefbf86fc551c29efe4cdd7661d5cf6c3db22d0cedde599854459d97f20df7455bdf356a198d0f7eb6d34111fc940b25c0543b788edda9d26810eac3d6cc9c51327c2cf83e887d4089e19695e11add837f6f440cc360f93f32fee8a9663712c6bbd38c84ab7b54823ec363eb7e42eb59fc1fce60fbd55307b3ec85fd9daf3206d7b4b3917f1c8b7a92e3c67d89880fdf2e47f5a0c994595db170af41babf5a25b4dc1c42dd6a9db271e764de2fb015a49a850c7919be47006a336e2e325fde53ac599554d0a7de4ef45ec40c39d6baff311beee75d89e02ad31f4be4bd20ae9194f5edddaa6650776116e9f270f77714ad7a8e89acef74b7ff7d8dbec27f8020a985247e2cdacef4894a4d68ba37ca912d6be73501c995181e5b77723350b3631da3700e13fd366e131bf06b36eb6b0345093209f0a7beffae1fdd875b00687c1163c353d7d2ac90937b34e978e92f821adc9662202ece89a17e7bb65ae17d83b90dbbe6a501a4e1345bee4e5a5b53af2e5ba3d1ef3f4e05adf0b3a4cf2e530360fee64929902b571f6fd2e305652a4cb010f79f815e18f2bbb8cc89fa6fc76f77c89e293cf175a0b195800fe72d2ccdd7d75e5bd90bc6ac435d6a440ef852e9a1c8c53de03bf193365d735aaf29c5162a617e364e7f944168d0fb48fef40558f454297cc3dd508662cf23fb88e1954aa45d1c5e115bcc36f05b3e098d555220f40be2629b34507b8464c54c27b5dec78da8f22650514797af86a2512bcb7e2923379ef6d73c137006c1b38f51e37f93585e29041a3e4e3af46007ce13b8b5f7b17d5d65d7d5668e427bcbe7ec1d7c408c054a48c1ae797bf99acbc8d2607522935fd665ea7822d930f23eabff783bb23697569e204b943141e00c08810956be0525365dbab54ed48cb76964ccdf5cbd3aee7282d4a0000d2784d7b8fab16b2f7f0d5225732b1efbc4eb1cfedeb43fde79b69ecc0fbeaa1e6b40728673bd4b2e98a0d4a8f02f853950730f28d35eb12fcc79768b8e18e4bda0e58a331a2f71d7ccc2d451b32b1c65c312acf47ee513b21954c41c00c873872ee94cf14f46037425361f4bdb54821f711460cebae8c07508a9219f88fa6bedaa678eed501944a16ae6f7b5bb7a2e1e357e70d7b98461a2c71cb0fa762d6ad9824081d37f292fd4be8b84c36110dc744360201beebe0bd6c9d05e869256d2ff3f99517b7efd2a33774056cb5671675a8b492e9f5f2620eb8ef9381d3d1df19938b7b5ffaac59bc8110fa87ba8d7a3d0165f8e41dd0f804f11b9ded0f352a597835d06307a8e0c6ef4d21904339e1cf458923a3e89e025d945347366c02f3dd6368d4e47e85d3d2a9705bd57961852e5a579f93b1c514c539f49ea1163a2a493b0efcb47f4748f6a99e10bf7078282e4ace18136e2a8b3ee0a380dcd3b3ef3e65e1b8157289d62467ad488ba0392b2e90a1ededcbdc931dc17298ccef76645c7d330a05c2ce40f89b85468f357a217751e154631304ec4e04bb45b3678909c74af51ce370364d8f4f7eb1e61e00287429c9961de8322ca9a2629b1309d800e92bc1dc5055dcc797f33866eb0cfd8d490250d48ffca8022f49290e2d5376162fbaa982d16453c825b35f6515635ea92bea72367baa54de3f9eaea69542a81a4127f71cbaa257f324fefef14f08fbd65a049cd2fb362594a8e23ff1a2617db5b158f6f01cf50ab0ed95c6e709841164108b06e1b40ab0ab11c408301d3d9d8ea69e968a9600b3d17f38011ce28074e2c2e10bf6197c602d8d0ce7d3a3ef2d89623bc9f12ea338791e9266bb8ce02b124c6c7929baea693244098454a080eb7523e13bb1b7c5b6775fabababbe9075fe5687aa451397bb9cfccd051243e9bf5aef24062d335de5fce24e9ddbde1191052d80c36df9f8434872f277ed4f5a1ce8ebd3b960824a4e4f1001b04cb685f9bee4d0ddb0c571598ac2021a6606fd23345c6fbb84f0ce05fe52734521b7b07c6388d3a3b99318bf0131504aa9dfbaf548f9d32a9cd4c6893524b11330a2d3aad3ed2a58966ebb0134465d543fd7797af549f568eaebe957f64fec854674902b97558756986946ea3ab7a251cbbea11a687bd43f5d0bd89cd2caba61d5218374990ee8b92219ed25dca011c68a9757c013bd837b2dd734e3751f64fcb4b23dcd6bc57ea567f5716e17367244751e2303b22a953e772756956cdcc013ffd2c32490754422a572529d4c92f1ebb19f1dad4d036f2fdf31ca9101bdf81aea948aedcf217aa8fccd7a0771aa2753e1a823bf41c95377a2ffa61b2265138153ce86d2c87dd07a4b32d27f5f2872641431ce9a18a502aaefd9afc5b0d13cd46c357e38e69e1ee945add1992932a5b1e5c5629c9f48f7661853da00787c9d78fb925553bf07a50dd5b9d935853420e4d1a71ae62ff90ca193cdd6c2f4bed263415aaf9a35094bc2a22e2a663c7645001cd190b7bc17c75feadf8e87ce5c24b763b6584ed32e71b0268142ea3ed6898157bf923bebf0192d1bf5ee30a7d351634a60b504dde38a2e114f7ae9bf176d4a18ba2895a7bb4b47444a9ba8dbb4c124cd41bbb32f4bcb1de48c4abb510607a001b5a000bba43618b6c19e43517b45b42405928b67c713881858bad3a42511c2716ff9cd332034b672b52ff16610805cdbe7544a8a84b66e1c745a73c1b6bcda5b77b951f36c0f7a5372de9e5d1f9bbcde8843c6909002dda4875e67571af0bec581856c32c09c240e664e761e57cd0d8dc8a71cb918a5762d111285cd8b5613ddbd0ca08ac0342b2bdee38f96fa754bb2b087179c113c93986a810356eb94540b93cb9dec4aa9290ff12ec1aa2e656c9be3d590753c366c601406c061bc22033a1fd1f4e1111d039b8813b983cb506c3ea7ff3057983e8bf01682fbb00f43005313c82c1392918a6165a13338ffe11a992c1fb3d1032aa679a418c8ba4f8a0bc199e10cf6bd77a14fdd6a06093514348e3a8974434ae8a3676369c6be2cf90e672b343fce04ac6b22e0cf47568bc45d70a68e68c649a4830ae218590c1a437e7a23a54efe44f67086eb697b9fa57835f0b8f70f0a929226efb336c0e21833a028218cd63732c80aa477e62d141dba81854f70da68daff4a84cb6de779254e8a97e73565374af4092af05cbd6654afc3fd72f0ae232695cb6668eafecc4069bd90bb528b83efa2fbcdbd93b289929621ed74d808738fc103eeb105510851fc9319f171ea0ced0b97b5b9fb5ef985186bc52098f9eb476f67b7cc7665d47587975cb45a50fc64100719bf76345f0fdf1e09efe9fb800dc114e46be0879a195cc06870e23d2631dae71c3994481c8761c40d07c5bfca95e718b7b22585af03ed34175a46d57af3518e32a7fc1aa4482732a81a87f724f8d2e780b3a39d451a380f75c2d680cc7213eab1d4a59d394ae3810a1c90818d52f93fb203e2d8b1b5fa8f60b2d585d9135d648846f138b86953242d2bb1f2ecdf389b4de7651817b8e4e64b333f1aac523a93f2748a9c38ffbc29ced457b6f9781b08a67a1975d031ccd71545c0037434056c2434d13e6c4beebf46fc12222c0b2eccd6159d5aea8e554d7a09652b06bf7ca699a7199e716d05dd553041a8f2b303d236a9babaafb9fa528f28a2ca2aa780b940383c099aa65a0074b83fd1f0bc5b7b5e46c25e54838b3cbcfc95f87f1d471b3ba894434fa58952fdcb77f161372693306dba4e8f216d1c8e5caff0fe8360a51c60763644169fdc6a8267f2e3f909a61b2a678bce6ae90403a836b1a7b7e8cd8b54c37087a9e14446d95e6908d2eedbfcc653e02fdf771f701a79b9e5a26ed0a947842070f3b5701742211219e761762c37f0d0a1d1b9750fee577e1208115c66ac07ec091e6a3fc4aa6a253bcba868edd3154dcaf5162f615e85490a6ca342f34c43ac61a3ea6bfeefd850e190eb1d8da4d28b5eceeb1678c02433ecd5d48b2536404257e8ca7bef5855f2b813ed2f4c409445a3317c9be1a35ae2fb4d2b87921b904bf2c14db514cee045251cfc276374db15c99dea15acde197c6eb524988e39b63287beb8676865aaa3bad1b43b8cab15cbf27a498759e3203abf369e97242f0b0154149f14ac233cdb73a22b7fb8f09325bf2ace83bb6b5db8a121a2b682149a69131ccce52229840b113fc7b0bcc58405bfe87f1f95ffc2e96fc5596567e94364dfaa6d9d5a6eb99ae4ddf424").unwrap()); - } #[test] fn keygen_error_cases() { /* - Testing this condition: - if !(seed.key_type() == KeyType::Seed || seed.key_type() == KeyType::BytesFullEntropy) - || seed.key_len() != 32 - */ + Testing this condition: + if !(seed.key_type() == KeyType::Seed || seed.key_type() == KeyType::BytesFullEntropy) + || seed.key_len() != 32 + */ // success case KeyType: seed let mut seed = KeyMaterial256::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), + &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); /* MLDSA44 */ let expected_pk_bytes: [u8; MLDSA44_PK_LEN] = hex::decode("d7b2b47254aae0db45e7930d4a98d2c97d8f1397d1789dafa17024b316e9bec94fc9946d42f19b79a7413bbaa33e7149cb42ed5115693ac041facb988adeb5fe0e1d8631184995b592c397d2294e2e14f90aa414ba3826899ac43f4cccacbc26e9a832b95118d5cb433cbef9660b00138e0817f61e762ca274c36ad554eb22aac1162e4ab01acba1e38c4efd8f80b65b333d0f72e55dfe71ce9c1ebb9889e7c56106c0fd73803a2aecfeafded7aa3cb2ceda54d12bd8cd36a78cf975943b47abd25e880ac452e5742ed1e8d1a82afa86e590c758c15ae4d2840d92bca1a5090f40496597fca7d8b9513f1a1bda6e950aaa98de467507d4a4f5a4f0599216582c3572f62eda8905ab3581670c4a02777a33e0ca7295fd8f4ff6d1a0a3a7683d65f5f5f7fc60da023e826c5f92144c02f7d1ba1075987553ea9367fcd76d990b7fa99cd45afdb8836d43e459f5187df058479709a01ea6835935fa70460990cd3dc1ba401ba94bab1dde41ac67ab3319dcaca06048d4c4eef27ee13a9c17d0538f430f2d642dc2415660de78877d8d8abc72523978c042e4285f4319846c44126242976844c10e556ba215b5a719e59d0c6b2a96d39859071fdcc2cde7524a7bedae54e85b318e854e8fe2b2f3edfac9719128270aafd1e5044c3a4fdafd9ff31f90784b8e8e4596144a0daf586511d3d9962b9ea95af197b4e5fc60f2b1ed15de3a5bef5f89bdc79d91051d9b2816e74fa54531efdc1cbe74d448857f476bcd58f21c0b653b3b76a4e076a6559a302718555cc63f74859aabab925f023861ca8cd0f7badb2871f67d55326d7451135ad45f4a1ba69118fbb2c8a30eec9392ef3f977066c9add5c710cc647b1514d217d958c7017c3e90fd20c04e674b90486e9370a31a001d32f473979e4906749e7e477fa0b74508f8a5f2378312b83c25bd388ca0b0fff7478baf42b71667edaac97c46b129643e586e5b055a0c211946d4f36e675bed5860fa042a315d9826164d6a9237c35a5fbf495490a5bd4df248b95c4aae7784b605673166ac4245b5b4b082a09e9323e62f2078c5b76783446defd736ad3a3702d49b089844900a61833397bc4419b30d7a97a0b387c1911474c4d41b53e32a977acb6f0ea75db65bb39e59e701e76957def6f2d44559c31a77122b5204e3b5c219f1688b14ed0bc0b801b3e6e82dcd43e9c0e9f41744cd9815bd1bc8820d8bb123f04facd1b1b685dd5a2b1b8dbbf3ed933670f095a180b4f192d08b10b8fabbdfcc2b24518e32eea0a5e0c904ca844780083f3b0cd2d0b8b6af67bc355b9494025dc7b0a78fa80e3a2dbfeb51328851d6078198e9493651ae787ec0251f922ba30e9f51df62a6d72784cf3dd205393176dfa324a512bd94970a36dd34a514a86791f0eb36f0145b09ab64651b4a0313b299611a2a1c48891627598768a3114060ba4443486df51522a1ce88b30985c216f8e6ed178dd567b304a0d4cafba882a28342f17a9aa26ae58db630083d2c358fdf566c3f5d62a428567bc9ea8ce95caa0f35474b0bfa8f339a250ab4dfcf2083be8eefbc1055e18fe15370eecb260566d83ff06b211aaec43ca29b54ccd00f8815a2465ef0b46515cc7e41f3124f09efff739309ab58b29a1459a00bce5038e938c9678f72eb0e4ee5fdaae66d9f8573fc97fc42b4959f4bf8b61d78433e86b0335d6e9191c4d8bf487b3905c108cfd6ac24b0ceb7dcb7cf51f84d0ed687b95eaeb1c533c06f0d97023d92a70825837b59ba6cb7d4e56b0a87c203862ae8f315ba5925e8edefa679369a2202766151f16a965f9f81ece76cc070b55869e4db9784cf05c830b3242c8312").unwrap() .try_into().unwrap(); @@ -182,15 +191,16 @@ mod mldsa_tests { seed.set_key_type(KeyType::BytesFullEntropy).unwrap(); _ = MLDSA44::keygen_from_seed(&seed).unwrap(); - // Failure case: key type != Seed || BytesFullEntropy let mac_seed = KeyMaterial256::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), + &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap(), KeyType::MACKey, - ).unwrap(); + ) + .unwrap(); match MLDSA44::keygen_from_seed(&mac_seed) { - Err(SignatureError::KeyGenError(_)) => { /* good */ }, + Err(SignatureError::KeyGenError(_)) => { /* good */ } _ => panic!("expected KeyGenError"), } @@ -198,11 +208,12 @@ mod mldsa_tests { let seed = KeyMaterial256::from_bytes_as_type( &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718").unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); assert_eq!(seed.key_len(), 25); match MLDSA44::keygen_from_seed(&seed) { - Err(SignatureError::KeyGenError(_)) => { /* good */ }, + Err(SignatureError::KeyGenError(_)) => { /* good */ } _ => panic!("expected KeyGenError"), } } @@ -216,22 +227,36 @@ mod mldsa_tests { let sk = MLDSA44PrivateKey::from_bytes(&hex::decode(MLDSA44_KAT1.sk).unwrap()).unwrap(); let rnd = if !MLDSA44_KAT1.deterministic { - let mut rnd = [0u8; 32]; - bouncycastle_rng::DefaultRNG::default().next_bytes_out(&mut rnd).unwrap(); - rnd - } else { [0u8; 32] }; + let mut rnd = [0u8; 32]; + bouncycastle_rng::DefaultRNG::default().next_bytes_out(&mut rnd).unwrap(); + rnd + } else { + [0u8; 32] + }; - let mu = MLDSA44::compute_mu_from_sk(&sk,&hex::decode(MLDSA44_KAT1.message).unwrap(), Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap())).unwrap(); + let mu = MLDSA44::compute_mu_from_sk( + &sk, + &hex::decode(MLDSA44_KAT1.message).unwrap(), + Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap()), + ) + .unwrap(); let sig = MLDSA44::sign_mu_deterministic(&sk, &mu, rnd).unwrap(); assert_eq!(&sig, &*hex::decode(MLDSA44_KAT1.signature).unwrap()); - MLDSA44::verify(&sk.derive_pk(), &hex::decode(MLDSA44_KAT1.message).unwrap(), Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap()), &sig).unwrap(); + MLDSA44::verify( + &sk.derive_pk(), + &hex::decode(MLDSA44_KAT1.message).unwrap(), + Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap()), + &sig, + ) + .unwrap(); // test the streaming API on the same value let mut s = MLDSA44::sign_init(&sk, Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap())).unwrap(); s.set_signer_rnd(rnd); s.sign_update(&hex::decode(MLDSA44_KAT1.message).unwrap()); let sig = s.sign_final().unwrap(); - let decoded_sig: &[u8; MLDSA44_SIG_LEN] = &hex::decode(MLDSA44_KAT1.signature).unwrap().try_into().unwrap(); + let decoded_sig: &[u8; MLDSA44_SIG_LEN] = + &hex::decode(MLDSA44_KAT1.signature).unwrap().try_into().unwrap(); assert_eq!(&sig, decoded_sig); // Then with the message broken into chunks @@ -241,9 +266,8 @@ mod mldsa_tests { s.sign_update(msg_chunk); } let sig_val = s.sign_final().unwrap(); - MLDSA44::verify(&sk.derive_pk(), DUMMY_SEED_1024, Some(b"streaming API chunked"), &sig_val).unwrap(); - - + MLDSA44::verify(&sk.derive_pk(), DUMMY_SEED_1024, Some(b"streaming API chunked"), &sig_val) + .unwrap(); // ML-DSA-65 @@ -252,25 +276,36 @@ mod mldsa_tests { let mut rnd = [0u8; 32]; bouncycastle_rng::DefaultRNG::default().next_bytes_out(&mut rnd).unwrap(); rnd - } else { [0u8; 32] }; + } else { + [0u8; 32] + }; - let mu = MLDSA65::compute_mu_from_sk(&sk, &hex::decode(MLDSA65_KAT1.message).unwrap(), Some(&hex::decode(MLDSA65_KAT1.ctx).unwrap())).unwrap(); + let mu = MLDSA65::compute_mu_from_sk( + &sk, + &hex::decode(MLDSA65_KAT1.message).unwrap(), + Some(&hex::decode(MLDSA65_KAT1.ctx).unwrap()), + ) + .unwrap(); let sig = MLDSA65::sign_mu_deterministic(&sk, &mu, rnd).unwrap(); assert_eq!(&sig, &*hex::decode(MLDSA65_KAT1.signature).unwrap()); MLDSA65::verify( - &sk.derive_pk(), &*hex::decode(MLDSA65_KAT1.message).unwrap(), Some(&hex::decode(MLDSA65_KAT1.ctx).unwrap()), &sig).unwrap(); + &sk.derive_pk(), + &*hex::decode(MLDSA65_KAT1.message).unwrap(), + Some(&hex::decode(MLDSA65_KAT1.ctx).unwrap()), + &sig, + ) + .unwrap(); // test the streaming API on the same value let mut s = MLDSA65::sign_init(&sk, Some(&hex::decode(MLDSA65_KAT1.ctx).unwrap())).unwrap(); s.set_signer_rnd(rnd); s.sign_update(&hex::decode(MLDSA65_KAT1.message).unwrap()); let sig = s.sign_final().unwrap(); - let decoded_sig: &[u8; MLDSA65_SIG_LEN] = &hex::decode(MLDSA65_KAT1.signature).unwrap().try_into().unwrap(); + let decoded_sig: &[u8; MLDSA65_SIG_LEN] = + &hex::decode(MLDSA65_KAT1.signature).unwrap().try_into().unwrap(); assert_eq!(&sig, decoded_sig); - - // ML-DSA-87 let sk = MLDSA87PrivateKey::from_bytes(&hex::decode(MLDSA87_KAT1.sk).unwrap()).unwrap(); @@ -278,20 +313,34 @@ mod mldsa_tests { let mut rnd = [0u8; 32]; bouncycastle_rng::DefaultRNG::default().next_bytes_out(&mut rnd).unwrap(); rnd - } else { [0u8; 32] }; + } else { + [0u8; 32] + }; - let mu = MLDSA87::compute_mu_from_sk(&sk, &hex::decode(MLDSA87_KAT1.message).unwrap(), Some(&hex::decode(MLDSA87_KAT1.ctx).unwrap())).unwrap(); + let mu = MLDSA87::compute_mu_from_sk( + &sk, + &hex::decode(MLDSA87_KAT1.message).unwrap(), + Some(&hex::decode(MLDSA87_KAT1.ctx).unwrap()), + ) + .unwrap(); let sig = MLDSA87::sign_mu_deterministic(&sk, &mu, rnd).unwrap(); assert_eq!(&sig, &*hex::decode(MLDSA87_KAT1.signature).unwrap()); - MLDSA87::verify(&sk.derive_pk(), &*hex::decode(MLDSA87_KAT1.message).unwrap(), Some(&hex::decode(MLDSA87_KAT1.ctx).unwrap()), &sig).unwrap(); + MLDSA87::verify( + &sk.derive_pk(), + &*hex::decode(MLDSA87_KAT1.message).unwrap(), + Some(&hex::decode(MLDSA87_KAT1.ctx).unwrap()), + &sig, + ) + .unwrap(); // test the streaming API on the same value let mut s = MLDSA87::sign_init(&sk, Some(&hex::decode(MLDSA87_KAT1.ctx).unwrap())).unwrap(); s.set_signer_rnd(rnd); s.sign_update(&hex::decode(MLDSA87_KAT1.message).unwrap()); let sig = s.sign_final().unwrap(); - let decoded_sig: &[u8; MLDSA87_SIG_LEN] = &hex::decode(MLDSA87_KAT1.signature).unwrap().try_into().unwrap(); + let decoded_sig: &[u8; MLDSA87_SIG_LEN] = + &hex::decode(MLDSA87_KAT1.signature).unwrap().try_into().unwrap(); assert_eq!(&sig, decoded_sig); } @@ -302,15 +351,19 @@ mod mldsa_tests { // ML-DSA-44 let seed = KeyMaterial256::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), + &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let rnd = if !MLDSA44_KAT1.deterministic { let mut rnd = [0u8; 32]; bouncycastle_rng::DefaultRNG::default().next_bytes_out(&mut rnd).unwrap(); rnd - } else { [0u8; 32] }; + } else { + [0u8; 32] + }; let tr: [u8; MLDSA_TR_LEN]; { @@ -320,38 +373,55 @@ mod mldsa_tests { // BEGIN expected values let (_, expected_sk) = MLDSA44::keygen_from_seed(&seed).unwrap(); - let expected_mu = MLDSA44::compute_mu_from_sk(&expected_sk, - &hex::decode(MLDSA44_KAT1.message).unwrap(), - Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap())).unwrap(); + let expected_mu = MLDSA44::compute_mu_from_sk( + &expected_sk, + &hex::decode(MLDSA44_KAT1.message).unwrap(), + Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap()), + ) + .unwrap(); let mut expected_sig = [0u8; MLDSA44_SIG_LEN]; - let bytes_written = MLDSA44::sign_mu_deterministic_out(&expected_sk, &expected_mu, rnd, &mut expected_sig).unwrap(); + let bytes_written = + MLDSA44::sign_mu_deterministic_out(&expected_sk, &expected_mu, rnd, &mut expected_sig) + .unwrap(); assert_eq!(bytes_written, MLDSA44_SIG_LEN); // END expected values - let mu = MLDSA44::compute_mu_from_tr(&tr, &hex::decode(MLDSA44_KAT1.message).unwrap(), Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap())).unwrap(); + let mu = MLDSA44::compute_mu_from_tr( + &tr, + &hex::decode(MLDSA44_KAT1.message).unwrap(), + Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap()), + ) + .unwrap(); assert_eq!(&expected_mu, &mu); let mut sig = [0u8; MLDSA44_SIG_LEN]; - let bytes_written = MLDSA44::sign_mu_deterministic_from_seed_out(&seed, &mu, rnd, &mut sig).unwrap(); + let bytes_written = + MLDSA44::sign_mu_deterministic_from_seed_out(&seed, &mu, rnd, &mut sig).unwrap(); assert_eq!(bytes_written, MLDSA44_SIG_LEN); assert_eq!(&sig, &expected_sig); let (pk, _) = MLDSA44::keygen_from_seed(&seed).unwrap(); - MLDSA44::verify(&pk, &hex::decode(MLDSA44_KAT1.message).unwrap(), Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap()), &sig).unwrap(); - + MLDSA44::verify( + &pk, + &hex::decode(MLDSA44_KAT1.message).unwrap(), + Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap()), + &sig, + ) + .unwrap(); // test the streaming API on the same value - let mut s = MLDSA44::sign_init_from_seed(&seed, Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap())).unwrap(); + let mut s = + MLDSA44::sign_init_from_seed(&seed, Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap())) + .unwrap(); s.set_signer_rnd(rnd); s.sign_update(&hex::decode(MLDSA44_KAT1.message).unwrap()); let sig = s.sign_final().unwrap(); assert_eq!(&sig, &expected_sig); - - // while we're at it, test the streaming verifier cause I'm not sure where else this is being tested. - let mut v = MLDSA44::verify_init(&pk, Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap())).unwrap(); + let mut v = + MLDSA44::verify_init(&pk, Some(&hex::decode(MLDSA44_KAT1.ctx).unwrap())).unwrap(); v.verify_update(&hex::decode(MLDSA44_KAT1.message).unwrap()); v.verify_final(&expected_sig).unwrap(); } @@ -365,25 +435,24 @@ mod mldsa_tests { let (_pk, sk) = MLDSA44::keygen().unwrap(); let too_long_ctx = [1u8; 256]; match MLDSA44::sign_init(&sk, Some(&too_long_ctx)) { - Err(SignatureError::LengthError(_)) => { /* good */ }, + Err(SignatureError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for ctx too long"), } // test various things that are shorter / longer than required - // sig too long / too short // MLDSA44 let (pk, sk) = MLDSA44::keygen().unwrap(); let sig = MLDSA44::sign(&sk, msg, None).unwrap(); // too short - match MLDSA44::verify(&pk, msg, None, &sig[..MLDSA44_SIG_LEN-1]) { - Err(SignatureError::LengthError(_)) => { /* good */ }, + match MLDSA44::verify(&pk, msg, None, &sig[..MLDSA44_SIG_LEN - 1]) { + Err(SignatureError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } // too long - let mut sig_too_long= vec![1u8; MLDSA44_SIG_LEN + 2]; + let mut sig_too_long = vec![1u8; MLDSA44_SIG_LEN + 2]; sig_too_long[..MLDSA44_SIG_LEN].copy_from_slice(&sig); MLDSA44::verify(&pk, msg, None, &sig_too_long).unwrap(); @@ -391,12 +460,12 @@ mod mldsa_tests { let (pk, sk) = MLDSA65::keygen().unwrap(); let sig = MLDSA65::sign(&sk, msg, None).unwrap(); // too short - match MLDSA65::verify(&pk, msg, None, &sig[..MLDSA65_SIG_LEN-1]) { - Err(SignatureError::LengthError(_)) => { /* good */ }, + match MLDSA65::verify(&pk, msg, None, &sig[..MLDSA65_SIG_LEN - 1]) { + Err(SignatureError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } // too long - let mut sig_too_long= vec![1u8; MLDSA65_SIG_LEN + 2]; + let mut sig_too_long = vec![1u8; MLDSA65_SIG_LEN + 2]; sig_too_long[..MLDSA65_SIG_LEN].copy_from_slice(&sig); MLDSA65::verify(&pk, msg, None, &sig_too_long).unwrap(); @@ -404,12 +473,12 @@ mod mldsa_tests { let (pk, sk) = MLDSA87::keygen().unwrap(); let sig = MLDSA87::sign(&sk, msg, None).unwrap(); // too short - match MLDSA87::verify(&pk, msg, None, &sig[..MLDSA44_SIG_LEN-1]) { - Err(SignatureError::LengthError(_)) => { /* good */ }, + match MLDSA87::verify(&pk, msg, None, &sig[..MLDSA44_SIG_LEN - 1]) { + Err(SignatureError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } // too long - let mut sig_too_long= vec![1u8; MLDSA87_SIG_LEN + 2]; + let mut sig_too_long = vec![1u8; MLDSA87_SIG_LEN + 2]; sig_too_long[..MLDSA87_SIG_LEN].copy_from_slice(&sig); MLDSA87::verify(&pk, msg, None, &sig_too_long).unwrap(); } @@ -425,9 +494,11 @@ mod mldsa_tests { let msg = b"The quick brown fox jumped over the lazy dog"; let seed = KeyMaterial256::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(), + &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (pk, _sk) = MLDSA44::keygen_from_seed(&seed).unwrap(); @@ -460,8 +531,6 @@ mod mldsa_tests { assert_eq!(format!("{:?}", p), "Polynomial (data masked)"); } - - #[test] fn keypair_consistency_check() { // this is common to all parameter sets, so I'll just test MLDSA44 @@ -473,11 +542,11 @@ mod mldsa_tests { // failure case: different but valid key let (pk2, sk2) = MLDSA44::keygen().unwrap(); match MLDSA44::keypair_consistency_check(&pk, &sk2) { - Err(SignatureError::ConsistencyCheckFailed()) => { /* good */ }, + Err(SignatureError::ConsistencyCheckFailed()) => { /* good */ } _ => panic!("Expected error for different key"), }; match MLDSA44::keypair_consistency_check(&pk2, &sk) { - Err(SignatureError::ConsistencyCheckFailed()) => { /* good */ }, + Err(SignatureError::ConsistencyCheckFailed()) => { /* good */ } _ => panic!("Expected error for different key"), }; @@ -486,7 +555,7 @@ mod mldsa_tests { pk_bytes[17] ^= 0x01; let pk2 = MLDSA44PublicKey::from_bytes(&pk_bytes).unwrap(); match MLDSA44::keypair_consistency_check(&pk2, &sk) { - Err(SignatureError::ConsistencyCheckFailed()) => { /* good */ }, + Err(SignatureError::ConsistencyCheckFailed()) => { /* good */ } _ => panic!("Expected error for different key"), }; @@ -494,7 +563,7 @@ mod mldsa_tests { sk_bytes[17] ^= 0x01; let sk2 = MLDSA44PrivateKey::from_bytes(&sk_bytes).unwrap(); match MLDSA44::keypair_consistency_check(&pk, &sk2) { - Err(SignatureError::ConsistencyCheckFailed()) => { /* good */ }, + Err(SignatureError::ConsistencyCheckFailed()) => { /* good */ } _ => panic!("Expected error for different key"), }; } @@ -534,7 +603,6 @@ mod mldsa_tests { let mu = MuBuilder::compute_mu(&pk.compute_tr(), msg, None).unwrap(); - let sig = MLDSA44::sign_mu(&sk, &mu).unwrap(); MLDSA44::verify(&pk, msg, None, &sig).unwrap(); diff --git a/crypto/mlkem/benches/mlkem_benches.rs b/crypto/mlkem/benches/mlkem_benches.rs index d6a78da..5330f73 100644 --- a/crypto/mlkem/benches/mlkem_benches.rs +++ b/crypto/mlkem/benches/mlkem_benches.rs @@ -1,9 +1,13 @@ -use criterion::{Criterion, criterion_group, criterion_main}; use bouncycastle_core::key_material::{KeyMaterial512, KeyType}; -use std::hint::black_box; use bouncycastle_core::traits::KEM; use bouncycastle_hex as hex; -use bouncycastle_mlkem::{MLKEM1024PrivateKeyExpanded, MLKEM512PrivateKeyExpanded, MLKEM768PrivateKeyExpanded, MLKEMPublicKeyTrait, MLKEMTrait, MLKEM1024, MLKEM1024_CT_LEN, MLKEM512, MLKEM512_CT_LEN, MLKEM768, MLKEM768_CT_LEN, MLKEM_RND_LEN}; +use bouncycastle_mlkem::{ + MLKEM_RND_LEN, MLKEM512, MLKEM512_CT_LEN, MLKEM512PrivateKeyExpanded, MLKEM768, + MLKEM768_CT_LEN, MLKEM768PrivateKeyExpanded, MLKEM1024, MLKEM1024_CT_LEN, + MLKEM1024PrivateKeyExpanded, MLKEMPublicKeyTrait, MLKEMTrait, +}; +use criterion::{Criterion, criterion_group, criterion_main}; +use std::hint::black_box; fn bench_mlkem_keygen(c: &mut Criterion) { let mut group = c.benchmark_group("KeyGen"); @@ -18,11 +22,11 @@ fn bench_mlkem_keygen(c: &mut Criterion) { group.throughput(criterion::Throughput::Elements(seeds.len() as u64)); group.bench_function("ML-KEM-512", |b| { - b.iter(|| { - for seed in seeds.iter() { - black_box(MLKEM512::keygen_from_seed(seed)).unwrap(); - } - }) + b.iter(|| { + for seed in seeds.iter() { + black_box(MLKEM512::keygen_from_seed(seed)).unwrap(); + } + }) }); group.bench_function("ML-KEM-768", |b| { @@ -44,7 +48,6 @@ fn bench_mlkem_keygen(c: &mut Criterion) { group.finish(); } - fn bench_mlkem_keygen_and_expand(c: &mut Criterion) { let mut group = c.benchmark_group("KeyGen_and_expand"); @@ -69,7 +72,7 @@ fn bench_mlkem_keygen_and_expand(c: &mut Criterion) { group.bench_function("ML-KEM-768", |b| { b.iter(|| { for seed in seeds.iter() { - let(_pk, sk) = MLKEM768::keygen_from_seed(seed).unwrap(); + let (_pk, sk) = MLKEM768::keygen_from_seed(seed).unwrap(); black_box(MLKEM768PrivateKeyExpanded::from(&sk)); } }) @@ -78,7 +81,7 @@ fn bench_mlkem_keygen_and_expand(c: &mut Criterion) { group.bench_function("ML-KEM-1024", |b| { b.iter(|| { for seed in seeds.iter() { - let(_pk, sk) = MLKEM1024::keygen_from_seed(seed).unwrap(); + let (_pk, sk) = MLKEM1024::keygen_from_seed(seed).unwrap(); black_box(MLKEM1024PrivateKeyExpanded::from(&sk)); } }) @@ -93,12 +96,16 @@ fn bench_mlkem_encaps(c: &mut Criterion) { // set up the seeds outside of the timing loop // Doing different seeds so that the CPU doesn't cache them or do too much branch prediction let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); // create a vector of signing nonces so that we're not measuring the time of the RNG const NUM_ELEMS: usize = 256; @@ -120,7 +127,6 @@ fn bench_mlkem_encaps(c: &mut Criterion) { }) }); - /*** ML-KEM-768 ***/ let (pk, _sk) = MLKEM768::keygen_from_seed(&seed).unwrap(); @@ -150,19 +156,22 @@ fn bench_mlkem_encaps(c: &mut Criterion) { group.finish(); } - fn bench_mlkem_encaps_for_expanded(c: &mut Criterion) { let mut group = c.benchmark_group("Encaps_for_expanded_key"); // set up the seeds outside of the timing loop // Doing different seeds so that the CPU doesn't cache them or do too much branch prediction let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); // create a vector of signing nonces so that we're not measuring the time of the RNG const NUM_ELEMS: usize = 256; @@ -185,7 +194,6 @@ fn bench_mlkem_encaps_for_expanded(c: &mut Criterion) { }) }); - /*** ML-KEM-768 ***/ let (pk, _sk) = MLKEM768::keygen_from_seed(&seed).unwrap(); let a_hat = pk.A_hat(); @@ -223,12 +231,16 @@ fn bench_mlkem_decaps(c: &mut Criterion) { // set up the seeds outside of the timing loop // Doing different seeds so that the CPU doesn't cache them or do too much branch prediction let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); const NUM_ELEMS: usize = 256; @@ -236,7 +248,7 @@ fn bench_mlkem_decaps(c: &mut Criterion) { let (pk, sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); // create a bunch of ciphertexts to decaps - let mut cts = [ [0u8; MLKEM512_CT_LEN]; NUM_ELEMS]; + let mut cts = [[0u8; MLKEM512_CT_LEN]; NUM_ELEMS]; for i in 0..NUM_ELEMS { // create each ct with a unique nonce // encaps_internal() returns (ss, ct) ... we only want ct, hence the ".1" @@ -248,7 +260,7 @@ fn bench_mlkem_decaps(c: &mut Criterion) { group.bench_function("ML-KEM-512", |b| { b.iter(|| { for i in 0..NUM_ELEMS { - _ = black_box( MLKEM512::decaps(&sk, &cts[i]) ); + _ = black_box(MLKEM512::decaps(&sk, &cts[i])); } }) }); @@ -257,7 +269,7 @@ fn bench_mlkem_decaps(c: &mut Criterion) { let (pk, sk) = MLKEM768::keygen_from_seed(&seed).unwrap(); // create a bunch of ciphertexts to decaps - let mut cts = [ [0u8; MLKEM768_CT_LEN]; NUM_ELEMS]; + let mut cts = [[0u8; MLKEM768_CT_LEN]; NUM_ELEMS]; for i in 0..NUM_ELEMS { // create each ct with a unique nonce // encaps_internal() returns (ss, ct) ... we only want ct, hence the ".1" @@ -269,7 +281,7 @@ fn bench_mlkem_decaps(c: &mut Criterion) { group.bench_function("ML-KEM-768", |b| { b.iter(|| { for i in 0..NUM_ELEMS { - _ = black_box( MLKEM768::decaps(&sk, &cts[i]) ); + _ = black_box(MLKEM768::decaps(&sk, &cts[i])); } }) }); @@ -278,7 +290,7 @@ fn bench_mlkem_decaps(c: &mut Criterion) { let (pk, sk) = MLKEM1024::keygen_from_seed(&seed).unwrap(); // create a bunch of ciphertexts to decaps - let mut cts = [ [0u8; MLKEM1024_CT_LEN]; NUM_ELEMS]; + let mut cts = [[0u8; MLKEM1024_CT_LEN]; NUM_ELEMS]; for i in 0..NUM_ELEMS { // create each ct with a unique nonce // encaps_internal() returns (ss, ct) ... we only want ct, hence the ".1" @@ -290,7 +302,7 @@ fn bench_mlkem_decaps(c: &mut Criterion) { group.bench_function("ML-KEM-1024", |b| { b.iter(|| { for i in 0..NUM_ELEMS { - _ = black_box( MLKEM1024::decaps(&sk, &cts[i]) ); + _ = black_box(MLKEM1024::decaps(&sk, &cts[i])); } }) }); @@ -298,19 +310,22 @@ fn bench_mlkem_decaps(c: &mut Criterion) { group.finish(); } - fn bench_mlkem_decaps_with_expanded_key(c: &mut Criterion) { let mut group = c.benchmark_group("Decaps_with_expanded_key"); // set up the seeds outside of the timing loop // Doing different seeds so that the CPU doesn't cache them or do too much branch prediction let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); const NUM_ELEMS: usize = 256; @@ -319,7 +334,7 @@ fn bench_mlkem_decaps_with_expanded_key(c: &mut Criterion) { let sk_expanded = MLKEM512PrivateKeyExpanded::from(&sk); // create a bunch of ciphertexts to decaps - let mut cts = [ [0u8; MLKEM512_CT_LEN]; NUM_ELEMS]; + let mut cts = [[0u8; MLKEM512_CT_LEN]; NUM_ELEMS]; for i in 0..NUM_ELEMS { // create each ct with a unique nonce // encaps_internal() returns (ss, ct) ... we only want ct, hence the ".1" @@ -331,7 +346,7 @@ fn bench_mlkem_decaps_with_expanded_key(c: &mut Criterion) { group.bench_function("ML-KEM-512", |b| { b.iter(|| { for i in 0..NUM_ELEMS { - _ = black_box( MLKEM512::decaps_with_expanded_key(&sk_expanded, &cts[i]) ); + _ = black_box(MLKEM512::decaps_with_expanded_key(&sk_expanded, &cts[i])); } }) }); @@ -341,7 +356,7 @@ fn bench_mlkem_decaps_with_expanded_key(c: &mut Criterion) { let sk_expanded = MLKEM768PrivateKeyExpanded::from(&sk); // create a bunch of ciphertexts to decaps - let mut cts = [ [0u8; MLKEM768_CT_LEN]; NUM_ELEMS]; + let mut cts = [[0u8; MLKEM768_CT_LEN]; NUM_ELEMS]; for i in 0..NUM_ELEMS { // create each ct with a unique nonce // encaps_internal() returns (ss, ct) ... we only want ct, hence the ".1" @@ -353,7 +368,7 @@ fn bench_mlkem_decaps_with_expanded_key(c: &mut Criterion) { group.bench_function("ML-KEM-768", |b| { b.iter(|| { for i in 0..NUM_ELEMS { - _ = black_box( MLKEM768::decaps_with_expanded_key(&sk_expanded, &cts[i]) ); + _ = black_box(MLKEM768::decaps_with_expanded_key(&sk_expanded, &cts[i])); } }) }); @@ -363,7 +378,7 @@ fn bench_mlkem_decaps_with_expanded_key(c: &mut Criterion) { let sk_expanded = MLKEM1024PrivateKeyExpanded::from(&sk); // create a bunch of ciphertexts to decaps - let mut cts = [ [0u8; MLKEM1024_CT_LEN]; NUM_ELEMS]; + let mut cts = [[0u8; MLKEM1024_CT_LEN]; NUM_ELEMS]; for i in 0..NUM_ELEMS { // create each ct with a unique nonce // encaps_internal() returns (ss, ct) ... we only want ct, hence the ".1" @@ -375,7 +390,7 @@ fn bench_mlkem_decaps_with_expanded_key(c: &mut Criterion) { group.bench_function("ML-KEM-1024", |b| { b.iter(|| { for i in 0..NUM_ELEMS { - _ = black_box( MLKEM1024::decaps_with_expanded_key(&sk_expanded, &cts[i]) ); + _ = black_box(MLKEM1024::decaps_with_expanded_key(&sk_expanded, &cts[i])); } }) }); @@ -383,19 +398,22 @@ fn bench_mlkem_decaps_with_expanded_key(c: &mut Criterion) { group.finish(); } - fn bench_mlkem_decaps_from_seed(c: &mut Criterion) { let mut group = c.benchmark_group("decaps_from_seed"); // set up the seeds outside of the timing loop // Doing different seeds so that the CPU doesn't cache them or do too much branch prediction let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); const NUM_ELEMS: usize = 256; @@ -403,7 +421,7 @@ fn bench_mlkem_decaps_from_seed(c: &mut Criterion) { let (pk, _sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); // create a bunch of ciphertexts to decaps - let mut cts = [ [0u8; MLKEM512_CT_LEN]; NUM_ELEMS]; + let mut cts = [[0u8; MLKEM512_CT_LEN]; NUM_ELEMS]; for i in 0..NUM_ELEMS { // create each ct with a unique nonce // encaps_internal() returns (ss, ct) ... we only want ct, hence the ".1" @@ -415,7 +433,7 @@ fn bench_mlkem_decaps_from_seed(c: &mut Criterion) { group.bench_function("ML-KEM-512", |b| { b.iter(|| { for i in 0..NUM_ELEMS { - _ = black_box( MLKEM512::decaps_from_seed(&seed, &cts[i]) ); + _ = black_box(MLKEM512::decaps_from_seed(&seed, &cts[i])); } }) }); @@ -424,7 +442,7 @@ fn bench_mlkem_decaps_from_seed(c: &mut Criterion) { let (pk, _sk) = MLKEM768::keygen_from_seed(&seed).unwrap(); // create a bunch of ciphertexts to decaps - let mut cts = [ [0u8; MLKEM768_CT_LEN]; NUM_ELEMS]; + let mut cts = [[0u8; MLKEM768_CT_LEN]; NUM_ELEMS]; for i in 0..NUM_ELEMS { // create each ct with a unique nonce // encaps_internal() returns (ss, ct) ... we only want ct, hence the ".1" @@ -436,7 +454,7 @@ fn bench_mlkem_decaps_from_seed(c: &mut Criterion) { group.bench_function("ML-KEM-768", |b| { b.iter(|| { for i in 0..NUM_ELEMS { - _ = black_box( MLKEM768::decaps_from_seed(&seed, &cts[i]) ); + _ = black_box(MLKEM768::decaps_from_seed(&seed, &cts[i])); } }) }); @@ -445,11 +463,11 @@ fn bench_mlkem_decaps_from_seed(c: &mut Criterion) { let (pk, _sk) = MLKEM1024::keygen_from_seed(&seed).unwrap(); // create a bunch of ciphertexts to decaps - let mut cts = [ [0u8; MLKEM1024_CT_LEN]; NUM_ELEMS]; + let mut cts = [[0u8; MLKEM1024_CT_LEN]; NUM_ELEMS]; for i in 0..NUM_ELEMS { // create each ct with a unique nonce // encaps_internal() returns (ss, ct) ... we only want ct, hence the ".1" - cts[i].copy_from_slice(&MLKEM1024::encaps_internal(&pk, None,[i as u8; MLKEM_RND_LEN]).1); + cts[i].copy_from_slice(&MLKEM1024::encaps_internal(&pk, None, [i as u8; MLKEM_RND_LEN]).1); } group.throughput(criterion::Throughput::Elements(NUM_ELEMS as u64)); @@ -457,7 +475,7 @@ fn bench_mlkem_decaps_from_seed(c: &mut Criterion) { group.bench_function("ML-KEM-1024", |b| { b.iter(|| { for i in 0..NUM_ELEMS { - _ = black_box( MLKEM1024::decaps_from_seed(&seed, &cts[i]) ); + _ = black_box(MLKEM1024::decaps_from_seed(&seed, &cts[i])); } }) }); @@ -465,9 +483,16 @@ fn bench_mlkem_decaps_from_seed(c: &mut Criterion) { group.finish(); } -criterion_group!(benches, bench_mlkem_keygen, bench_mlkem_keygen_and_expand, - bench_mlkem_encaps, bench_mlkem_encaps_for_expanded, - bench_mlkem_decaps, bench_mlkem_decaps_with_expanded_key, bench_mlkem_decaps_from_seed); +criterion_group!( + benches, + bench_mlkem_keygen, + bench_mlkem_keygen_and_expand, + bench_mlkem_encaps, + bench_mlkem_encaps_for_expanded, + bench_mlkem_decaps, + bench_mlkem_decaps_with_expanded_key, + bench_mlkem_decaps_from_seed +); criterion_main!(benches); diff --git a/crypto/mlkem/src/aux_functions.rs b/crypto/mlkem/src/aux_functions.rs index 264654f..cf0478f 100644 --- a/crypto/mlkem/src/aux_functions.rs +++ b/crypto/mlkem/src/aux_functions.rs @@ -1,12 +1,11 @@ //! Implements auxiliary functions for ML-DSA as defined in Section 7 of FIPS 204. +use crate::Matrix; +use crate::matrix::Vector; use crate::mlkem::{N, q, q_inv}; -use crate::polynomial::{Polynomial}; +use crate::polynomial::Polynomial; use bouncycastle_core::traits::XOF; use bouncycastle_sha3::{SHAKE128, SHAKE256}; -use crate::Matrix; -use crate::matrix::Vector; - pub(crate) fn expandA(rho: &[u8; 32]) -> Matrix { let mut A_hat = Matrix::::new(); @@ -31,7 +30,7 @@ pub(crate) fn byte_encode(F: &Polynomial) let mut B = [0u8; PACK_LEN]; - for i in 0 .. N { + for i in 0..N { let mut alpha = F[i]; // For efficiency, the library is happy to work with values outside the range [0..q], @@ -45,8 +44,7 @@ pub(crate) fn byte_encode(F: &Polynomial) // 4: 𝑏[𝑖⋅𝑑 + 𝑗] ← 𝑎 mod 2 // constant-time note: yes, % is not constant-time, // but all of the values in (i*d + j) % 8 are loop indices and not part of the secret key. - B[(i*d + j)/8] |= tmp << ((i*d + j) % 8); - + B[(i * d + j) / 8] |= tmp << ((i * d + j) % 8); // 5: 𝑎 ← (𝑎 − 𝑏[𝑖⋅𝑑 + 𝑗])/2 // ▷ note 𝑎 − 𝑏[𝑖⋅𝑑 + 𝑗] is always even @@ -76,7 +74,7 @@ pub(crate) fn byte_decode(B: &[u8; PACK_L // 3: F[i] = SUM_j=0..d-1{ 𝑏[𝑖 ⋅ 𝑑 + 𝑗] ⋅ 2𝑗 } mod m for j in 0..d { // select the next bit, according to bitcount, then shift it up by j - F[i] |= (((B[(i*d + j)/8] >> (i*d + j)%8) & 1) as i16) << j; // there's supposed to be a `mod m` here, but that shouldn't matter; we'll check it below anyway. + F[i] |= (((B[(i * d + j) / 8] >> (i * d + j) % 8) & 1) as i16) << j; // there's supposed to be a `mod m` here, but that shouldn't matter; we'll check it below anyway. } } @@ -119,12 +117,12 @@ pub(crate) fn sample_ntt(rho: &[u8; 32], nonce: &[u8; 2]) -> Polynomial { // 6: 𝑑1 ← 𝐶[0] + 256 ⋅ (𝐶[1] mod 16) // ▷ 0 ≤ 𝑑1 < 2^12 - let d1: i16 = (C[idx+0] as i16) | ((C[idx+1] as i32) << 8) as i16 & 0xFFF; + let d1: i16 = (C[idx + 0] as i16) | ((C[idx + 1] as i32) << 8) as i16 & 0xFFF; debug_assert!(d1 < 2 << 12); // 7: 𝑑2 ← ⌊𝐶[1]/16⌋ + 16 ⋅ 𝐶[2] // ▷ 0 ≤ 𝑑2 < 2^12 - let d2: i16 = ((C[idx+1] as i16) >> 4) | ((C[idx+2] as i32) << 4) as i16 & 0xFFF; + let d2: i16 = ((C[idx + 1] as i16) >> 4) | ((C[idx + 2] as i32) << 4) as i16 & 0xFFF; debug_assert!(d2 < 2 << 12); // 8: if 𝑑1 < 𝑞 then @@ -163,8 +161,8 @@ pub(crate) fn sample_poly_cbd(bytes: &[u8]) -> Polynomial { match eta { 2 => { - for i in 0..N/8 { - let t = u32::from_le_bytes(bytes[4*i .. 4*i + 4].try_into().unwrap()); + for i in 0..N / 8 { + let t = u32::from_le_bytes(bytes[4 * i..4 * i + 4].try_into().unwrap()); let mut d = t & 0x55555555; d += (t >> 1) & 0x55555555; for j in 0..8usize { @@ -179,7 +177,7 @@ pub(crate) fn sample_poly_cbd(bytes: &[u8]) -> Polynomial { } } 3 => { - for i in 0..N/4 { + for i in 0..N / 4 { let t = little_endian_to_u24(bytes, 3 * i); let mut d = t & 0x00249249; d += (t >> 1) & 0x00249249; @@ -204,7 +202,6 @@ pub(crate) fn sample_poly_cbd(bytes: &[u8]) -> Polynomial { /// SamplePolyCBD𝜂1(PRF𝜂1 (𝜎, 𝑁 )) /// Performs both the PRF and SamplePolyCBD steps pub(crate) fn sample_poly_CBD(b: &[u8; 32], n: u8) -> Polynomial { - // Alg 13: 9: 𝐬[𝑖] ← SamplePolyCBD𝜂1(PRF𝜂1 (𝜎, 𝑁 )) // ▷ 𝐬[𝑖] ∈ ℤ256 sampled from CBD match eta { @@ -220,7 +217,7 @@ pub(crate) fn sample_poly_CBD(b: &[u8; 32], n: u8) -> Polynomial }; sample_poly_cbd::(&buf) - }, + } 3 => { let buf = { let mut xof = SHAKE256::new(); @@ -232,13 +229,16 @@ pub(crate) fn sample_poly_CBD(b: &[u8; 32], n: u8) -> Polynomial }; sample_poly_cbd::(&buf) - }, - _ => unreachable!() + } + _ => unreachable!(), } } /// Internal helper for keygen since both s_hat and e_hat have identical sampling code -pub(crate) fn sample_vector_CBD(b: &[u8; 32], mut n: u8) -> Vector { +pub(crate) fn sample_vector_CBD( + b: &[u8; 32], + mut n: u8, +) -> Vector { let mut v = Vector::::new(); for i in 0..k { @@ -302,13 +302,20 @@ pub(super) fn cond_sub_q(a: i16) -> i16 { tmp + ((tmp >> 15) & q) } - /// Multiplication of polynomials in Zq\[X]/(X^2-zeta) /// used for multiplication of elements in Rq in NTT domain /// /// Borrowed from: /// https://github.com/pq-crystals/kyber/blob/main/ref/ntt.c#L139 -pub(crate) fn ntt_base_mult(r: &mut [i16], off: usize, a0: i16, a1: i16, b0: i16, b1: i16, zeta: i16) { +pub(crate) fn ntt_base_mult( + r: &mut [i16], + off: usize, + a0: i16, + a1: i16, + b0: i16, + b1: i16, + zeta: i16, +) { let mut out_val0 = mul_mont(a1, b1); out_val0 = mul_mont(out_val0, zeta); out_val0 += mul_mont(a0, b0); @@ -319,29 +326,46 @@ pub(crate) fn ntt_base_mult(r: &mut [i16], off: usize, a0: i16, a1: i16, b0: i16 r[off + 1] = out_val1; } -pub(crate) fn pack_ciphertext(u: &Vector, v: &Polynomial) -> [u8; CT_LEN] { +pub(crate) fn pack_ciphertext( + u: &Vector, + v: &Polynomial, +) -> [u8; CT_LEN] { let mut out = [0u8; CT_LEN]; // each of the N i16's will take du bits, so a polynomial takes N * du bits, then we have k of them - let lim: usize = k* (N * (du as usize) / 8); + let lim: usize = k * (N * (du as usize) / 8); u.compress_pol_vec::(&mut out[..lim]); v.compress_poly::(&mut out[lim..]); out } -pub(crate) fn unpack_ciphertext_u(c: &[u8; CT_LEN]) -> Vector { +pub(crate) fn unpack_ciphertext_u< + const k: usize, + const CT_LEN: usize, + const du: i16, + const dv: i16, +>( + c: &[u8; CT_LEN], +) -> Vector { // each of the N i16's will take du bits, so a polynomial takes N * du bits, then we have k of them - let lim: usize = k* (N * (du as usize) / 8); + let lim: usize = k * (N * (du as usize) / 8); let u = Vector::::decompress_pol_vec::(&c[..lim]); u } -pub(crate) fn unpack_ciphertext_v(c: &[u8; CT_LEN]) -> Polynomial { +pub(crate) fn unpack_ciphertext_v< + const k: usize, + const CT_LEN: usize, + const du: i16, + const dv: i16, +>( + c: &[u8; CT_LEN], +) -> Polynomial { // each of the N i16's will take du bits, so a polynomial takes N * du bits, then we have k of them - let lim: usize = k* (N * (du as usize) / 8); + let lim: usize = k * (N * (du as usize) / 8); let v = Polynomial::decompress_poly::(&c[lim..]); diff --git a/crypto/mlkem/src/lib.rs b/crypto/mlkem/src/lib.rs index 117627d..4de7d42 100644 --- a/crypto/mlkem/src/lib.rs +++ b/crypto/mlkem/src/lib.rs @@ -138,25 +138,20 @@ //! constant-time after compilation. #![no_std] - #![forbid(missing_docs)] - #![forbid(unsafe_code)] #![allow(incomplete_features)] // needed because currently generic_const_exprs is experimental #![feature(generic_const_exprs)] #![feature(adt_const_params)] - // These are because I'm matching variable names exactly against FIPS 204, for example both 'K' and 'k', // or 'A' and 'a' are used and have specific meanings. // But need to tell the rust linter to not care. #![allow(non_snake_case)] #![allow(non_upper_case_globals)] - // so I can use private traits to hide internal stuff that needs to be generic within the // MLKEM implementation, but I don't want accessed from outside, such as FIPS-internal functions. #![allow(private_bounds)] - // imports needed just for docs #[allow(unused_imports)] use bouncycastle_core::key_material::KeyMaterialTrait; @@ -165,33 +160,40 @@ use bouncycastle_core::key_material::KeyMaterialTrait; // todo -- crucible tests +mod aux_functions; +mod matrix; pub mod mlkem; mod mlkem_keys; mod polynomial; -mod aux_functions; -mod matrix; - /*** Exported types ***/ -pub use mlkem::{MLKEMTrait, MLKEM, MLKEM512, MLKEM768, MLKEM1024}; +pub use mlkem::{MLKEM, MLKEM512, MLKEM768, MLKEM1024, MLKEMTrait}; +pub use mlkem_keys::{ + MLKEM512PrivateKey, MLKEM768PrivateKey, MLKEM1024PrivateKey, MLKEMPrivateKey, +}; +pub use mlkem_keys::{ + MLKEM512PrivateKeyExpanded, MLKEM768PrivateKeyExpanded, MLKEM1024PrivateKeyExpanded, + MLKEMPrivateKeyExpanded, +}; +pub use mlkem_keys::{MLKEM512PublicKey, MLKEM768PublicKey, MLKEM1024PublicKey, MLKEMPublicKey}; +pub use mlkem_keys::{ + MLKEM512PublicKeyExpanded, MLKEM768PublicKeyExpanded, MLKEM1024PublicKeyExpanded, + MLKEMPublicKeyExpanded, +}; pub use mlkem_keys::{MLKEMPrivateKeyTrait, MLKEMPublicKeyTrait}; -pub use mlkem_keys::{MLKEMPublicKey, MLKEM512PublicKey, MLKEM768PublicKey, MLKEM1024PublicKey}; -pub use mlkem_keys::{MLKEMPublicKeyExpanded, MLKEM512PublicKeyExpanded, MLKEM768PublicKeyExpanded, MLKEM1024PublicKeyExpanded}; -pub use mlkem_keys::{MLKEMPrivateKey, MLKEM512PrivateKey, MLKEM768PrivateKey, MLKEM1024PrivateKey}; -pub use mlkem_keys::{MLKEMPrivateKeyExpanded, MLKEM512PrivateKeyExpanded, MLKEM768PrivateKeyExpanded, MLKEM1024PrivateKeyExpanded}; /*** Exported constants ***/ pub use mlkem::ML_KEM_512_NAME; pub use mlkem::ML_KEM_768_NAME; pub use mlkem::ML_KEM_1024_NAME; -pub use mlkem::{MLKEM_SEED_LEN, MLKEM_SS_LEN, MLKEM_RND_LEN}; +pub use mlkem::{MLKEM_RND_LEN, MLKEM_SEED_LEN, MLKEM_SS_LEN}; -pub use mlkem::{MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM512_CT_LEN}; -pub use mlkem::{MLKEM768_PK_LEN, MLKEM768_SK_LEN, MLKEM768_CT_LEN}; -pub use mlkem::{MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, MLKEM1024_CT_LEN}; +pub use mlkem::{MLKEM512_CT_LEN, MLKEM512_PK_LEN, MLKEM512_SK_LEN}; +pub use mlkem::{MLKEM768_CT_LEN, MLKEM768_PK_LEN, MLKEM768_SK_LEN}; +pub use mlkem::{MLKEM1024_CT_LEN, MLKEM1024_PK_LEN, MLKEM1024_SK_LEN}; pub use matrix::Matrix; // re-export just so it's visible to unit tests -pub use polynomial::Polynomial; \ No newline at end of file +pub use polynomial::Polynomial; diff --git a/crypto/mlkem/src/matrix.rs b/crypto/mlkem/src/matrix.rs index 381e7be..100d6e0 100644 --- a/crypto/mlkem/src/matrix.rs +++ b/crypto/mlkem/src/matrix.rs @@ -3,16 +3,18 @@ use core::ops::{Index, IndexMut}; -use crate::mlkem::{q, N}; +use crate::mlkem::{N, q}; use crate::polynomial; -use crate::polynomial::{Polynomial}; +use crate::polynomial::Polynomial; #[derive(Clone)] /// A matrix over the ML-KEM ring. -pub struct Matrix{ /*pub(crate)*/ mat: [[Polynomial; l]; k] } +pub struct Matrix { + /*pub(crate)*/ mat: [[Polynomial; l]; k], +} /// Convenience function to avoid ".0" all over the place. -impl Index for Matrix { +impl Index for Matrix { type Output = [Polynomial; l]; fn index(&self, index: usize) -> &Self::Output { @@ -20,7 +22,7 @@ impl Index for Matrix { } } /// Convenience function to avoid ".0" all over the place. -impl IndexMut for Matrix { +impl IndexMut for Matrix { fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut self.mat[index] } @@ -28,7 +30,7 @@ impl IndexMut for Matrix { impl Matrix { pub(crate) fn new() -> Self { - Self{ mat: [[(); l]; k].map(|_| [(); l].map(|_| Polynomial::new())) } + Self { mat: [[(); l]; k].map(|_| [(); l].map(|_| Polynomial::new())) } } /// FIPS 204 Algorithm 48 MatrixVectorNTT(𝐌, 𝐯) @@ -41,16 +43,16 @@ impl Matrix { /// transpose: False will multiply A, where as True will multiply A^T pub(crate) fn matrix_vector_ntt(&self, v: &Vector) -> Vector { let mut w = Vector::::new(); - for i in 0 .. k { + for i in 0..k { // split out the 0 case to skip a no-op add_ntt() - w[i] = if transpose{ + w[i] = if transpose { polynomial::base_mult_montgomery(&self.mat[0][i], &v[0]) } else { polynomial::base_mult_montgomery(&self.mat[i][0], &v[0]) }; let mut w1: Polynomial; - for j in 1 .. l { + for j in 1..l { // dot product a vector into a matrix: multiply the input vector // into each row of the matrix, then sum the results to produce a vector of // length k. @@ -79,9 +81,10 @@ impl Matrix { // Technically all matrices and some vectors are only part of the public key and might not need to be zeroized, // but I'll leave it zeroizing for now and leave this as a potential future optimization. - #[derive(Clone)] -pub(crate) struct Vector{ pub(crate) vec: [Polynomial; k] } +pub(crate) struct Vector { + pub(crate) vec: [Polynomial; k], +} /// Convenience function to avoid ".0" all over the place. impl Index for Vector { @@ -98,10 +101,9 @@ impl IndexMut for Vector { } } -impl Vector -{ +impl Vector { pub(crate) fn new() -> Self { - Self {vec: [(); k].map(|_| Polynomial::new()) } + Self { vec: [(); k].map(|_| Polynomial::new()) } } /// Algorithm 46 AddVectorNTT(𝐯, 𝐰)̂ @@ -110,7 +112,7 @@ impl Vector /// Output: u_hat ∈ T^ℓ_𝑞. /// Add another vector to this vector pub(crate) fn add_vector_ntt(&mut self, s: &Self) { - for i in 0 ..k { + for i in 0..k { // perform montgomery addition of each polynomial in the vector self[i].add(&s[i]); } @@ -138,7 +140,7 @@ impl Vector } } - pub(crate) fn ntt(&mut self){ + pub(crate) fn ntt(&mut self) { for i in 0..k { self[i].ntt(); } @@ -151,7 +153,7 @@ impl Vector } pub(crate) fn convert_to_mont(&mut self) { - for i in 0 ..k { + for i in 0..k { self[i].convert_to_mont(); } } @@ -165,7 +167,7 @@ impl Vector // make sure we were given the right size output buffer // each of the N i16's will take dv bits - debug_assert_eq!(out.len(), k *(N * (du as usize) / 8)); + debug_assert_eq!(out.len(), k * (N * (du as usize) / 8)); // bc-java has a conditional_sub_q() here, but I pass all unit tests without it, so I'm taking it out for performance. // let mut s = self.clone(); @@ -173,10 +175,11 @@ impl Vector let mut idx = 0; match du { - 10 => { // MLKEM512 and MLKEM 768 + 10 => { + // MLKEM512 and MLKEM 768 let mut t = [0i16; 4]; for i in 0..k { - for j in 0..N/4 { + for j in 0..N / 4 { // fill the temp array t for (l, item) in t.iter_mut().enumerate() { *item = (((((self[i][4 * j + l] as u32) << 10) as i32 @@ -193,11 +196,11 @@ impl Vector idx += 5; } } - }, + } 11 => { let mut t = [0i16; 8]; for i in 0..k { - for j in 0..N/8 { + for j in 0..N / 8 { for (l, item) in t.iter_mut().enumerate() { *item = (((((self[i][8 * j + l] as u32) << 11) as i32 + (q as i32 / 2)) @@ -219,7 +222,7 @@ impl Vector idx += 11; } } - }, + } _ => unreachable!(), } } @@ -232,17 +235,17 @@ impl Vector // make sure we were given the right size output buffer // each of the N i16's will take dv bits - debug_assert_eq!(compressed_u.len(), k *(N * (du as usize) / 8)); + debug_assert_eq!(compressed_u.len(), k * (N * (du as usize) / 8)); let mut idx = 0; match du { - 10 => { // MLKEM512 and MLKEM768 + 10 => { + // MLKEM512 and MLKEM768 let mut t = [0i16; 4]; for i in 0..k { - for j in 0..(N/4) { - t[0] = ((compressed_u[idx] as u16) - | (compressed_u[idx + 1] as u16) << 8) + for j in 0..(N / 4) { + t[0] = ((compressed_u[idx] as u16) | (compressed_u[idx + 1] as u16) << 8) as i16; t[1] = (((compressed_u[idx + 1] as u16) >> 2) | (compressed_u[idx + 2] as u16) << 6) @@ -260,11 +263,12 @@ impl Vector } } } - }, - 11 => { // MLKEM1024 + } + 11 => { + // MLKEM1024 let mut t = [0i16; 8]; for i in 0..k { - for j in 0..N/8 { + for j in 0..N / 8 { t[0] = (compressed_u[idx] as i32 | ((compressed_u[idx + 1] as u16) as i32) << 8) as i16; @@ -298,10 +302,10 @@ impl Vector } } } - }, + } _ => unreachable!(), } u } -} \ No newline at end of file +} diff --git a/crypto/mlkem/src/mlkem.rs b/crypto/mlkem/src/mlkem.rs index 70f4352..bd31e43 100644 --- a/crypto/mlkem/src/mlkem.rs +++ b/crypto/mlkem/src/mlkem.rs @@ -125,22 +125,28 @@ //! assert_eq!(ss, ss1.ref_to_bytes()); //! ``` - -use core::marker::PhantomData; -use bouncycastle_core::errors::{KEMError}; -use bouncycastle_core::key_material::{KeyMaterialTrait, KeyMaterial, KeyType}; -use bouncycastle_core::traits::{RNG, SecurityStrength, XOF, Algorithm, Hash, KEM}; -use bouncycastle_rng::{HashDRBG_SHA512}; -use bouncycastle_sha3::{SHA3_256, SHA3_512, SHAKE256}; -use bouncycastle_utils::ct::{conditional_copy_bytes, ct_eq_bytes}; -use crate::aux_functions::{sample_poly_CBD, sample_vector_CBD, pack_ciphertext, expandA, unpack_ciphertext_u, unpack_ciphertext_v}; +use crate::MLKEMPublicKeyExpanded; +use crate::aux_functions::{ + expandA, pack_ciphertext, sample_poly_CBD, sample_vector_CBD, unpack_ciphertext_u, + unpack_ciphertext_v, +}; use crate::matrix::{Matrix, Vector}; -use crate::mlkem_keys::{MLKEMPublicKeyTrait, MLKEMPublicKeyInternalTrait, MLKEMPrivateKeyExpanded}; -use crate::mlkem_keys::{MLKEMPrivateKeyTrait, MLKEMPrivateKeyInternalTrait}; -use crate::mlkem_keys::{MLKEM512PublicKey, MLKEM512PrivateKey, MLKEM768PublicKey, MLKEM768PrivateKey, MLKEM1024PublicKey, MLKEM1024PrivateKey}; -use crate::{MLKEMPublicKeyExpanded}; +use crate::mlkem_keys::{ + MLKEM512PrivateKey, MLKEM512PublicKey, MLKEM768PrivateKey, MLKEM768PublicKey, + MLKEM1024PrivateKey, MLKEM1024PublicKey, +}; +use crate::mlkem_keys::{ + MLKEMPrivateKeyExpanded, MLKEMPublicKeyInternalTrait, MLKEMPublicKeyTrait, +}; +use crate::mlkem_keys::{MLKEMPrivateKeyInternalTrait, MLKEMPrivateKeyTrait}; use crate::polynomial::Polynomial; - +use bouncycastle_core::errors::KEMError; +use bouncycastle_core::key_material::{KeyMaterial, KeyMaterialTrait, KeyType}; +use bouncycastle_core::traits::{Algorithm, Hash, KEM, RNG, SecurityStrength, XOF}; +use bouncycastle_rng::HashDRBG_SHA512; +use bouncycastle_sha3::{SHA3_256, SHA3_512, SHAKE256}; +use bouncycastle_utils::ct::{conditional_copy_bytes, ct_eq_bytes}; +use core::marker::PhantomData; /*** Constants ***/ @@ -166,7 +172,6 @@ pub(crate) const q_inv: i32 = 62209; pub(crate) const ETA2: i16 = 2; pub(crate) const POLY_BYTES: usize = 384; - /* ML-KEM-512 params */ /// Length of the \[u8] holding a ML-KEM-512 public key. @@ -197,7 +202,6 @@ pub(crate) const MLKEM768_DV: i16 = 4; /// Maps to "required RBG strength (bits)" in FIPS 203 Table 2 pub(crate) const MLKEM768_LAMBDA: i16 = 192; - /* ML-KEM-1024 params */ /// Length of the \[u8] holding a ML-KEM-1024 public key. @@ -213,15 +217,11 @@ pub(crate) const MLKEM1024_DV: i16 = 5; /// Maps to "required RBG strength (bits)" in FIPS 203 Table 2 pub(crate) const MLKEM1024_LAMBDA: i16 = 256; - - // Typedefs just to make the algorithms look more like the FIPS 204 sample code. pub(crate) type G = SHA3_512; pub(crate) type H = SHA3_256; pub(crate) type J = SHAKE256; - - /*** Pub Types ***/ /// The ML-KEM-512 algorithm. @@ -293,7 +293,8 @@ pub struct MLKEM< const CT_LEN: usize, const SS_LEN: usize, PK: MLKEMPublicKeyTrait + MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const k: usize, const eta: i16, const du: i16, @@ -309,31 +310,17 @@ impl< const CT_LEN: usize, const SS_LEN: usize, PK: MLKEMPublicKeyTrait + MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const k: usize, const eta1: i16, const du: i16, const dv: i16, const LAMBDA: i16, -> MLKEM< - PK_LEN, - SK_LEN, - CT_LEN, - SS_LEN, - PK, - SK, - k, - eta1, - du, - dv, - LAMBDA, -> +> MLKEM { /// Should still be ok in FIPS mode - pub fn keygen_from_os_rng() -> Result< - (PK, SK), - KEMError, - > { + pub fn keygen_from_os_rng() -> Result<(PK, SK), KEMError> { let mut seed = KeyMaterial::<64>::new(); HashDRBG_SHA512::new_from_os().fill_keymaterial_out(&mut seed)?; Self::keygen_internal(&seed) @@ -344,12 +331,7 @@ impl< /// Input: randomness 𝑧 ∈ 𝔹32 . /// Output: encapsulation key ek ∈ 𝔹384𝑘+32 . /// Output: decapsulation key dk ∈ 𝔹768𝑘+96 . - pub(crate) fn keygen_internal( - seed: &KeyMaterial<64>, - ) -> Result< - (PK, SK), - KEMError, - > { + pub(crate) fn keygen_internal(seed: &KeyMaterial<64>) -> Result<(PK, SK), KEMError> { if !(seed.key_type() == KeyType::Seed || seed.key_type() == KeyType::BytesFullEntropy) || seed.key_len() != 64 { @@ -359,7 +341,9 @@ impl< } if seed.security_strength() < SecurityStrength::from_bits(LAMBDA as usize) { - return Err(KEMError::KeyGenError("Seed SecurityStrength must match algorithm security strength")); + return Err(KEMError::KeyGenError( + "Seed SecurityStrength must match algorithm security strength", + )); } // 1: (ekPKE, dkPKE) ← K-PKE.KeyGen(𝑑) @@ -369,12 +353,15 @@ impl< // 3: dk ← (dkPKE‖ek‖H(ek)‖𝑧) ▷ KEM decaps key includes PKE decryption key // 4: return (ek, dk) let pk_hash = pk.compute_hash(); - Ok((pk.clone(), SK::new( - s_hat, - pk, - pk_hash, - seed.ref_to_bytes()[32..].try_into().unwrap(), - Some(seed.ref_to_bytes()[..32].try_into().unwrap())) + Ok(( + pk.clone(), + SK::new( + s_hat, + pk, + pk_hash, + seed.ref_to_bytes()[32..].try_into().unwrap(), + Some(seed.ref_to_bytes()[..32].try_into().unwrap()), + ), )) } @@ -403,7 +390,6 @@ impl< // Note: in the definition of PRF_eta on page 18, it's said to be one byte. // since the number of loops here is static; we can hard-code the N values rather than using a counter - // 8: for (𝑖 ← 0; 𝑖 < 𝑘; 𝑖++) // ▷ generate 𝐬 ∈ (ℤ256)^k // 9: 𝐬[𝑖] ← SamplePolyCBD𝜂1(PRF𝜂1 (𝜎, 𝑁 )) @@ -445,7 +431,6 @@ impl< t_hat.add_vector_ntt(&e); } - // Clear the secret data before returning memory to the OS sigma.fill(0u8); @@ -462,11 +447,10 @@ impl< /// Input: message 𝑚 ∈ 𝔹32 . /// Input: randomness 𝑟 ∈ 𝔹32 . /// Output: ciphertext 𝑐 ∈ 𝔹32(𝑑𝑢𝑘+𝑑𝑣). - fn pke_encrypt(ek: &PK, A_hat: &Matrix, m: [u8; 32], r: &[u8; 32]) -> [u8; CT_LEN] { + fn pke_encrypt(ek: &PK, A_hat: &Matrix, m: [u8; 32], r: &[u8; 32]) -> [u8; CT_LEN] { // 1: 𝑁 ← 0 // since the number of loops here is static; we can hard-code the N values rather than using a counter - // 2: 𝐭 ← ByteDecode12(ekPKE[0 ∶ 384𝑘]) // 3: 𝜌 ← ekPKE[384𝑘 ∶ 384𝑘 + 32] // not necessary here because ek is already decoded @@ -516,7 +500,7 @@ impl< // 17: 𝑒2 ← SamplePolyCBD𝜂2(PRF𝜂2 (𝑟, 𝑁)) // ▷ sample 𝑒2 ∈ ℤ256 from CBD // note: here n = 2k - let e2 = sample_poly_CBD::(&r, 2*k as u8); + let e2 = sample_poly_CBD::(&r, 2 * k as u8); v.add(&e2); let mu = Polynomial::from_msg(m); @@ -524,7 +508,6 @@ impl< v.poly_reduce(); - pack_ciphertext::(&u, &v) } @@ -556,8 +539,12 @@ impl< /// that wish to provide randomness from their own source instead of the built-in RNG in bc-rust. /// If you think you will be clever and invent some scheme that uses a deterministic KEM, /// then you will almost certainly end up with security problems. Please don't do this. - pub fn encaps_internal(ek: &PK, A_hat: Option<&Matrix>, m: [u8; 32]) -> ([u8; 32], [u8; CT_LEN]) { - debug_assert_eq!(CT_LEN, 32*( (du as usize)*k + (dv as usize))); + pub fn encaps_internal( + ek: &PK, + A_hat: Option<&Matrix>, + m: [u8; 32], + ) -> ([u8; 32], [u8; CT_LEN]) { + debug_assert_eq!(CT_LEN, 32 * ((du as usize) * k + (dv as usize))); // 1: (𝐾, 𝑟) ← G(𝑚‖H(ek)) // ▷ derive shared secret key 𝐾 and randomness 𝑟 @@ -580,12 +567,8 @@ impl< // To allow for pre-computing A_hat for multiple encapsulations, we will either take // A_hat passed in, or compute it fresh. let ct = match A_hat { - Some(A_hat) => { - Self::pke_encrypt(ek, A_hat, m, &r) - } - None => { - Self::pke_encrypt(ek, &ek.A_hat(), m, &r) - } + Some(A_hat) => Self::pke_encrypt(ek, A_hat, m, &r), + None => Self::pke_encrypt(ek, &ek.A_hat(), m, &r), }; (K, ct) @@ -633,12 +616,15 @@ impl< /// Input: decapsulation key dk ∈ 𝔹768𝑘+96 . /// Input: ciphertext 𝑐 ∈ 𝔹32(𝑑𝑢𝑘+𝑑𝑣). /// Output: shared secret key 𝐾 ∈ 𝔹32 . - fn decaps_internal(dk: &SK, A_hat: Option<&Matrix>, c: [u8; CT_LEN]) -> [u8; MLKEM_SS_LEN] { - + fn decaps_internal( + dk: &SK, + A_hat: Option<&Matrix>, + c: [u8; CT_LEN], + ) -> [u8; MLKEM_SS_LEN] { // I have tried to keep this as clean as possible for correspondence with the FIPS, // but I have moved things around so that I can use unnamed scopes to limit how many // stack variables are alive at the same time. - + // 1: dkPKE ← dk[0 ∶ 384𝑘] ▷ extract (from KEM decaps key) the PKE decryption key // 2: ekPKE ← dk[384𝑘 ∶ 768𝑘 + 32] ▷ extract PKE encryption key // 3: ℎ ← dk[768𝑘 + 32 ∶ 768𝑘 + 64] ▷ extract hash of PKE encryption key @@ -687,12 +673,8 @@ impl< // To allow for pre-computing A_hat for multiple encapsulations, we will either take // A_hat passed in, or compute it fresh. let c_prime = match A_hat { - Some(A_hat) => { - Self::pke_encrypt(dk.pk(), A_hat, m_prime, &r_prime) - } - None => { - Self::pke_encrypt(dk.pk(), &dk.pk().A_hat(), m_prime, &r_prime) - } + Some(A_hat) => Self::pke_encrypt(dk.pk(), A_hat, m_prime, &r_prime), + None => Self::pke_encrypt(dk.pk(), &dk.pk().A_hat(), m_prime, &r_prime), }; // 9: if 𝑐 ≠ 𝑐′ then @@ -707,7 +689,10 @@ impl< /// Alternative initialization of the streaming signer where you have your private key /// as a seed and you want to delay its expansion as late as possible for memory-usage reasons. // todo -- should we build a fully-stitched-together decaps-from-seed ... or not? - pub fn decaps_from_seed(seed: &KeyMaterial<64>, ct: &[u8]) -> Result, KEMError> { + pub fn decaps_from_seed( + seed: &KeyMaterial<64>, + ct: &[u8], + ) -> Result, KEMError> { let (_pk, sk) = Self::keygen_from_seed(seed)?; Self::decaps(&sk, ct) @@ -720,25 +705,16 @@ impl< const CT_LEN: usize, const SS_LEN: usize, PK: MLKEMPublicKeyTrait + MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const k: usize, const eta1: i16, const du: i16, const dv: i16, const LAMBDA: i16, -> MLKEMTrait for MLKEM< - PK_LEN, - SK_LEN, - CT_LEN, - SS_LEN, - PK, - SK, - k, - eta1, - du, - dv, - LAMBDA, -> { +> MLKEMTrait + for MLKEM +{ /// Imports a secret key from a seed. fn keygen_from_seed(seed: &KeyMaterial<64>) -> Result<(PK, SK), KEMError> { Self::keygen_internal(seed) @@ -752,10 +728,7 @@ impl< fn keygen_from_seed_and_encoded( seed: &KeyMaterial<64>, encoded_sk: &[u8; SK_LEN], - ) -> Result< - (PK, SK), - KEMError, - > { + ) -> Result<(PK, SK), KEMError> { let (pk, sk) = Self::keygen_internal(seed)?; let sk_from_bytes = SK::sk_decode(encoded_sk)?; @@ -775,10 +748,7 @@ impl< /// (in which case a keygen_from_seed is run and then the pk's compared). /// /// Returns either `()` or [KEMError::ConsistencyCheckFailed]. - fn keypair_consistency_check( - pk: &PK, - sk: &SK, - ) -> Result<(), KEMError> { + fn keypair_consistency_check(pk: &PK, sk: &SK) -> Result<(), KEMError> { let derived_pk = sk.pk(); if derived_pk.compute_hash() == pk.compute_hash() { Ok(()) @@ -787,7 +757,9 @@ impl< } } - fn encaps_for_expanded_key(pk: &MLKEMPublicKeyExpanded) -> Result<(KeyMaterial, [u8; CT_LEN]), KEMError> { + fn encaps_for_expanded_key( + pk: &MLKEMPublicKeyExpanded, + ) -> Result<(KeyMaterial, [u8; CT_LEN]), KEMError> { let mut m = [0u8; 32]; HashDRBG_SHA512::new_from_os().next_bytes_out(&mut m)?; @@ -795,7 +767,7 @@ impl< let mut key = KeyMaterial::::from_bytes_as_type(&ss, KeyType::BytesFullEntropy)?; key.allow_hazardous_operations(); - key.set_security_strength( SecurityStrength::from_bits(LAMBDA as usize) )?; + key.set_security_strength(SecurityStrength::from_bits(LAMBDA as usize))?; key.drop_hazardous_operations(); Ok((key, ct)) @@ -808,7 +780,7 @@ impl< /* decapsulation inputs checks described on FIPS 203 section 7.3 */ // 1. (Ciphertext type check) If 𝑐 is not a byte array of length 32(𝑑𝑢 𝑘 + 𝑑𝑣) for the values of 𝑑𝑢, // 𝑑𝑣, and 𝑘 specified by the relevant parameter set, then input checking has failed. - debug_assert_eq!(CT_LEN, 32*( (du as usize)*k + (dv as usize))); + debug_assert_eq!(CT_LEN, 32 * ((du as usize) * k + (dv as usize))); if ct.len() != CT_LEN { return Err(KEMError::LengthError("Ciphertext has the incorrect length")); @@ -821,13 +793,12 @@ impl< // 3. Check that the H(ek) stored in the private key matches the ek also stored in the private key. // Again, this is handled by the MLKEMPrivateKey trait. - /* the actual decaps operation */ let K = Self::decaps_internal(&sk.dk, Some(&sk.A_hat), ct.try_into().unwrap()); let mut key = KeyMaterial::::from_bytes_as_type(&K, KeyType::BytesFullEntropy)?; key.allow_hazardous_operations(); - key.set_security_strength( SecurityStrength::from_bits(LAMBDA as usize) )?; + key.set_security_strength(SecurityStrength::from_bits(LAMBDA as usize))?; key.drop_hazardous_operations(); Ok(key) @@ -841,13 +812,15 @@ pub trait MLKEMTrait< const CT_LEN: usize, const SS_LEN: usize, PK: MLKEMPublicKeyTrait + MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const k: usize, const eta: i16, const du: i16, const dv: i16, const LAMBDA: i16, -> : Sized { +>: Sized +{ /// Imports a secret key from a seed. fn keygen_from_seed(seed: &KeyMaterial<64>) -> Result<(PK, SK), KEMError>; /// Imports a secret key from both a seed and an encoded_sk. @@ -859,10 +832,7 @@ pub trait MLKEMTrait< fn keygen_from_seed_and_encoded( seed: &KeyMaterial<64>, encoded_sk: &[u8; SK_LEN], - ) -> Result< - (PK, SK), - KEMError, - >; + ) -> Result<(PK, SK), KEMError>; /// Given a public key and a secret key, check that the public key matches the secret key. /// This is a sanity check that the public key was generated correctly from the secret key. /// @@ -871,14 +841,11 @@ pub trait MLKEMTrait< /// (in which case a keygen_from_seed is run and then the pk's compared). /// /// Returns either `()` or [KEMError::ConsistencyCheckFailed]. - fn keypair_consistency_check( - pk: &PK, - sk: &SK, - ) -> Result<(), KEMError>; + fn keypair_consistency_check(pk: &PK, sk: &SK) -> Result<(), KEMError>; /// Same as [KEM::encaps], but acts on an [MLKEMPublicKeyExpanded]. fn encaps_for_expanded_key( - pk: &MLKEMPublicKeyExpanded + pk: &MLKEMPublicKeyExpanded, ) -> Result<(KeyMaterial, [u8; CT_LEN]), KEMError>; /// Same as [KEM::decaps], but acts on an [MLKEMPrivateKeyExpanded]. @@ -894,25 +861,16 @@ impl< const CT_LEN: usize, const SS_LEN: usize, PK: MLKEMPublicKeyTrait + MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const k: usize, const eta: i16, const du: i16, const dv: i16, const LAMBDA: i16, -> KEM for MLKEM< - PK_LEN, - SK_LEN, - CT_LEN, - SS_LEN, - PK, - SK, - k, - eta, - du, - dv, - LAMBDA, -> { +> KEM + for MLKEM +{ /// Generates a fresh key pair. fn keygen() -> Result<(PK, SK), KEMError> { Self::keygen_from_os_rng() @@ -937,6 +895,9 @@ impl< /// The derived shared secret key is returned as a KeyMaterial with the SecurityStrength set to /// the security level of the ML-KEM parameter set. fn decaps(sk: &SK, ct: &[u8]) -> Result, KEMError> { - Self::decaps_with_expanded_key(&MLKEMPrivateKeyExpanded::::from(sk), ct) + Self::decaps_with_expanded_key( + &MLKEMPrivateKeyExpanded::::from(sk), + ct, + ) } } diff --git a/crypto/mlkem/src/mlkem_keys.rs b/crypto/mlkem/src/mlkem_keys.rs index bcf75ba..850929a 100644 --- a/crypto/mlkem/src/mlkem_keys.rs +++ b/crypto/mlkem/src/mlkem_keys.rs @@ -1,54 +1,74 @@ use crate::aux_functions::{byte_decode, byte_encode, expandA}; use crate::matrix::{Matrix, Vector}; -use crate::mlkem::{POLY_BYTES, H, q}; +use crate::mlkem::{H, POLY_BYTES, q}; +use crate::mlkem::{MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM512_k}; +use crate::mlkem::{MLKEM768_PK_LEN, MLKEM768_SK_LEN, MLKEM768_k}; +use crate::mlkem::{MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, MLKEM1024_k}; use crate::{ML_KEM_512_NAME, ML_KEM_768_NAME, ML_KEM_1024_NAME}; -use crate::mlkem::{MLKEM512_k, MLKEM512_PK_LEN, MLKEM512_SK_LEN}; -use crate::mlkem::{MLKEM768_k, MLKEM768_PK_LEN, MLKEM768_SK_LEN}; -use crate::mlkem::{MLKEM1024_k, MLKEM1024_PK_LEN, MLKEM1024_SK_LEN}; -use bouncycastle_core::key_material::{KeyMaterialTrait, KeyMaterial, KeyType}; -use bouncycastle_core::traits::{Hash, KEMPrivateKey, KEMPublicKey, Secret, SecurityStrength}; use bouncycastle_core::errors::KEMError; +use bouncycastle_core::key_material::{KeyMaterial, KeyMaterialTrait, KeyType}; +use bouncycastle_core::traits::{Hash, KEMPrivateKey, KEMPublicKey, Secret, SecurityStrength}; +use bouncycastle_sha3::SHA3_256; use core::fmt; use core::fmt::{Debug, Display, Formatter}; -use bouncycastle_sha3::SHA3_256; - // imports just for docs #[allow(unused_imports)] use crate::mlkem::MLKEMTrait; - - /* Pub Types */ /// ML-KEM-512 Public Key pub type MLKEM512PublicKey = MLKEMPublicKey; /// ML-KEM-512 Private Key -pub type MLKEM512PrivateKey = MLKEMPrivateKey; +pub type MLKEM512PrivateKey = + MLKEMPrivateKey; /// ML-KEM-768 Public Key pub type MLKEM768PublicKey = MLKEMPublicKey; /// ML-KEM-768 Private Key -pub type MLKEM768PrivateKey = MLKEMPrivateKey; +pub type MLKEM768PrivateKey = + MLKEMPrivateKey; /// ML-KEM-1024 Public Key pub type MLKEM1024PublicKey = MLKEMPublicKey; /// ML-KEM-1024 Private Key -pub type MLKEM1024PrivateKey = MLKEMPrivateKey; - +pub type MLKEM1024PrivateKey = + MLKEMPrivateKey; /* Pre-expanded keys for repeated operations */ /// ML-KEM-512 Public Key with a pre-expanded public matrix A for repeated encaps operations. -pub type MLKEM512PublicKeyExpanded = MLKEMPublicKeyExpanded; +pub type MLKEM512PublicKeyExpanded = + MLKEMPublicKeyExpanded; /// ML-KEM-512 Private Key with a pre-expanded public matrix A for repeated decaps operations. -pub type MLKEM512PrivateKeyExpanded = MLKEMPrivateKeyExpanded; +pub type MLKEM512PrivateKeyExpanded = MLKEMPrivateKeyExpanded< + MLKEM512_k, + MLKEM512PublicKey, + MLKEM512PrivateKey, + MLKEM512_SK_LEN, + MLKEM512_PK_LEN, +>; /// ML-KEM-768 Public Key with a pre-expanded public matrix A for repeated encaps operations. -pub type MLKEM768PublicKeyExpanded = MLKEMPublicKeyExpanded; +pub type MLKEM768PublicKeyExpanded = + MLKEMPublicKeyExpanded; /// ML-KEM-768 Private Key with a pre-expanded public matrix A for repeated decaps operations. -pub type MLKEM768PrivateKeyExpanded = MLKEMPrivateKeyExpanded; +pub type MLKEM768PrivateKeyExpanded = MLKEMPrivateKeyExpanded< + MLKEM768_k, + MLKEM768PublicKey, + MLKEM768PrivateKey, + MLKEM768_SK_LEN, + MLKEM768_PK_LEN, +>; /// ML-KEM-1024 Public Key with a pre-expanded public matrix A for repeated encaps operations. -pub type MLKEM1024PublicKeyExpanded = MLKEMPublicKeyExpanded; +pub type MLKEM1024PublicKeyExpanded = + MLKEMPublicKeyExpanded; /// ML-KEM-1024 Private Key with a pre-expanded public matrix A for repeated decaps operations. -pub type MLKEM1024PrivateKeyExpanded = MLKEMPrivateKeyExpanded; +pub type MLKEM1024PrivateKeyExpanded = MLKEMPrivateKeyExpanded< + MLKEM1024_k, + MLKEM1024PublicKey, + MLKEM1024PrivateKey, + MLKEM1024_SK_LEN, + MLKEM1024_PK_LEN, +>; /// An ML-KEM public key. #[derive(Clone)] @@ -58,7 +78,7 @@ pub struct MLKEMPublicKey { } /// General trait for all ML-KEM public keys types. -pub trait MLKEMPublicKeyTrait : KEMPublicKey { +pub trait MLKEMPublicKeyTrait: KEMPublicKey { /// Algorithm 23 pkDecode(𝑝𝑘) /// Reverses the procedure pkEncode. /// Input: Public key 𝑝𝑘 ∈ 𝔹32+32𝑘(bitlen (𝑞−1)−𝑑). @@ -70,16 +90,20 @@ pub trait MLKEMPublicKeyTrait : KEMPublicKe fn compute_hash(&self) -> [u8; 32]; } -pub(crate) trait MLKEMPublicKeyInternalTrait : MLKEMPublicKeyTrait { +pub(crate) trait MLKEMPublicKeyInternalTrait: + MLKEMPublicKeyTrait +{ /// Not exposing a constructor publicly because you should have to get an instance either by /// running a keygen, or by decoding an existing key. - fn new(t_hat: Vector, rho: [u8; 32], ) -> Self; + fn new(t_hat: Vector, rho: [u8; 32]) -> Self; /// Get a ref to t1 fn t_hat(&self) -> &Vector; } -impl MLKEMPublicKeyTrait for MLKEMPublicKey { +impl MLKEMPublicKeyTrait + for MLKEMPublicKey +{ fn pk_decode(pk: &[u8; PK_LEN]) -> Result { let (pk_chunks, last_chunk) = pk.as_chunks::(); @@ -88,7 +112,7 @@ impl MLKEMPublicKeyTrait for MLK debug_assert_eq!(last_chunk.len(), 32); let t_hat = { - let mut t_hat = Vector::::new(); + let mut t_hat = Vector::::new(); for (t_i, pk_chunk) in t_hat.vec.iter_mut().zip(pk_chunks) { t_i.coeffs.copy_from_slice(&byte_decode::<12, POLY_BYTES>(pk_chunk).coeffs); @@ -104,7 +128,6 @@ impl MLKEMPublicKeyTrait for MLK return Err(KEMError::DecodingError("Invalid or corrupted key")); } } - } t_hat @@ -126,15 +149,19 @@ impl MLKEMPublicKeyTrait for MLK } } -impl MLKEMPublicKeyInternalTrait for MLKEMPublicKey { +impl MLKEMPublicKeyInternalTrait + for MLKEMPublicKey +{ fn new(t_hat: Vector, rho: [u8; 32]) -> Self { Self { rho, t_hat } } - fn t_hat(&self) -> &Vector { &self.t_hat } + fn t_hat(&self) -> &Vector { + &self.t_hat + } } -impl KEMPublicKey for MLKEMPublicKey { +impl KEMPublicKey for MLKEMPublicKey { /// Encodes the public key as per FIPS 203 Algorithm 13 /// 19: ekPKE ← ByteEncode12(𝐭)‖𝜌 fn encode(&self) -> [u8; PK_LEN] { @@ -146,8 +173,8 @@ impl KEMPublicKey for MLKEMPublicK /// Encodes the public key as per FIPS 203 Algorithm 13 /// 19: ekPKE ← ByteEncode12(𝐭)‖𝜌 fn encode_out(&self, out: &mut [u8; PK_LEN]) -> usize { - debug_assert_eq!(PK_LEN, 12*k*32 + 32); - debug_assert_eq!(POLY_BYTES, 12*32); + debug_assert_eq!(PK_LEN, 12 * k * 32 + 32); + debug_assert_eq!(POLY_BYTES, 12 * 32); let (pk_chunks, last_chunk) = out.as_chunks_mut::(); @@ -164,13 +191,15 @@ impl KEMPublicKey for MLKEMPublicK } fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != PK_LEN { return Err(KEMError::DecodingError("Provided key bytes are the incorrect length")) } + if bytes.len() != PK_LEN { + return Err(KEMError::DecodingError("Provided key bytes are the incorrect length")); + } let bytes_sized: [u8; PK_LEN] = bytes[..PK_LEN].try_into().unwrap(); Self::pk_decode(&bytes_sized) } } -impl Eq for MLKEMPublicKey { } +impl Eq for MLKEMPublicKey {} impl PartialEq for MLKEMPublicKey { fn eq(&self, other: &Self) -> bool { @@ -208,21 +237,23 @@ impl Display for MLKEMPublicKey /// against the same public key, which causes the MLKEMPublicKey struct to take up more memory, but results /// in more efficient repeated encaps() operations. #[derive(Clone)] -pub struct MLKEMPublicKeyExpanded, const PK_LEN: usize> { +pub struct MLKEMPublicKeyExpanded< + const k: usize, + PK: MLKEMPublicKeyInternalTrait, + const PK_LEN: usize, +> { pub(crate) ek: PK, pub(crate) A_hat: Matrix, } impl, const PK_LEN: usize> -MLKEMPublicKeyInternalTrait for MLKEMPublicKeyExpanded { + MLKEMPublicKeyInternalTrait for MLKEMPublicKeyExpanded +{ fn new(t_hat: Vector, rho: [u8; 32]) -> Self { let ek = PK::new(t_hat, rho); let A_hat = ek.A_hat(); - Self { - ek, - A_hat, - } + Self { ek, A_hat } } fn t_hat(&self) -> &Vector { @@ -231,7 +262,8 @@ MLKEMPublicKeyInternalTrait for MLKEMPublicKeyExpanded } impl, const PK_LEN: usize> -KEMPublicKey for MLKEMPublicKeyExpanded { + KEMPublicKey for MLKEMPublicKeyExpanded +{ fn encode(&self) -> [u8; PK_LEN] { let mut pk = [0u8; PK_LEN]; self.encode_out(&mut pk); @@ -244,24 +276,30 @@ KEMPublicKey for MLKEMPublicKeyExpanded { } fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != PK_LEN { return Err(KEMError::DecodingError("Provided key bytes are the incorrect length")) } + if bytes.len() != PK_LEN { + return Err(KEMError::DecodingError("Provided key bytes are the incorrect length")); + } let bytes_sized: [u8; PK_LEN] = bytes[..PK_LEN].try_into().unwrap(); Self::pk_decode(&bytes_sized) } } -impl, const PK_LEN: usize> -PartialEq for MLKEMPublicKeyExpanded { +impl, const PK_LEN: usize> PartialEq + for MLKEMPublicKeyExpanded +{ fn eq(&self, other: &Self) -> bool { self.encode() == other.encode() } } -impl, const PK_LEN: usize> -Eq for MLKEMPublicKeyExpanded {} +impl, const PK_LEN: usize> Eq + for MLKEMPublicKeyExpanded +{ +} -impl, const PK_LEN: usize> -Debug for MLKEMPublicKeyExpanded { +impl, const PK_LEN: usize> Debug + for MLKEMPublicKeyExpanded +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let alg = match k { 2 => ML_KEM_512_NAME, @@ -274,8 +312,9 @@ Debug for MLKEMPublicKeyExpanded { } } -impl, const PK_LEN: usize> -Display for MLKEMPublicKeyExpanded { +impl, const PK_LEN: usize> Display + for MLKEMPublicKeyExpanded +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let alg = match k { 2 => ML_KEM_512_NAME, @@ -289,7 +328,8 @@ Display for MLKEMPublicKeyExpanded { } impl, const PK_LEN: usize> -MLKEMPublicKeyTrait for MLKEMPublicKeyExpanded { + MLKEMPublicKeyTrait for MLKEMPublicKeyExpanded +{ fn pk_decode(pk: &[u8; PK_LEN]) -> Result { let ek = PK::pk_decode(pk)?; let A_hat = ek.A_hat(); @@ -306,23 +346,17 @@ MLKEMPublicKeyTrait for MLKEMPublicKeyExpanded { } impl, const PK_LEN: usize> From<&PK> -for MLKEMPublicKeyExpanded { + for MLKEMPublicKeyExpanded +{ /// Fully expands the intermediate values needed for performing multiple encaps operations /// against the same public key, which causes the MLKEMPublicKey struct to take up fn from(ek: &PK) -> Self { let A_hat = ek.A_hat(); - Self { - ek: ek.clone(), - A_hat, - } + Self { ek: ek.clone(), A_hat } } } - - - - /// An ML-KEM private key. #[derive(Clone)] pub struct MLKEMPrivateKey< @@ -343,35 +377,35 @@ impl< PK: MLKEMPublicKeyInternalTrait, const SK_LEN: usize, const PK_LEN: usize, -> MLKEMPrivateKey { +> MLKEMPrivateKey +{ /// As described on Algorithm 16 line /// 3: dk ← (dkPKE ‖ ek ‖ H(ek) ‖ 𝑧) fn sk_encode_out(&self, out: &mut [u8; SK_LEN]) -> usize { - debug_assert_eq!(SK_LEN, /* dk_pke*/12*k*32 + /*ek*/PK_LEN + /*H(ek)*/32 + /*z*/32); + debug_assert_eq!(SK_LEN, /* dk_pke*/ 12*k*32 + /*ek*/PK_LEN + /*H(ek)*/32 + /*z*/32); let mut pos = 0usize; /* dk_pke */ // Alg 13; line 20: dkPKE ← ByteEncode12(𝐬) for i in 0..k { - out[i*POLY_BYTES .. (i+1)*POLY_BYTES].copy_from_slice(&byte_encode::<12, POLY_BYTES>( - &self.s_hat[i] - )); + out[i * POLY_BYTES..(i + 1) * POLY_BYTES] + .copy_from_slice(&byte_encode::<12, POLY_BYTES>(&self.s_hat[i])); } pos += k * POLY_BYTES; /* ek */ // Alg 13; line 19: ekPKE ← ByteEncode12(𝐭)‖𝜌 debug_assert_eq!(self.ek.encode().len(), PK_LEN); - out[pos .. pos + PK_LEN].copy_from_slice(&self.ek.encode()); + out[pos..pos + PK_LEN].copy_from_slice(&self.ek.encode()); pos += PK_LEN; /* H(ek) */ - out[pos .. pos + 32].copy_from_slice(&self.pk_hash); + out[pos..pos + 32].copy_from_slice(&self.pk_hash); pos += 32; /* z */ - out[pos .. pos + 32].copy_from_slice(&self.z); + out[pos..pos + 32].copy_from_slice(&self.z); debug_assert_eq!(pos + 32, SK_LEN); SK_LEN @@ -383,7 +417,9 @@ pub trait MLKEMPrivateKeyTrait< const k: usize, PK: MLKEMPublicKeyInternalTrait, const SK_LEN: usize, - const PK_LEN: usize> : KEMPrivateKey { + const PK_LEN: usize, +>: KEMPrivateKey +{ /// Get a ref to the seed, if there is one stored with this private key fn seed(&self) -> Option>; @@ -395,16 +431,16 @@ pub trait MLKEMPrivateKeyTrait< fn sk_decode(sk: &[u8; SK_LEN]) -> Result; } -pub(crate) trait MLKEMPrivateKeyInternalTrait, const SK_LEN: usize, const PK_LEN: usize> { +pub(crate) trait MLKEMPrivateKeyInternalTrait< + const k: usize, + PK: MLKEMPublicKeyTrait, + const SK_LEN: usize, + const PK_LEN: usize, +> +{ /// Not exposing a constructor publicly because you should have to get an instance either by /// running a keygen, or by decoding an existing key. - fn new( - s_hat: Vector, - ek: PK, - h: [u8; 32], - z: [u8; 32], - seed_d: Option<[u8; 32]>, - ) -> Self; + fn new(s_hat: Vector, ek: PK, h: [u8; 32], z: [u8; 32], seed_d: Option<[u8; 32]>) -> Self; /// Get a ref to s_hat fn s_hat(&self) -> &Vector; @@ -412,9 +448,13 @@ pub(crate) trait MLKEMPrivateKeyInternalTrait &[u8; 32]; } - -impl, const SK_LEN: usize, const PK_LEN: usize> - MLKEMPrivateKeyTrait for MLKEMPrivateKey { +impl< + const k: usize, + PK: MLKEMPublicKeyInternalTrait, + const SK_LEN: usize, + const PK_LEN: usize, +> MLKEMPrivateKeyTrait for MLKEMPrivateKey +{ fn seed(&self) -> Option> { if self.seed_d.is_none() { None @@ -424,12 +464,13 @@ impl, const SK_LEN: u tmp[32..].copy_from_slice(&self.z); let mut seed = KeyMaterial::<64>::from_bytes_as_type(&tmp, KeyType::Seed).unwrap(); seed.allow_hazardous_operations(); - seed.set_security_strength( match k { + seed.set_security_strength(match k { 2 => SecurityStrength::_128bit, 3 => SecurityStrength::_192bit, 4 => SecurityStrength::_256bit, _ => unreachable!("Invalid mlkem param set"), - }).unwrap(); + }) + .unwrap(); seed.drop_hazardous_operations(); Some(seed) } @@ -444,7 +485,7 @@ impl, const SK_LEN: u } fn sk_decode(sk: &[u8; SK_LEN]) -> Result { - debug_assert_eq!(SK_LEN, /* dk_pke*/12*k*32 + /*ek*/PK_LEN + /*H(ek)*/32 + /*z*/32); + debug_assert_eq!(SK_LEN, /* dk_pke*/ 12*k*32 + /*ek*/PK_LEN + /*H(ek)*/32 + /*z*/32); let mut pos = 0usize; @@ -453,7 +494,7 @@ impl, const SK_LEN: u // for (s_i, sk_chunk) in s_hat.0.iter_mut().zip(sk_chunks) { for i in 0..k { s_hat[i] = byte_decode::<12, POLY_BYTES>( - sk[i*POLY_BYTES .. (i+1)*POLY_BYTES].try_into().unwrap() + sk[i * POLY_BYTES..(i + 1) * POLY_BYTES].try_into().unwrap(), ); // FIPS 203 says: @@ -471,29 +512,36 @@ impl, const SK_LEN: u pos += k * POLY_BYTES; /* ek */ - let ek = PK::pk_decode(sk[pos .. pos + PK_LEN].try_into().unwrap())?; + let ek = PK::pk_decode(sk[pos..pos + PK_LEN].try_into().unwrap())?; pos += PK_LEN; /* H(ek) */ - let h_pk: [u8; 32] = sk[pos .. pos + 32].try_into().unwrap(); + let h_pk: [u8; 32] = sk[pos..pos + 32].try_into().unwrap(); pos += 32; // This satisfies the "Decapsulation input check #3) in FIPS 203 section 7.3. // We're doing it here on key load rather than as part of the decapsulation for performance - // because if you're doing multiple decapsulations, you only need to perform this check once. + // because if you're doing multiple decapsulations, you only need to perform this check once. if h_pk != ek.compute_hash() { - return Err(KEMError::ConsistencyCheckFailed("Corrupted private key: computed hash of ek != h_ek stored in private key")); + return Err(KEMError::ConsistencyCheckFailed( + "Corrupted private key: computed hash of ek != h_ek stored in private key", + )); } /* z */ - let z: [u8; 32] = sk[pos .. pos + 32].try_into().unwrap(); + let z: [u8; 32] = sk[pos..pos + 32].try_into().unwrap(); Ok(Self::new(s_hat, ek, h_pk, z, None)) } } -impl, const SK_LEN: usize, const PK_LEN: usize> - MLKEMPrivateKeyInternalTrait for MLKEMPrivateKey { +impl< + const k: usize, + PK: MLKEMPublicKeyInternalTrait, + const SK_LEN: usize, + const PK_LEN: usize, +> MLKEMPrivateKeyInternalTrait for MLKEMPrivateKey +{ /// Note to future maintainers: FIPS 203 section 7.3 requires that ek be hashed and compared to pk_hash. fn new( s_hat: Vector, @@ -502,22 +550,25 @@ impl, const SK_LEN: u z: [u8; 32], seed_d: Option<[u8; 32]>, ) -> Self { - Self { - s_hat, - ek, - pk_hash, - z, - seed_d: seed_d.clone(), - } + Self { s_hat, ek, pk_hash, z, seed_d: seed_d.clone() } } - fn s_hat(&self) -> &Vector { &self.s_hat } + fn s_hat(&self) -> &Vector { + &self.s_hat + } - fn z(&self) -> &[u8; 32] { &self.z } + fn z(&self) -> &[u8; 32] { + &self.z + } } -impl, const SK_LEN: usize, const PK_LEN: usize -> KEMPrivateKey for MLKEMPrivateKey { +impl< + const k: usize, + PK: MLKEMPublicKeyInternalTrait, + const SK_LEN: usize, + const PK_LEN: usize, +> KEMPrivateKey for MLKEMPrivateKey +{ fn encode(&self) -> [u8; SK_LEN] { let mut out = [0u8; SK_LEN]; self.encode_out(&mut out); @@ -530,18 +581,30 @@ impl, const SK_LEN: u } fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != SK_LEN { return Err(KEMError::DecodingError("Provided key bytes are the incorrect length")) } + if bytes.len() != SK_LEN { + return Err(KEMError::DecodingError("Provided key bytes are the incorrect length")); + } let bytes_sized: [u8; SK_LEN] = bytes[..SK_LEN].try_into().unwrap(); Self::sk_decode(&bytes_sized) } } -impl, const SK_LEN: usize, const PK_LEN: usize> - Eq for MLKEMPrivateKey {} +impl< + const k: usize, + PK: MLKEMPublicKeyInternalTrait, + const SK_LEN: usize, + const PK_LEN: usize, +> Eq for MLKEMPrivateKey +{ +} -impl, const SK_LEN: usize, const PK_LEN: usize> - PartialEq for MLKEMPrivateKey +impl< + const k: usize, + PK: MLKEMPublicKeyInternalTrait, + const SK_LEN: usize, + const PK_LEN: usize, +> PartialEq for MLKEMPrivateKey { fn eq(&self, other: &Self) -> bool { let self_encoded = self.encode(); @@ -550,20 +613,30 @@ impl, const SK_LEN: u } } -impl, const SK_LEN: usize, const PK_LEN: usize> -Secret for MLKEMPrivateKey {} +impl< + const k: usize, + PK: MLKEMPublicKeyInternalTrait, + const SK_LEN: usize, + const PK_LEN: usize, +> Secret for MLKEMPrivateKey +{ +} /// Debug impl mainly to prevent the secret key from being printed in logs. -impl, const SK_LEN: usize, const PK_LEN: usize> - fmt::Debug for MLKEMPrivateKey +impl< + const k: usize, + PK: MLKEMPublicKeyInternalTrait, + const SK_LEN: usize, + const PK_LEN: usize, +> fmt::Debug for MLKEMPrivateKey { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let alg = match k { - 2 => ML_KEM_512_NAME, - 3 => ML_KEM_768_NAME, - 4 => ML_KEM_1024_NAME, - _ => panic!("Unsupported key length"), - }; + let alg = match k { + 2 => ML_KEM_512_NAME, + 3 => ML_KEM_768_NAME, + 4 => ML_KEM_1024_NAME, + _ => panic!("Unsupported key length"), + }; write!( f, "MLKEMPrivateKey {{ alg: {}, pub_key_hash: {:x?}, has_seed: {} }}", @@ -575,8 +648,12 @@ impl, const SK_LEN: u } /// Display impl mainly to prevent the secret key from being printed in logs. -impl, const SK_LEN: usize, const PK_LEN: usize> - Display for MLKEMPrivateKey +impl< + const k: usize, + PK: MLKEMPublicKeyInternalTrait, + const SK_LEN: usize, + const PK_LEN: usize, +> Display for MLKEMPrivateKey { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let alg = match k { @@ -596,19 +673,23 @@ impl, const SK_LEN: u } /// Zeroizing drop -impl, const SK_LEN: usize, const PK_LEN: usize> -Drop for MLKEMPrivateKey +impl< + const k: usize, + PK: MLKEMPublicKeyInternalTrait, + const SK_LEN: usize, + const PK_LEN: usize, +> Drop for MLKEMPrivateKey { fn drop(&mut self) { // s_hat, has its own zeroizing drop self.pk_hash.fill(0u8); self.z.fill(0u8); - if self.seed_d.is_some() { self.seed_d.as_mut().unwrap().fill(0u8); } + if self.seed_d.is_some() { + self.seed_d.as_mut().unwrap().fill(0u8); + } } } - - /// A fully expanded ML-KEM private key that includes the intermediate values needed for performing /// multiple decaps operations with the same private key, which causes the private key struct to /// take up more memory, but results in more efficient repeated decaps() operations. @@ -616,43 +697,43 @@ Drop for MLKEMPrivateKey pub struct MLKEMPrivateKeyExpanded< const k: usize, PK: MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const SK_LEN: usize, - const PK_LEN: usize + const PK_LEN: usize, > { _phantom: core::marker::PhantomData, pub(crate) dk: SK, - pub(crate) A_hat: Matrix, + pub(crate) A_hat: Matrix, } impl< const k: usize, PK: MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const SK_LEN: usize, - const PK_LEN: usize -> From<&SK> -for MLKEMPrivateKeyExpanded { + const PK_LEN: usize, +> From<&SK> for MLKEMPrivateKeyExpanded +{ /// Fully expands the intermediate values needed for performing multiple encaps operations /// against the same public key, which causes the MLKEMPublicKey struct to take up fn from(dk: &SK) -> Self { let A_hat = dk.pk().A_hat(); - Self { - _phantom: core::marker::PhantomData, - dk: dk.clone(), - A_hat, - } + Self { _phantom: core::marker::PhantomData, dk: dk.clone(), A_hat } } } impl< const k: usize, PK: MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const SK_LEN: usize, - const PK_LEN: usize -> KEMPrivateKey for MLKEMPrivateKeyExpanded { + const PK_LEN: usize, +> KEMPrivateKey for MLKEMPrivateKeyExpanded +{ fn encode(&self) -> [u8; SK_LEN] { self.dk.encode() } @@ -669,10 +750,12 @@ impl< impl< const k: usize, PK: MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const SK_LEN: usize, - const PK_LEN: usize -> PartialEq for MLKEMPrivateKeyExpanded { + const PK_LEN: usize, +> PartialEq for MLKEMPrivateKeyExpanded +{ fn eq(&self, other: &Self) -> bool { self.dk.eq(&other.dk) } @@ -681,26 +764,34 @@ impl< impl< const k: usize, PK: MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const SK_LEN: usize, - const PK_LEN: usize -> Eq for MLKEMPrivateKeyExpanded {} + const PK_LEN: usize, +> Eq for MLKEMPrivateKeyExpanded +{ +} impl< const k: usize, PK: MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const SK_LEN: usize, - const PK_LEN: usize -> Secret for MLKEMPrivateKeyExpanded {} + const PK_LEN: usize, +> Secret for MLKEMPrivateKeyExpanded +{ +} impl< const k: usize, PK: MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const SK_LEN: usize, - const PK_LEN: usize -> Drop for MLKEMPrivateKeyExpanded { + const PK_LEN: usize, +> Drop for MLKEMPrivateKeyExpanded +{ fn drop(&mut self) { // Nothing to do since self.sk already impls zeroizing Drop } @@ -709,10 +800,12 @@ impl< impl< const k: usize, PK: MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const SK_LEN: usize, - const PK_LEN: usize -> Debug for MLKEMPrivateKeyExpanded { + const PK_LEN: usize, +> Debug for MLKEMPrivateKeyExpanded +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let alg = match k { 2 => ML_KEM_512_NAME, @@ -733,10 +826,12 @@ impl< impl< const k: usize, PK: MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const SK_LEN: usize, - const PK_LEN: usize -> Display for MLKEMPrivateKeyExpanded { + const PK_LEN: usize, +> Display for MLKEMPrivateKeyExpanded +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let alg = match k { 2 => ML_KEM_512_NAME, @@ -757,10 +852,13 @@ impl< impl< const k: usize, PK: MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const SK_LEN: usize, - const PK_LEN: usize -> MLKEMPrivateKeyTrait for MLKEMPrivateKeyExpanded { + const PK_LEN: usize, +> MLKEMPrivateKeyTrait + for MLKEMPrivateKeyExpanded +{ fn seed(&self) -> Option> { self.dk.seed() } @@ -777,10 +875,6 @@ impl< let dk = SK::sk_decode(sk)?; let A_hat = dk.pk().A_hat(); - Ok(Self { - _phantom: core::marker::PhantomData, - dk: dk.clone(), - A_hat, - }) + Ok(Self { _phantom: core::marker::PhantomData, dk: dk.clone(), A_hat }) } } diff --git a/crypto/mlkem/src/polynomial.rs b/crypto/mlkem/src/polynomial.rs index ae518fc..1d7642c 100644 --- a/crypto/mlkem/src/polynomial.rs +++ b/crypto/mlkem/src/polynomial.rs @@ -4,16 +4,20 @@ use core::fmt; use core::fmt::{Debug, Display, Formatter}; use core::ops::{Index, IndexMut}; -use bouncycastle_core::traits::Secret; -use crate::aux_functions::{barrett_reduce, cond_sub_q, montgomery_reduce, mul_mont, ntt_base_mult, ZETAS, ZETAS_INV}; +use crate::aux_functions::{ + ZETAS, ZETAS_INV, barrett_reduce, cond_sub_q, montgomery_reduce, mul_mont, ntt_base_mult, +}; use crate::mlkem::{N, q}; +use bouncycastle_core::traits::Secret; /// A polynomial over the ML-KEM ring. /// Dev note: this doesn't strictly need to be pub ... ie there's no good reason for a caller to use this class directly, /// but in order to test the Debug and Display traits, you need STD, so those can't be tested from inline tests in this file /// and the real unit tests are in a different crate, so here we are. #[derive(Clone)] -pub struct Polynomial{ pub(crate) coeffs: [i16; N] } +pub struct Polynomial { + pub(crate) coeffs: [i16; N], +} /// Convenience function to avoid ".0" all over the place. impl Index for Polynomial { @@ -40,7 +44,7 @@ impl Polynomial { pub(crate) fn from_msg(m: [u8; 32]) -> Self { let mut w = Polynomial::new(); - for (i, b) in m.iter().enumerate().take(N/8) { + for (i, b) in m.iter().enumerate().take(N / 8) { for j in 0..8 { let mask = -(((*b >> j) & 1) as i16); w[8 * i + j] = mask /*as i32*/ & ((q + 1) / 2); @@ -52,8 +56,7 @@ impl Polynomial { /// Convert a Polynomial back into a message m pub(crate) fn to_msg(mut self) -> [u8; 32] { - - const LOWER: i32 = q as i32 >> 2; // 832 + const LOWER: i32 = q as i32 >> 2; // 832 const UPPER: i32 = q as i32 - LOWER; // 2497 let mut msg = [0u8; 32]; @@ -63,7 +66,7 @@ impl Polynomial { self.cond_sub_q(); // for (i, item) in msg.iter_mut().enumerate().take(N/8) { - for i in 0 .. N/8 { + for i in 0..N / 8 { for j in 0..8 { let c_j = self[8 * i + j] as i32; let t = (((LOWER - c_j) & (c_j - UPPER)) >> 31) & 0x0000000000000001; @@ -131,12 +134,12 @@ impl Polynomial { // s.cond_sub_q(); match dv { - 4 => { // MLKEM512 and MLKEM768 - for i in 0..N/8 { + 4 => { + // MLKEM512 and MLKEM768 + for i in 0..N / 8 { // fill the temp array t for (j, item) in t.iter_mut().enumerate() { - *item = ((((self[8 * i + j] as i32) << 4) + (q as i32 /2)) - / (q as i32) + *item = ((((self[8 * i + j] as i32) << 4) + (q as i32 / 2)) / (q as i32) & 15) as u8; } @@ -146,13 +149,13 @@ impl Polynomial { out[idx + 3] = t[6] | (t[7] << 4); idx += 4; } - }, - 5 => { // MLKEM1024 - for i in 0..N/8 { + } + 5 => { + // MLKEM1024 + for i in 0..N / 8 { // fill the temp array t for (j, item) in t.iter_mut().enumerate() { - *item = (((((self[8 * i + j] as i32) << 5) + (q as i32 /2)) - / (q as i32)) + *item = (((((self[8 * i + j] as i32) << 5) + (q as i32 / 2)) / (q as i32)) & 31) as u8; } @@ -163,7 +166,7 @@ impl Polynomial { out[idx + 4] = (t[6] >> 2) | (t[7] << 3); idx += 5; } - }, + } _ => unreachable!(), }; } @@ -185,38 +188,34 @@ impl Polynomial { // if self.m_engine.poly_compressed_bytes() == 128 { match dv { - 4 => { // MLKEM512 and MLKEM768 - for i in 0..N/2 { + 4 => { + // MLKEM512 and MLKEM768 + for i in 0..N / 2 { v[2 * i] = - (((((compressed_v[idx] & 15) as i16) as i32 * (q as i32)) + 8) >> 4) - as i16; + (((((compressed_v[idx] & 15) as i16) as i32 * (q as i32)) + 8) >> 4) as i16; v[2 * i + 1] = - (((((compressed_v[idx] >> 4) as i16) as i32 * (q as i32)) + 8) >> 4) - as i16; + (((((compressed_v[idx] >> 4) as i16) as i32 * (q as i32)) + 8) >> 4) as i16; idx += 1; } - }, - 5 => { // MLKEM1024 + } + 5 => { + // MLKEM1024 let mut t = [0u8; 8]; - for i in 0..N/8 { + for i in 0..N / 8 { t[0] = compressed_v[idx]; - t[1] = - (compressed_v[idx] >> 5) | (compressed_v[idx + 1] << 3); + t[1] = (compressed_v[idx] >> 5) | (compressed_v[idx + 1] << 3); t[2] = compressed_v[idx + 1] >> 2; - t[3] = (compressed_v[idx + 1] >> 7) - | (compressed_v[idx + 2] << 1); - t[4] = (compressed_v[idx + 2] >> 4) - | (compressed_v[idx + 3] << 4); + t[3] = (compressed_v[idx + 1] >> 7) | (compressed_v[idx + 2] << 1); + t[4] = (compressed_v[idx + 2] >> 4) | (compressed_v[idx + 3] << 4); t[5] = compressed_v[idx + 3] >> 1; - t[6] = (compressed_v[idx + 3] >> 6) - | (compressed_v[idx + 4] << 2); + t[6] = (compressed_v[idx + 3] >> 6) | (compressed_v[idx + 4] << 2); t[7] = compressed_v[idx + 4] >> 3; idx += 5; for (j, item) in t.iter_mut().enumerate() { v[8 * i + j] = (((*item & 31) as i32 * (q as i32) + 16) >> 5) as i16; } } - }, + } _ => unreachable!(), } @@ -300,7 +299,7 @@ impl Polynomial { pub(crate) fn base_mult_montgomery(a: &Polynomial, b: &Polynomial) -> Polynomial { let mut r = Polynomial::new(); - for i in 0..(N/4) { + for i in 0..(N / 4) { ntt_base_mult( &mut r.coeffs, 4 * i, diff --git a/crypto/mlkem/tests/mlkem_key_tests.rs b/crypto/mlkem/tests/mlkem_key_tests.rs index 830196f..69d24e3 100644 --- a/crypto/mlkem/tests/mlkem_key_tests.rs +++ b/crypto/mlkem/tests/mlkem_key_tests.rs @@ -2,17 +2,22 @@ mod mlkem_key_tests { use bouncycastle_core::errors::KEMError; use bouncycastle_core::key_material::{KeyMaterial512, KeyType}; - use bouncycastle_core::traits::{KEMPrivateKey, KEMPublicKey, KEM}; - use bouncycastle_mlkem::{MLKEMPrivateKeyTrait, MLKEMPublicKeyTrait, MLKEMTrait}; - use bouncycastle_mlkem::{MLKEM512, MLKEM768, MLKEM1024}; - use bouncycastle_mlkem::{MLKEM512PrivateKey, MLKEM512PublicKey, MLKEM768PrivateKey, MLKEM768PublicKey, MLKEM1024PrivateKey, MLKEM1024PublicKey}; - use bouncycastle_mlkem::{MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM512_CT_LEN, MLKEM768_PK_LEN, MLKEM768_SK_LEN, MLKEM768_CT_LEN, MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, MLKEM1024_CT_LEN, MLKEM_SS_LEN}; + use bouncycastle_core::traits::{KEM, KEMPrivateKey, KEMPublicKey}; use bouncycastle_hex as hex; - + use bouncycastle_mlkem::{ + MLKEM_SS_LEN, MLKEM512_CT_LEN, MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM768_CT_LEN, + MLKEM768_PK_LEN, MLKEM768_SK_LEN, MLKEM1024_CT_LEN, MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, + }; + use bouncycastle_mlkem::{MLKEM512, MLKEM768, MLKEM1024}; + use bouncycastle_mlkem::{ + MLKEM512PrivateKey, MLKEM512PublicKey, MLKEM768PrivateKey, MLKEM768PublicKey, + MLKEM1024PrivateKey, MLKEM1024PublicKey, + }; + use bouncycastle_mlkem::{MLKEMPrivateKeyTrait, MLKEMPublicKeyTrait, MLKEMTrait}; #[test] fn core_framework_tests() { - use bouncycastle_core_test_framework::kem::{TestFrameworkKEMKeys}; + use bouncycastle_core_test_framework::kem::TestFrameworkKEMKeys; let tf = TestFrameworkKEMKeys::new(); tf.test_keys::(); @@ -22,7 +27,6 @@ mod mlkem_key_tests { #[test] fn pk_from_sk() { - /* MLDSA44 */ let expected_sk_bytes: [u8; MLKEM512_SK_LEN] = hex::decode("70554fd436344f2785b1b3b1bac184b6679003336c26f15a7de878c4825c6be03f3c4a480f75b7486aad31d3a00518623fd207ab528dd62721495835ae0062c367b74a71baf10aad0e8a2902076be31348beb15ccc0957cdebb4aff226756bbc601b6568ab784acbaeb34702f0f86a26202118b22b23f83558776c79c14dba983379c803e0dcc3160a11757030e69c6919798d81eb698a9a4483a99e5a5cb2c31c9a661799f3cc89c790706ea041629045d42a83aed88860e394c69187e2105d28cc14ec393592d67dd00aa43fe8b4eae4414002866b5c713c6a8d7d16cf78b819d6f12e9e5a74233908f0b15e3c4ba8329c5cdda55c84928e3aa8063e5aa9676403f91735b11010c7f593091364dc86445bc804840a9a21724212469f8a7b0ce0ac698eb86cad39a7f4824d9a5163aac21ee6808b053c8a3facb0b6744b5262bbcb26a43f664c8732b64cfc7acf099605f41c796060976ac433833fe00343fb1828300a424741116e4b45bb276ea81129a0db4c6e60bce611101e8c625474925e0222679308a3e7708d1972a7b423eb232851c36d2ed53d3ed3bb7500637061a5dc2292fa1c466c07354683328bec2c1ed2cb5c99b78eca0969038cf7c34dd118724e31cae086206b34302b520f5d177aded5b3cce02acce808ea26bcc072625fdb93f17458a5fc1d4da394380a1f57e9cc66109438a075f0d2813fcc4a199cc76db3823f270b0061594192940411a37ffbafae2c150165cec5c6bf73c595fb92cd15312607da070778652bd9944bc48bc7d1a534338bad0bad6656c5d502ce7850ab1587244eeb58f439ab5e08574a718c8aac3d77c798bba1542733be73448f23fb70c0e5353a27c88322c5218493afbb38086434d6d60a56ba887dd498c3ab26a0870993815aa6a40975f218adca1582d64ffc8652fbb3a9a6fbc304f91945fa4aaef2878fd715df70113d2379f44886f812c83ff2b719a69e1ec74ae4b15accd3aed5a53ce76a7b0982471633b973cb40a1a0015d0a424fa11a479c023017436d2a2900e993eb5a0a067400c7f4aadf201fc4fa31264a63bae95cc8d65c3995815e597d104355cf29aa5333c93251869d5bcdbe487124f602b8b6a66c16c4761648ad765cf5d8006b515e905a7f0ac076b0c62efa328153e7ca5701699f1305f1e6bc6f90b0e49b693512b6ce992a8b8016ddfc1a662c7e3f9619cbd869dd771af30896ccd5918ac6cb77466c5e779996d67ff9aabc97503f2c7b7e2d000d86450fb1807ca4cabda465825a31c789a1b7a491ab3872765d320d0b71920fa213c94093416b83b8124e69f65e62cb5000dcc37aa9a0fff73970c4772f357d24189ca6f5305568c0e2376a3762a68c605e563c5d209572e0fc7532ca294729535567b5fc413c5e8792d2464536cc808f98add74664f141566f9016a90a541829a98a0464ce41a8bb44c2d4fa3c2c209460728ef14a1a7c4c9b98d12203b4cc3529160a9ab2d7838f7ff6b53ae05aa31a7d646b7afa6c45932526a3c3755619be994c211c2a31c05b3447836cb2150be1829dae6b04c5535cff546e392ba797411720f924f490a5ac5495f21356d550b782a64c1688b6b655bcc7842197a434c2f6563b5b7f09a78bcc488232783561d16f4cbab6755400050781570c66604b817ad1252294736e8b01861a4b5a74519b8b6fe51489a5072392e587626c713776575d33806a1c8e2732af97c2680f51666331c4eb8bbc0431c4f96832daf1b3c45528fba153f6c78b1c198702947ccd337727a46fb53ba11de5cb4191346859516cb6ad72400f3cf209b236aef35a580ac87eb3e30fafd66973ca8a7dd2675af41f7a17b61433cd1af80f7708869f665488497980b1ac10a0cdcb636a00ed8681b35e429124ca80350725b85f83a5eac3a4a3cc1600903e65293560b9b336e5af0d529dac1a048119302cb7a9bcc110b94851bf02117f199dc485a852b7473f09b831a6831d5b54c0b790d225cf6bb92d9462a26cdb33dda5123c7aaf0e26a0b83655eea28bf3a8074725018fd6bae4b601cf61baab71a7a3d35197a343e74b4a272c125d540896426d85b7958d3b38a6ba987ec37225c7b44cdb12dde4539b4ab082363683f04bf7a09cc5c41dfe830a1b162e0b324334362f084a14467723344badd000f8d8c537c48f998f05307cebd1ede0b81c3bc59a065a1b6d63b26c82f101ff648063b376e2bb6c5b7455f655a50c2feadade150efa0e0e6f365aea202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f").unwrap() .try_into().unwrap(); @@ -35,7 +39,6 @@ mod mlkem_key_tests { assert_eq!(sk_bytes.len(), expected_sk_bytes.len()); assert_eq!(sk_bytes, expected_sk_bytes.as_slice()); - // Decode and re-encode the pk, make sure you get the same thing let decoded_pk = MLKEM512PublicKey::from_bytes(&expected_pk_bytes).unwrap(); let pk_bytes = decoded_pk.encode(); @@ -54,34 +57,41 @@ mod mlkem_key_tests { // 3) does it reject a private key if the H(ek) is wrong? let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (pk, sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); // generation of KAT // let h_ek = pk.compute_hash(); // println!("H(ek) for public key: {}", hex::encode(h_ek)); - let expected_h_ek: [u8; 32] = hex::decode("82f101ff648063b376e2bb6c5b7455f655a50c2feadade150efa0e0e6f365aea").unwrap().try_into().unwrap(); + let expected_h_ek: [u8; 32] = + hex::decode("82f101ff648063b376e2bb6c5b7455f655a50c2feadade150efa0e0e6f365aea") + .unwrap() + .try_into() + .unwrap(); assert_eq!(pk.compute_hash(), expected_h_ek); assert_eq!(sk.pk_hash(), &expected_h_ek); - // 3) does it reject a private key if the H(ek) is wrong? let mut sk_bytes: [u8; MLKEM512_SK_LEN] = sk.encode(); // h is: // dk[768𝑘 + 32 ∶ 768𝑘 + 64] // k for MLKEM512 is 2 - sk_bytes[768 * 2 .. (768 * 2) + 32].fill(1); + sk_bytes[768 * 2..(768 * 2) + 32].fill(1); // now try loading it match MLKEM512PrivateKey::from_bytes(&sk_bytes) { Ok(_) => panic!("Expected error loading private key with invalid H(ek)"), - Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ }, + Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ } _ => panic!("Unexpected error loading private key with invalid H(ek)"), } } @@ -89,12 +99,16 @@ mod mlkem_key_tests { #[test] fn encode_decode() { let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (pk1, sk1) = MLKEM512::keygen_from_seed(&seed).unwrap(); let pk1_bytes = pk1.encode(); @@ -113,19 +127,22 @@ mod mlkem_key_tests { #[test] fn seed() { let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (_pk, sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); assert!(sk.seed().is_some()); assert_eq!(sk.seed().as_ref().unwrap(), &seed); - - + // now load a key from bytes so that it doesn't have a seed let sk_bytes = sk.encode(); let sk2 = MLKEM512PrivateKey::from_bytes(&sk_bytes).unwrap(); @@ -140,19 +157,18 @@ mod mlkem_key_tests { // so let's test these conditions in both private key s_hat and public key t_hat match MLKEM512PrivateKey::from_bytes(&[255u8; MLKEM512_SK_LEN]) { - Err(KEMError::DecodingError(_)) => { /* good */ }, - _ => panic!("Expected malformed key to be rejected") + Err(KEMError::DecodingError(_)) => { /* good */ } + _ => panic!("Expected malformed key to be rejected"), }; match MLKEM512PublicKey::from_bytes(&[255u8; MLKEM512_PK_LEN]) { - Err(KEMError::DecodingError(_)) => { /* good */ }, - _ => panic!("Expected malformed key to be rejected") + Err(KEMError::DecodingError(_)) => { /* good */ } + _ => panic!("Expected malformed key to be rejected"), }; } #[test] fn test_eq() { - // MLKEM512 let (pk, sk) = MLKEM512::keygen().unwrap(); @@ -175,7 +191,6 @@ mod mlkem_key_tests { bytes[17] ^= 0x01; assert_ne!(sk, MLKEM512PrivateKey::from_bytes(&bytes).unwrap()); - // MLKEM768 let (pk, sk) = MLKEM768::keygen().unwrap(); @@ -198,7 +213,6 @@ mod mlkem_key_tests { bytes[17] ^= 0x01; assert_ne!(sk, MLKEM768PrivateKey::from_bytes(&bytes).unwrap()); - // MLKEM1024 let (pk, sk) = MLKEM1024::keygen().unwrap(); @@ -229,7 +243,6 @@ mod mlkem_key_tests { let (pk768, sk768) = MLKEM768::keygen().unwrap(); let (pk1024, sk1024) = MLKEM1024::keygen().unwrap(); - /*** MLDSAPublicKey ***/ // fmt @@ -252,8 +265,6 @@ mod mlkem_key_tests { let pk_str = format!("{:?}", pk1024); assert!(pk_str.contains("MLKEMPublicKey { alg: ML-KEM-1024, pub_key_hash:")); - - /*** MLDSAPrivateKey ***/ // fmt let sk_str = format!("{}", sk512); @@ -279,9 +290,9 @@ mod mlkem_key_tests { /// Tests that no private data is displayed #[test] fn test_display_expanded_key() { - use bouncycastle_mlkem::{MLKEM512PublicKeyExpanded, MLKEM512PrivateKeyExpanded}; - use bouncycastle_mlkem::{MLKEM768PublicKeyExpanded, MLKEM768PrivateKeyExpanded}; - use bouncycastle_mlkem::{MLKEM1024PublicKeyExpanded, MLKEM1024PrivateKeyExpanded}; + use bouncycastle_mlkem::{MLKEM512PrivateKeyExpanded, MLKEM512PublicKeyExpanded}; + use bouncycastle_mlkem::{MLKEM768PrivateKeyExpanded, MLKEM768PublicKeyExpanded}; + use bouncycastle_mlkem::{MLKEM1024PrivateKeyExpanded, MLKEM1024PublicKeyExpanded}; let (pk512, sk512) = MLKEM512::keygen().unwrap(); let pk512 = MLKEM512PublicKeyExpanded::from(&pk512); @@ -295,7 +306,6 @@ mod mlkem_key_tests { let pk1024 = MLKEM1024PublicKeyExpanded::from(&pk1024); let sk1024 = MLKEM1024PrivateKeyExpanded::from(&sk1024); - /*** MLDSAPublicKey ***/ // fmt @@ -318,8 +328,6 @@ mod mlkem_key_tests { let pk_str = format!("{:?}", pk1024); assert!(pk_str.contains("MLKEMPublicKeyExpanded { alg: ML-KEM-1024, pub_key_hash:")); - - /*** MLDSAPrivateKey ***/ // fmt let sk_str = format!("{}", sk512); diff --git a/crypto/mlkem/tests/mlkem_tests.rs b/crypto/mlkem/tests/mlkem_tests.rs index 71137fe..c24abd2 100644 --- a/crypto/mlkem/tests/mlkem_tests.rs +++ b/crypto/mlkem/tests/mlkem_tests.rs @@ -2,13 +2,19 @@ #[cfg(test)] mod mlkem_tests { use bouncycastle_core::errors::KEMError; - use bouncycastle_core::key_material::{KeyMaterialTrait, KeyMaterial512, KeyType}; - use bouncycastle_core::traits::{KEMPrivateKey, KEMPublicKey, SecurityStrength, KEM, XOF}; - use bouncycastle_mlkem::{MLKEM512, MLKEM768, MLKEM1024, MLKEM_RND_LEN, Polynomial}; - use bouncycastle_mlkem::{MLKEM512PrivateKey, MLKEM512PublicKey, MLKEM768PrivateKey, MLKEM768PublicKey, MLKEM1024PrivateKey, MLKEM1024PublicKey}; - use bouncycastle_mlkem::{MLKEMPrivateKeyTrait, MLKEMTrait}; - use bouncycastle_mlkem::{MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM768_PK_LEN, MLKEM768_SK_LEN, MLKEM768_CT_LEN, MLKEM512_CT_LEN, MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, MLKEM1024_CT_LEN, MLKEM_SS_LEN}; + use bouncycastle_core::key_material::{KeyMaterial512, KeyMaterialTrait, KeyType}; + use bouncycastle_core::traits::{KEM, KEMPrivateKey, KEMPublicKey, SecurityStrength, XOF}; use bouncycastle_hex as hex; + use bouncycastle_mlkem::{MLKEM_RND_LEN, MLKEM512, MLKEM768, MLKEM1024, Polynomial}; + use bouncycastle_mlkem::{ + MLKEM_SS_LEN, MLKEM512_CT_LEN, MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM768_CT_LEN, + MLKEM768_PK_LEN, MLKEM768_SK_LEN, MLKEM1024_CT_LEN, MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, + }; + use bouncycastle_mlkem::{ + MLKEM512PrivateKey, MLKEM512PublicKey, MLKEM768PrivateKey, MLKEM768PublicKey, + MLKEM1024PrivateKey, MLKEM1024PublicKey, + }; + use bouncycastle_mlkem::{MLKEMPrivateKeyTrait, MLKEMTrait}; use bouncycastle_sha3::SHAKE256; // #[test] @@ -31,7 +37,7 @@ mod mlkem_tests { #[test] fn core_framework_tests() { - use bouncycastle_core_test_framework::kem::{TestFrameworkKEM}; + use bouncycastle_core_test_framework::kem::TestFrameworkKEM; let tf = TestFrameworkKEM::new(false, true); @@ -57,13 +63,16 @@ mod mlkem_tests { fn rfc9935_keygen() { // note: same seed for MLKEM512, MLKEM768, MLKEM1024 let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); - + ) + .unwrap(); /* MLKEM512 */ let expected_sk_bytes: [u8; MLKEM512_SK_LEN] = hex::decode("70554fd436344f2785b1b3b1bac184b6679003336c26f15a7de878c4825c6be03f3c4a480f75b7486aad31d3a00518623fd207ab528dd62721495835ae0062c367b74a71baf10aad0e8a2902076be31348beb15ccc0957cdebb4aff226756bbc601b6568ab784acbaeb34702f0f86a26202118b22b23f83558776c79c14dba983379c803e0dcc3160a11757030e69c6919798d81eb698a9a4483a99e5a5cb2c31c9a661799f3cc89c790706ea041629045d42a83aed88860e394c69187e2105d28cc14ec393592d67dd00aa43fe8b4eae4414002866b5c713c6a8d7d16cf78b819d6f12e9e5a74233908f0b15e3c4ba8329c5cdda55c84928e3aa8063e5aa9676403f91735b11010c7f593091364dc86445bc804840a9a21724212469f8a7b0ce0ac698eb86cad39a7f4824d9a5163aac21ee6808b053c8a3facb0b6744b5262bbcb26a43f664c8732b64cfc7acf099605f41c796060976ac433833fe00343fb1828300a424741116e4b45bb276ea81129a0db4c6e60bce611101e8c625474925e0222679308a3e7708d1972a7b423eb232851c36d2ed53d3ed3bb7500637061a5dc2292fa1c466c07354683328bec2c1ed2cb5c99b78eca0969038cf7c34dd118724e31cae086206b34302b520f5d177aded5b3cce02acce808ea26bcc072625fdb93f17458a5fc1d4da394380a1f57e9cc66109438a075f0d2813fcc4a199cc76db3823f270b0061594192940411a37ffbafae2c150165cec5c6bf73c595fb92cd15312607da070778652bd9944bc48bc7d1a534338bad0bad6656c5d502ce7850ab1587244eeb58f439ab5e08574a718c8aac3d77c798bba1542733be73448f23fb70c0e5353a27c88322c5218493afbb38086434d6d60a56ba887dd498c3ab26a0870993815aa6a40975f218adca1582d64ffc8652fbb3a9a6fbc304f91945fa4aaef2878fd715df70113d2379f44886f812c83ff2b719a69e1ec74ae4b15accd3aed5a53ce76a7b0982471633b973cb40a1a0015d0a424fa11a479c023017436d2a2900e993eb5a0a067400c7f4aadf201fc4fa31264a63bae95cc8d65c3995815e597d104355cf29aa5333c93251869d5bcdbe487124f602b8b6a66c16c4761648ad765cf5d8006b515e905a7f0ac076b0c62efa328153e7ca5701699f1305f1e6bc6f90b0e49b693512b6ce992a8b8016ddfc1a662c7e3f9619cbd869dd771af30896ccd5918ac6cb77466c5e779996d67ff9aabc97503f2c7b7e2d000d86450fb1807ca4cabda465825a31c789a1b7a491ab3872765d320d0b71920fa213c94093416b83b8124e69f65e62cb5000dcc37aa9a0fff73970c4772f357d24189ca6f5305568c0e2376a3762a68c605e563c5d209572e0fc7532ca294729535567b5fc413c5e8792d2464536cc808f98add74664f141566f9016a90a541829a98a0464ce41a8bb44c2d4fa3c2c209460728ef14a1a7c4c9b98d12203b4cc3529160a9ab2d7838f7ff6b53ae05aa31a7d646b7afa6c45932526a3c3755619be994c211c2a31c05b3447836cb2150be1829dae6b04c5535cff546e392ba797411720f924f490a5ac5495f21356d550b782a64c1688b6b655bcc7842197a434c2f6563b5b7f09a78bcc488232783561d16f4cbab6755400050781570c66604b817ad1252294736e8b01861a4b5a74519b8b6fe51489a5072392e587626c713776575d33806a1c8e2732af97c2680f51666331c4eb8bbc0431c4f96832daf1b3c45528fba153f6c78b1c198702947ccd337727a46fb53ba11de5cb4191346859516cb6ad72400f3cf209b236aef35a580ac87eb3e30fafd66973ca8a7dd2675af41f7a17b61433cd1af80f7708869f665488497980b1ac10a0cdcb636a00ed8681b35e429124ca80350725b85f83a5eac3a4a3cc1600903e65293560b9b336e5af0d529dac1a048119302cb7a9bcc110b94851bf02117f199dc485a852b7473f09b831a6831d5b54c0b790d225cf6bb92d9462a26cdb33dda5123c7aaf0e26a0b83655eea28bf3a8074725018fd6bae4b601cf61baab71a7a3d35197a343e74b4a272c125d540896426d85b7958d3b38a6ba987ec37225c7b44cdb12dde4539b4ab082363683f04bf7a09cc5c41dfe830a1b162e0b324334362f084a14467723344badd000f8d8c537c48f998f05307cebd1ede0b81c3bc59a065a1b6d63b26c82f101ff648063b376e2bb6c5b7455f655a50c2feadade150efa0e0e6f365aea202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f").unwrap() @@ -103,11 +112,10 @@ mod mlkem_tests { let mut wrong_sk_bytes = sk_bytes.clone(); wrong_sk_bytes[4..8].copy_from_slice(&[0u8, 0u8, 0u8, 0u8]); match MLKEM512::keygen_from_seed_and_encoded(&seed, &wrong_sk_bytes) { - Err(KEMError::KeyGenError(_)) => {/* good */ }, + Err(KEMError::KeyGenError(_)) => { /* good */ } _ => panic!("sk_from_seed_and_encoded should fail with InvalidSignature"), } - /* MLKEM768 */ let expected_sk_bytes: [u8; MLKEM768_SK_LEN] = hex::decode("27d2a77f33756f61208ef113abe82595873d4abc730e5b5d679529bf6a4ceb6383427231a8612f41550515acba52e48ead8b942833bbe6865d13d14a79d2c5c3e07f0a056d8de7aadfcaba058c493c80b37cab8c562753bb3ba6b6ec8297f885eaa7540d530015a84406e55b1366b577e236ce58a26d8a1eb5a44d542323c2167d9bf4a47f985699ca05bae43b8dec617f02380a3890afd4b8c7ec7ede26553a025f3ce5bc5d7a62130304235cb1ad4836b566b5b863bd9bdb45a2844a7047b6c8d383e448525e040b4dc8a2b48c6c37c96d62d43f3fd88e2881c40a205c9e248f652b592781a779f86880f2a147b67863f391cc1a5a908c0095e07212291e2ef8a36eb9a9c0c6073225b34703a4af049382c47573da68fde9245ad444e31b1fbdb521f1f61f37bc0cef292067e670d28a1ffd904f6f1190a996918a13037a6cabf3c373bf8296cd37ab33ba7746809cc3f8ade1b3639bd57bfcc69650aaaf1de198fc4c0463299e52c461780cc428fc5d04a5c51850cba6c2a5274340675793dda09be44c29e6395c65f85d2a0a7c6df411e6911b1f2cb6c351cd2e875f51b638be776097e93e2f2b2f83da0beef4aa85ba9e763ab64502a0ca5222e9eab5b3b7088ed52060e8c8269b943a71ab0ae1c5b1b687d2e019cf8036bcf9bf6e7bac3aaa36e41660faa4540f2648cd93a189ec5c2dea70bacaaa4ffc906f90810ea1b67bf24f2c78cf6ba881aaea61c0652bff95b1bae4426d1773b9cc2ca82c21e38c636e3b1c523244986b0be8a83f5dd5cf2d54762fb3c5ebf59b8e885302b1ce47033edf760f4e029be40b6d566b19dd758acd5c7412878131244f90172c53f26663c21d905301d48baf91c917cc7779e9d8802cc10d89a3705099a2ad3a3a8896743c1144698093be257dacb66dc785228b912c8d965d14aa28342c3ac4a93fefa532b20945ddc1020139c14d638b908c4ddde9a0645b95b2e4414d40bb79f04413830f15a873c28bb7059c2741002015f20408f058e715b0bf995b5380b7dd325a056ab97e659a2be0cdf6c33731c683a634b771e8c92a139aee4bb0e49c7077321d42fc199f7c1f298ca625d223a5c263a03cc48159b7812665b78637e4e18720b2c29a6b99f42766a4cbc4dc508ba94ba83b89c3a5c78f8bb26bbd9b79beb8c8182490f5793ee5b96013b74b7e169e29d162f1315464ea7d72436d89b755161192c81cc2dd1c8b8bba795ef426ee1cc01c37aaa37b2cff8b0a378b47cbd0b4d49398cfc2712959699fa0bd8cd84666acc61f541b84fa96b9c854e4e75e9144addb44b8566a57dfbb545ce423c03346f2b2c1a91780d152a8de1a4d4c9cacde7392c996888cc2399c02c38b3353adf8acab283924da00a05b76e738c72c930d6cba09ae168990faa1fef2226e780861d416eff402f4f759fc648ab1f97100109087f96e4b148d2cb31e4805314ea0cd95fb023eac0d989474ba4201d7b41d26f5394b217eea5b34b71a8b37931c0e594271e0b7c733257240233e7ba735603e425a87dee77079e37cb28a21764594ce5350d8da2b62a07174943032ec89c98809c73b6423d30c1d283a766a64d89703c3d629b497828d48320c346210797a298aa10d423c8dda069d02bc59e6cdf03a096b8b3da4cab9b80ca4a14907672ccef1ec4faf234a0bc5b7e9d473f2b3133b3b26a1d175cb67a7805919699c02f76531b99c5f89180704bb4ca4535c5b8972679c660a07c5e514b87009c862eb8f5157695efb3fc40a9def6b81c1cc02a249ae4f094ad0d9bd3485c1c1c68080520a7c8c632032cee738154e5c5176c07da56024776a430fe76eacf665a3f7b832102215bc82f10939c8355704336a8fac1d81e4bb0485aa5d7c74d6b59bbe5c5e972a0d8bac411b55b5d5557cd680a1a8f71b4eb86bc48c9a0509731a54bd9d7290b27963e4372dc9b199cfdcac0b01acd28a62395112e4c43648d622c48c8234d01440e8cc376c927f23a5afc9ac0474c662274e424525c8552ece3b3fe26516de901bc7d515bde89558e626c95c80b93342f8010004f39e6c6c94871c5e344cab3966c835f9a96a59afd31c40286b38b1c1a78470bab947518934453ce86736a919f1f5a6d510a86f5454fc3980cb5c765bd2bd5f7b36b1410d6635c8ceb47c4dda0d76a28eac939c71c3024804866c71626658442163c2c22117e50acefce6378a985652302a4ef0c2ce0cc716b7796e2b6b2e3777dfa1ac3da259a31b5a9b530f8cb638a81a62ac301849abaf95a7301bda30068909bfdb7e67dbccbb38a5551a25b1a3a0f685748ad5753d8880f0016c627486166384c5571fe2365900364d038311e2d875db366686932b5ec602430a369e87a6ef5c338786657825bd4c057aceb923eb0935e6905e63b4ced7f80857a773dd64b150d26612ea9ac12052db2017bf1843ccb4b3281b690dc728adfa85c00281b8e3c09287335f856b4fc2892f69a2f57921ada01914c40988662d57769662a786351b9b66493dab79594d986de2100d65ba0ff4ea58b81538d24a4435a258fac25404aa7f41f658b1385065e158dcb60115732720f40459aaac15e406953a90ac52997d1ccd070060efc65db9e653354467fad56ec713c86e7540c423acf2669f52fa6f4ac6888d871ef3e847c029a8aafbb92e17b24aa079b1f419ba6175b442afb11909d4a56b70a0335b28739218aa7c9348e2c3c2f3eb3d15a41e6417c0dd94bfeb21419b311a7bb13a180bbe833218a9a6b17447cc85f225859587a73077049acbcfd44d0f025438e15d1538270d586e1bf83192a9459cf63c0e972f85297679831ecf121509851cb8340f6f107b0fa1a0efd1b36a8189bc085c4f5cb784e553f41b918f80397ce1956f785bee377ca9aa8be6998ada30c26b7c3d8c6b55254cc96203b20c42aee0ac4e1ebb408e49a9e3f879d0ab0785eb7025425d1305a2299c015e120d163b0e19494ce57253d0246d182745cb8197ab7438b3c1bb7972bec5a306eba3567855c014699fef65ae54c770a0d85c18400cf642aedc660777ba4b138502bd5a7812f621f84a48296b98dd4322b6f15828b8a8f0e00a8ba44a53c3a8b143571b0740abd567daf1cde9c79c204b6d5e259d1766a31bbbcb4e6a05cf4502176b301c1c2f41247750157bcec85e809b30a4d60d7747cdd0f5b99aa8c826987517793aaa8080a0b124a8558df72bbe37b75f4edbb6be8216d6c633fb2b2280e25113d8695e43481c3eeb397eb192505229b67a201ea893c3e2cb32da8bc342fa4dea0578a24e16d8f8f9383a95b77050f4d9fd2f5733eec1d63ef3c23ebf9918173669a7202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f").unwrap() .try_into().unwrap(); @@ -120,14 +128,12 @@ mod mlkem_tests { assert_eq!(sk_bytes.len(), expected_sk_bytes.len()); assert_eq!(sk_bytes, expected_sk_bytes.as_slice()); - // Decode and re-encode the pk, make sure you get the same thing let expected_pk = MLKEM768PublicKey::from_bytes(&expected_pk_bytes).unwrap(); let pk_bytes = expected_pk.encode(); assert_eq!(pk_bytes.len(), expected_pk_bytes.len()); assert_eq!(pk_bytes, expected_pk_bytes.as_slice()); - // run keygen from seed let (derived_pk, derived_sk) = MLKEM768::keygen_from_seed(&seed).unwrap(); let sk_bytes = derived_sk.encode(); @@ -148,11 +154,10 @@ mod mlkem_tests { let mut wrong_sk_bytes = sk_bytes.clone(); wrong_sk_bytes[4..8].copy_from_slice(&[0u8, 0u8, 0u8, 0u8]); match MLKEM768::keygen_from_seed_and_encoded(&seed, &wrong_sk_bytes) { - Err(KEMError::KeyGenError(_)) => {/* good */ }, + Err(KEMError::KeyGenError(_)) => { /* good */ } _ => panic!("sk_from_seed_and_encoded should fail with InvalidSignature"), } - /* MLKEM1024 */ let expected_sk_bytes: [u8; MLKEM1024_SK_LEN] = hex::decode("f77b7f6b15c73fe2cc546b67fb774ca19b42cd463ea9fbb984ca477a77b6c71087cbf051abe4736a9072c6e870c8311c55963f500a3c7b1b8f2a58558f49c62527b6c594b5e7acb3bcf597273a5743517d151208bd4aa61e75ba67b0bd594a994919627ac0a804d489e171336bc339f4666706e5134412b366823d50318c8bf261ab120a28a04fec01cc15f2b71912cee54aa8eed854694b6ba886b5eb7661e6d56aac213cc1d814d592b395554fae74476d34371163129bf864527250606cc21a53746b20997077bba155733b28a4e7fa0776399524763eb481ceaa11366c3474a04685f40c3f08b0424f40bff949a0ac92704c3ba0c6eb36f1f5b621d8bf2b6327beb57cd3facb94186fe3fc9ab0a1434bb291d2c9bb70723057e2254059656f565919a32cf74579de89681cd2c5a935a52b4aaa2d24cb5d5c9e20729ec5492ec36961efb8a28cbc00ac303523295f3d8036abc1603307ce70d7848a35657a5687dd589927ea63731626abb26ec4e431b8eb6b3b0bc1e82573ee73b1a021183183528108ae2eacaddb95b464a0b98469c319cc27bfa01bc31054a68c05502b1662b879fe98a1711c3426f6436cb0214cea379ac3a7e5fb60184a37c1da1eda61c6c39c1dd4e847845811f2a358a43731528536d4a3291b04158c2c3dc641624882678bc7805f58a9d94c7104567846a2044e65aece2a225372b6024799a5477d60237504aa5c0ac57bc70a3558c08c4de687ef1302b4fcb5594413d22cb959bc31be423450403c6bc57dc411b3fefac1052ac4bb162c44545a4ca80892657fa13a0b2c482ced629cc4999d969c593d4aadf073cc3e3a458e78a8aa039408e652be93b20c8b42ec5b0e50239dac726052851a6d15312ec39ed208b72209a577c6b2770112895749d5260e7dd446c0b0118c1000be6801d2611fcf00792a9cc4f4b49922f9a2d4b9c8fa5a5d0d60506631a7e971cee840b08fa63c13729d7ea5aac70352a984cdb669331cba758fe87ec3931b3e3161fcc747aa749424689feae14bf7c9a2ffba1302b212b80372d8e9049db69a3a1261d0a2859a9b4d57899e0ba41607a1b67a7c0e12923689f8c6395377d970c7490a4129611a1d05c3b7813bed945420723f7f9525a87793fafbbfca982e66bb80681c83248a89da084c19882f48f31e7fc09093a49e9fd09691b021edf463afc519b62853816118346115fb0b882cc6482f3c5cbcc1c1894697e1239598b34b2a9a7acd15244d0690c88194097a9beda585e87c437124624c210768e6215d376482653eb89947877c118d370c696a6ffcc1018ae413a08a8d0ffaa819945da7a167c229913290cad1c80a369258762610ea253e62dc24226a30c892c12136c326f13f4446664712b0b90bc063b4028593cbde06cdc22289e240c7e296b59172c1aeda8c99e0512d1a0163a942ea33148e6937c026029424b81b996b1df22ea0623ec65c6bf093500cf3bf35374adc392035ca7c583b99685bca541a0807b163acd0888be0385dea820da46e4dbb44d2e462c734b83a473fed1364273159257cc259a8c5676c1c76d41d56b9907ec1c3599c9e8907403a27a705e3619b04b0ad046e8ec8169c17b460d44c0c0c4464d044c946186bc725965083a892bcc495c0540311ff9b3e5192c303d88f8ba46a901c782ef02388f1b2addab6a5350fc3639700e3154337337e4a178d351cd2b56ee1f0bfea34aacfa33d2ec791e50752d4d034cb1c951572caaa5c4d90947b6b175a6dd3c62a77bb8f7ac9ae24719b53c2b120a2876986e217b72bd7cee44a7265b11cee1ab2261762b31a3738386969c0825fb79452e652e1142fc73c9df6fba411795b4717922b29ba2d53abe5a8c0dcc1601b096c96d7938fd5a68a8797c7b9477a86a472eb5da250cb2fec318d83c8f43bbe8e11c35e377d349366c85c4382597f6fc27a0051c0fb00b02c01ca20f9a427f172599477ca690cc1327e0f025f80ec338a80a159e308c12a27db1a7e1b960a99d37dfc22872e51930f28c651ab221f53abaee20bad9a3eabcbab913251bf135beb29617b5754333c4daadb2238341c2ad9378186280f6449440b784ba78f5dac44d8f65b3b7421950397c3913a2dd23ec6d1cb717b36a5fc95af191e278296948c1254ea86b4ec004b94c29450111191823b3514c9ac1ea3d9825ccb86393a2dfb04654fa2192d37bfad1c497c6502eee5ca80a73bfce0baf5a54a88585a401397a3d232f426a7afb082bc21a44317090eaac7592c2ea88a653c4491ea193931335f52e989a3c4cc56d9c553732d57c470fb41ab759b65d2d04445382fcd9c4e344a1128fa9e11e04358e192ed014b23232a7ee2b22e23717f44111ee33575399c37646da9813ec9b212afe94e5dc5c2330a7294cc1f4234a6d3fbb4f1685ab8892c04acb17cd1c170d7b0611b6a7176c794cc8c67f55fc923c2ad203100f365991882c30243d77813843b5ec7c964032263706092ecf00c7516be64e4598ca4226c069bb5e67e4175cf2286c8dd5c488a6c5861f31baa0bd0269470e8b551dd3bcd38c86c12f9cdb176c77dc8b6c02a701f478902c8553f694c0d82727b4c4a5c2c1041212aa1274808b82111b377ec75214e9b1978f76004d4139d98613f4b8e98d20af7b534073a509a959b7a7564f9b40ca218bf61829320a8502017954d328d7ac6c769ec29700756e7b0685b340d5e118059504a49a9a50a10198eb10a5784678eb427d7b4babb9552933b062897973e1318eaf0a0eac37584a65401b1703e042accd837531483f241cadcd1c1d378119e694429db199ac891e4c5343757085bb3ae783667350c4458d97672e861e80b1d2679510ea3a6f2360c77a46942c7a06a554d228080c84b47aef14db17620cb16c06ab30a1be4cda7082be9f87e9c211c46916349a5ba8eaa5201c7294a3c0885b53b657452108825ec646c90a04612324ee7d031afe5343132cbef67b6efb1a5ec2809b773538ce77b3d8b04eb0b3c2256011e4c716c19a8ba0752bf71492117649f0615c3290fc29a46fde4bd52db9286d603388244259c15a7ac2b640a60cc03376a5841a3fb8a473568fa9b1a267215f34c01697b0f0e627175d72105b7707c29b9e614bdc33a6f6c818a95370b427882d7b476796a9ec6eb993274cd9b2391a82ba45e3393d2e9ae9721ca9d6c1b988b5827713f90a6585de9433528c02b03ce10bb5f720138d0fbb4c30c1266b918e52925dfe17b37f95d22bca54f475919ac859098c0f0d08ac5875ef29b56fd141e6ef15f700a0b66f39595c588177373c4669b21bc071e4c3aa5f0b4a31b6258f35da24ac3cd29c7f2092410c5078355b138fb53a6b9ae6e0b9c08243e7baa45c47376eb8c7f13d4cf51aa736fa31540c9241f370da544bf9f9c28d9a57e2f2a7ca95a4e4b466e641ab3bcc76adf1139d567a6f12b52f3a65e7ec0aae26bcaa8c55833b04e59998ebc9a1930fbb6d2233c53d2c1f8b9518e3c2de73a19dee6b380a5b32971cf64e129fd6c1fa6e75d4a234501e966dd3a540af5c8f4f34a6b4a253ee28492566d5e67c6f55855fcb0506fb06c156744d9a03a31a26fa94cad14f157b7f303d07a69c773768fcb4d079c09059703a0c3a94de4b99ea3a2f16583d0f9170a3950db07b4f0bc30802927f9f7961b6259892636a9502a2705303637799dd344da451c1cf7bf67840ceb3079ab8c6b8c1927f64053c612450c45c9e603bc16666e596b3471e103b6f15447424d17022048111ffbd37e1c670f64f14b8a7b32b94c1a49b45dd2fc38cd5289d910ad63602cf5e13042c64ac6797b89fb551ad08e05a92d200cccb7e712ef23c9312cb350f029ab537e287347fd3075ac10906a783f1c6c07ccb88f41228c4be1c640f790b5c3a5d5d3ca792495d74bc461562658c07ac600276b924ab5bc9be1f0494cb76f82f460a7480972663381e169996061d799859ec54d4f5ca5c411c01db1597b165977669de13a928a34afbac258fea8c4764239c9421dc3119bf5b47699206978327b1c5345ef746a7983841f056e2534100ab24d4e9abbd0b17c6a95bd4c3c0e40f69e1612aceeb28b99086c95116e7204273893390bf46b899b36286b0ebf1947bb9884f732ca27da82b19b5dc0cc7f8885714910888b2310c4f9319d410b34e6433b9003e2176bb995257456106e8952163b8ba592530cc5aa0aeb43ad398fe9e97baa523d7a4431677c3d3af0719e475db85ca95af5089beabeb05b2faab4896ba60f81c88472a57b46a828826a0cdfb446f8189182d2bf5eac4ec1cc5deaf599c8a13e48235406d17ffddc8344b6c66984a868aa92fa02227a086950eb0c8701ed58dc628776b983882e117561349e5c131a7e116a0463861d7d18663c5627c38c7147ddaadfd48acd7a4535202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f").unwrap() .try_into().unwrap(); @@ -165,14 +170,12 @@ mod mlkem_tests { assert_eq!(sk_bytes.len(), expected_sk_bytes.len()); assert_eq!(sk_bytes, expected_sk_bytes.as_slice()); - // Decode and re-encode the pk, make sure you get the same thing let expected_pk = MLKEM1024PublicKey::from_bytes(&expected_pk_bytes).unwrap(); let pk_bytes = expected_pk.encode(); assert_eq!(pk_bytes.len(), expected_pk_bytes.len()); assert_eq!(pk_bytes, expected_pk_bytes.as_slice()); - // run keygen from seed let (derived_pk, derived_sk) = MLKEM1024::keygen_from_seed(&seed).unwrap(); let sk_bytes = derived_sk.encode(); @@ -192,21 +195,23 @@ mod mlkem_tests { let mut wrong_sk_bytes = sk_bytes.clone(); wrong_sk_bytes[4..8].copy_from_slice(&[0u8, 0u8, 0u8, 0u8]); match MLKEM1024::keygen_from_seed_and_encoded(&seed, &wrong_sk_bytes) { - Err(KEMError::KeyGenError(_)) => {/* good */ }, + Err(KEMError::KeyGenError(_)) => { /* good */ } _ => panic!("sk_from_seed_and_encoded should fail with InvalidSignature"), } } - #[test] /// Mirror of bc-java MLKEMTest.java : testMLKEM fn test_mlkem() { let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3 - 99E3246884181F8E1DD44E0C7629093330221FD67D9B7D6E1510B2DBAD8762F7" - ).unwrap(), + &hex::decode( + "49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3 + 99E3246884181F8E1DD44E0C7629093330221FD67D9B7D6E1510B2DBAD8762F7", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let expected_sk_bytes: [u8; MLKEM1024_SK_LEN] = hex::decode("8C8B3722A82E550565521611EBBC63079944C9B1ABB3B0020FF12F631891A9C468D3A67BF6271280DA58D03CB042B3A461441637F929C273469AD15311E910DE18CB9537BA1BE42E98BB59E498A13FD440D0E69EE832B45CD95C382177D67096A18C07F1781663651BDCAC90DEDA3DDD143485864181C91FA2080F6DAB3F86204CEB64A7B4446895C03987A031CB4B6D9E0462FDA829172B6C012C638B29B5CD75A2C930A5596A3181C33A22D574D30261196BC350738D4FD9183A763336243ACED99B3221C71D8866895C4E52C119BF3280DAF80A95E15209A795C4435FBB3570FDB8AA9BF9AEFD43B094B781D5A81136DAB88B8799696556FEC6AE14B0BB8BE4695E9A124C2AB8FF4AB1229B8AAA8C6F41A60C34C7B56182C55C2C685E737C6CA00A23FB8A68C1CD61F30D3993A1653C1675AC5F0901A7160A73966408B8876B715396CFA4903FC69D60491F8146808C97CD5C533E71017909E97B835B86FF847B42A696375435E006061CF7A479463272114A89EB3EAF2246F0F8C104A14986828E0AD20420C9B37EA23F5C514949E77AD9E9AD12290DD1215E11DA274457AC86B1CE6864B122677F3718AA31B02580E64317178D38F25F609BC6C55BC374A1BF78EA8ECC219B30B74CBB3272A599238C93985170048F176775FB19962AC3B135AA59DB104F7114DBC2C2D42949ADECA6A85B323EE2B2B23A77D9DB235979A8E2D67CF7D2136BBBA71F269574B38888E1541340C19284074F9B7C8CF37EB01384E6E3822EC4882DFBBEC4E6098EF2B2FC177A1F0BCB65A57FDAA89315461BEB7885FB68B3CD096EDA596AC0E61DD7A9C507BC6345E0827DFCC8A3AC2DCE51AD731AA0EB932A6D0983992347CBEB3CD0D9C9719797CC21CF0062B0AD94CAD734C63E6B5D859CBE19F0368245351BF464D7505569790D2BB724D8659A9FEB1C7C473DC4D061E29863A2714BAC42ADCD1A8372776556F7928A7A44E94B6A25322D03C0A1622A7FD261522B7358F085BDFB60758762CB901031901B5EECF4920C81020A9B1781BCB9DD19A9DFB66458E7757C52CEC75B4BA740A24099CB56BB60A76B6901AA3E0169C9E83496D73C4C99435A28D613E97A1177F58B6CC595D3B2331E9CA7B57B74DC2C5277D26F2FE19240A55C35D6CFCA26C73E9A2D7C980D97960AE1A04698C16B398A5F20C35A0914145CE1674B71ABC6066A909A3E4B911E69D5A849430361F731B07246A6329B52361904225082D0AAC5B21D6B34862481A890C3C360766F04263603A6B73E802B1F70B2EB00046836B8F493BF10B90B8737C6C548449B294C47253BE26CA72336A632063AD3D0B48C8B0F4A34447EF13B764020DE739EB79ABA20E2BE1951825F293BEDD1089FCB0A91F560C8E17CDF52541DC2B81F972A7375B201F10C08D9B5BC8B95100054A3D0AAFF89BD08D6A0E7F2115A435231290460C9AD435A3B3CF35E52091EDD1890047BCC0AABB1ACEBC75F4A32BC1451ACC4969940788E89412188946C9143C5046BD1B458DF617C5DF533B052CD6038B7754034A23C2F7720134C7B4EACE01FAC0A2853A9285847ABBD06A3343A778AC6062E458BC5E61ECE1C0DE0206E6FE8A84034A7C5F1B005FB0A584051D3229B86C909AC5647B3D75569E05A88279D80E5C30F574DC327512C6BBE8101239EC62861F4BE67B05B9CDA9C545C13E7EB53CFF260AD9870199C21F8C63D64F0458A7141285023FEB829290872389644B0C3B73AC2C8E121A29BB1C43C19A233D56BED82740EB021C97B8EBBA40FF328B541760FCC372B52D3BC4FCBC06F424EAF253804D4CB46F41FF254C0C5BA483B44A87C219654555EC7C163C79B9CB760A2AD9BB722B93E0C28BD4B1685949C496EAB1AFF90919E3761B346838ABB2F01A91E554375AFDAAAF3826E6DB79FE7353A7A578A7C0598CE28B6D9915214236BBFFA6D45B6376A07924A39A7BE818286715C8A3C110CD76C02E0417AF138BDB95C3CCA798AC809ED69CFB672B6FDDC24D89C06A6558814AB0C21C62B2F84C0E3E0803DB337A4E0C7127A6B4C8C08B1D1A76BF07EB6E5B5BB47A16C74BC548375FB29CD789A5CFF91BDBD071859F4846E355BB0D29484E264DFF36C9177A7ACA78908879695CA87F25436BC12630724BB22F0CB64897FE5C41195280DA04184D4BC7B532A0F70A54D7757CDE6175A6843B861CB2BC4830C0012554CFC5D2C8A2027AA3CD967130E9B96241B11C4320C7649CC23A71BAFE691AFC08E680BCEF42907000718E4EACE8DA28214197BE1C269DA9CB541E1A3CE97CFADF9C6058780FE6793DBFA8218A2760B802B8DA2AA271A38772523A76736A7A31B9D3037AD21CEBB11A472B8792EB17558B940E70883F264592C689B240BB43D5408BF446432F412F4B9A5F6865CC252A43CF40A320391555591D67561FDD05353AB6B019B3A08A73353D51B6113AB2FA51D975648EE254AF89A230504A236A4658257740BDCBBE1708AB022C3C588A410DB3B9C308A06275BDF5B4859D3A2617A295E1A22F90198BAD0166F4A943417C5B831736CB2C8580ABFDE5714B586ABEEC0A175A08BC710C7A2895DE93AC438061BF7765D0D21CD418167CAF89D1EFC3448BCBB96D69B3E010C82D15CAB6CACC6799D3639669A5B21A633C865F8593B5B7BC800262BB837A924A6C5440E4FC73B41B23092C3912F4C6BEBB4C7B4C62908B03775666C22220DF9C88823E344C7308332345C8B795D34E8C051F21F5A21C214B69841358709B1C305B32CC2C3806AE9CCD3819FFF4507FE520FBFC27199BC23BE6B9B2D2AC1717579AC769279E2A7AAC68A371A47BA3A7DBE016F14E1A727333663C4A5CD1A0F8836CF7B5C49AC51485CA60345C990E06888720003731322C5B8CD5E6907FDA1157F468FD3FC20FA8175EEC95C291A262BA8C5BE990872418930852339D88A19B37FEFA3CFE82175C224407CA414BAEB37923B4D2D83134AE154E490A9B45A0563B06C953C3301450A2176A07C614A74E3478E48509F9A60AE945A8EBC7815121D90A3B0E07091A096CF02C57B25BCA58126AD0C629CE166A7EDB4B33221A0D3F72B85D562EC698B7D0A913D73806F1C5C87B38EC003CB303A3DC51B4B35356A67826D6EDAA8FEB93B98493B2D1C11B676A6AD9506A1AAAE13A824C7C08D1C6C2C4DBA9642C76EA7F6C8264B64A23CCCA9A74635FCBF03E00F1B5722B214376790793B2C4F0A13B5C40760B4218E1D2594DCB30A70D9C1782A5DD30576FA4144BFC8416EDA8118FC6472F56A979586F33BB070FB0F1B0B10BC4897EBE01BCA3893D4E16ADB25093A7417D0708C83A26322E22E6330091E30152BF823597C04CCF4CFC7331578F43A2726CCB428289A90C863259DD180C5FF142BEF41C7717094BE07856DA2B140FA67710967356AA47DFBC8D255B4722AB86D439B7E0A6090251D2D4C1ED5F20BBE6807BF65A90B7CB2EC0102AF02809DC9AC7D0A3ABC69C18365BCFF59185F33996887746185906C0191AED4407E139446459BE29C6822717644353D24AB6339156A9C424909F0A9025BB74720779BE43F16D81C8CC666E99710D8C68BB5CC4E12F314E925A551F09CC59003A1F88103C254BB978D75F394D3540E31E771CDA36E39EC54A62B5832664D821A72F1E6AFBBA27F84295B2694C498498E812BC8E9378FE541CEC5891B25062901CB7212E3CDC46179EC5BCEC10BC0B9311DE05074290687FD6A5392671654284CD9C8CC3EBA80EB3B662EB53EB75116704A1FEB5C2D056338532868DDF24EB8992AB8565D9E490CADF14804360DAA90718EAB616BAB0765D33987B47EFB6599C5563235E61E4BE670E97955AB292D9732CB8930948AC82DF230AC72297A23679D6B94C17F1359483254FEDC2F05819F0D069A443B78E3FC6C3EF4714B05A3FCA81CBBA60242A7060CD885D8F39981BB18092B23DAA59FD9578388688A09BBA079BC809A54843A60385E2310BBCBCC0213CE3DFAAB33B47F9D6305BC95C6107813C585C4B657BF30542833B14949F573C0612AD524BAAE69590C1277B86C286571BF66B3CFF46A3858C09906A794DF4A06E9D4B0A2E43F10F72A6C6C47E5646E2C799B71C33ED2F01EEB45938EB7A4E2E2908C53558A540D350369FA189C616943F7981D7618CF02A5B0A2BCC422E857D1A47871253D08293C1C179BCDC0437069107418205FDB9856623B8CA6B694C96C084B17F13BB6DF12B2CFBBC2B0E0C34B00D0FCD0AECFB27924F6984E747BE2A09D83A8664590A8077331491A4F7D720843F23E652C6FA840308DB4020337AAD37967034A9FB523B67CA70330F02D9EA20C1E84CB8E5757C9E1896B60581441ED618AA5B26DA56C0A5A73C4DCFD755E610B4FC81FF84E21D2E574DFD8CD0AE893AA7E125B44B924F45223EC09F2AD1141EA93A68050DBF699E3246884181F8E1DD44E0C7629093330221FD67D9B7D6E1510B2DBAD8762F7").unwrap() .try_into().unwrap(); @@ -218,8 +223,16 @@ mod mlkem_tests { assert_eq!(sk.encode(), expected_sk_bytes.as_slice()); assert_eq!(pk.encode(), expected_pk_bytes.as_slice()); - let message: [u8; MLKEM_RND_LEN] = hex::decode("59C5154C04AE43AAFF32700F081700389D54BEC4C37C088B1C53F66212B12C72").unwrap().try_into().unwrap(); - let expected_shared_secret: [u8; MLKEM_SS_LEN] = hex::decode("5CF38F578AC4AE95FBFED574B3D8EBF7CB1DC9074F22277360E36D775347C058").unwrap().try_into().unwrap(); + let message: [u8; MLKEM_RND_LEN] = + hex::decode("59C5154C04AE43AAFF32700F081700389D54BEC4C37C088B1C53F66212B12C72") + .unwrap() + .try_into() + .unwrap(); + let expected_shared_secret: [u8; MLKEM_SS_LEN] = + hex::decode("5CF38F578AC4AE95FBFED574B3D8EBF7CB1DC9074F22277360E36D775347C058") + .unwrap() + .try_into() + .unwrap(); let expected_ciphertext: [u8; MLKEM1024_CT_LEN] = hex::decode("8B9FE419250C5FB0463C8181FCF7CEC777136B738E015EBA31067AA4A8C378BBAC0121B88214F1AEB866E4F33C277099E09B4BF7E21CDDA30B5B32C18B0E9660C30601D85DAEC07AAF4B343EC5516FA501DD63088B999FB9A414C6CA593806C08CD4C775139BF0F0BF3676D773EDD56E616A13830D5F5FE35E515DBC84E43AAD0167D57E60A9DE30886ACD3F7F2006CAC26A7A07B4DADBEDFBED7F305764386AAD726D5B2BF14A376BAD8B4896688491733FB34E6EDEA10BFD5E448541CB6E69E3D87DF190AFA7FF62577775BAACEA444A6128A20200251D8FA759DC60FDA6A9730CFFE4997FE7EBCDD1644AE2D55290A4074CDD2CE53C18D22BC33671E68727A9B5A2FEAFB114A8045D96A56981E200A09661375987625ACC233EDE817AF1DEEAA21C7C4377423E73C5AF9BFF58A49DE6DAFD07A3E3BABD891F62BBA41D1856B8BC502CC86EE115A3598431E2B54AB0C5EACC3CE6A03090925C1FD5A251B00576763A963994A7A23EE12EBFC1B994F93C6144178F0BEF88245CE77CD32EF651826A6090AF561A5864DEC2A51D846F1F48F88B4B55F58C2373E0F67BDC95DC23A43E8546232A7B234E49F5226A3A63BDBCED7240FC81C2DB68AAEB2671A2FD231997BF8839C63A7F41F15E7242821D42E80BBC0F43FA9E353DE8B25ED8FFC242EB512C6A5260919AAE89A11176532BCCC762A520A37AEC4E7209AA81CEE0DD4ADD932C47EB8100BE98AA1DEEA9EA698115ADCED950A6C536D19AEB325CEA8C5245C0A2281533FB90809DC2BE90567EBE6AE229FE09B44DA2182585EA694D8A9AB33EBC24B44E09BD510F34B4140E1FB41162F9415F2D9106A0CEA00A26ED0920021F4E5BCFB3DABF5850DAB22B2E889D9611FBE06D0C899708EB5E5FAD2FBBE0D5C0BDE080F8E760EDFA037D55DA77F0F39591BF5B050C905FA538B7228E238A290DF340778DCBD6BE40A3B1DD455FB27ADBE176AEF6CC295BEA570BDC221BA14002E3B113B0EF237452FBC9F1AEC42E0D2B33F19832DB0A6171CAEB0B30EEAD3A54B704B761C7D4AFEA8F6AFC15156666A081C43AEB2E04FEECEF8AABA4049BD78B120B9ABA86A60342A0CF806411C473C26C4BE1540E3312388BCBC8523BA73F40EA28D5564274F3661D7ACAA0F1E8D0F28DCF6B501329963E6857FDB2AAE873A7D9D6C14821F6C0B6AA50AC449075CD6F2A256C5A05959DAB5A5912CC8E8F8B9F59941BFCCE6A28CBA74A20382B1FD3382D056547D5BC5EF4AAE62F96F038C595A4F901D6AE790F8978292AD1CC3A1E800B71A5BBE84533646655E3752FBD6B02B97B204E75D28A34C2F990FB8E8CD31CE6E683FA7E67DA03367E8D47DC626F060FBA2D0425004CAC2A61D982D2E3D85008624B45DB022CF51BA265B5E974712A9372EECAC0EA272B2FC56EBED0D32105521BA2C4A8FE0C678CE4E45902C7BA9D510BD47B2B5F931DD732F27DE9B42FD4AA39EAC765283A9965EE97C0D88E23EFA6F718242C67770B87BF8832858C1D13FC520870BD34F2B9C6FBFD1A528B744F814C93F4F4E87108316FE2AB06E02292DEA7FCF6FEFB17BF5AA7376A4A9BDB7C49BF709EB1E05D60EF14CD85A75239B97BCA9A6A3CC1B28F28979D612431BAAC1ACEE5EF62776B4D51B7EB0F63DF507760097223CA903E16E02DEB7FCABFBEC26DAEDC0ED4CC55726BDC31D1775112EF3C35D1DF928C6EB7830D8CA6570CB5CE348E3F26DDE864F20E5BE7B99E264EBC0E9D8DE9C6E4B7FE3CFBE673833CF7E8B3081529062CB6815C7C0766822B3B31E56BA1FC73FE3DED4B5D435BFCE2F2997C1D4B9CE293220DD461103BE084BF12076372668A69836769C1F6D8C32E2C7BC2E7D66714C814793A2970C90DD94DF14C89C60DD35B52A14778E137E750CE83AC3AAB667FCBDCBA38B7FA6D1C6BF7B99D957078176D9779A09F84B75FBC2A11769EF65532B09ACA4C9A3766B4A1FC717F94648FB8B8D9363E54F1C4201C075C18B1EAE098B83598089585ED9DC06B96E2D1C96DC738086EBBC26C3193B64139E1FC1DFB22A17893506EF7B35792B4EB00196693686EB5DEB3CEB436DD16D2D92A0FD31F468AF8662040F5257BFA0F14991C0D560999EEF775178D14955ADF091DD797AC1FDCEC7776055271C0F130562D0B0A6749B159DD0DB9AC69271AC719B83B683CE8B32342AC4AB257B0F8083C8CC86338AFA4D386C9848F413ED0").unwrap().try_into().unwrap(); // encaps @@ -235,13 +248,16 @@ mod mlkem_tests { #[test] fn test_decaps_from_seed() { - let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3 + &hex::decode( + "49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3 99E3246884181F8E1DD44E0C7629093330221FD67D9B7D6E1510B2DBAD8762F7 - ").unwrap(), + ", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let expected_pk_bytes: [u8; MLKEM1024_PK_LEN] = hex::decode("A04184D4BC7B532A0F70A54D7757CDE6175A6843B861CB2BC4830C0012554CFC5D2C8A2027AA3CD967130E9B96241B11C4320C7649CC23A71BAFE691AFC08E680BCEF42907000718E4EACE8DA28214197BE1C269DA9CB541E1A3CE97CFADF9C6058780FE6793DBFA8218A2760B802B8DA2AA271A38772523A76736A7A31B9D3037AD21CEBB11A472B8792EB17558B940E70883F264592C689B240BB43D5408BF446432F412F4B9A5F6865CC252A43CF40A320391555591D67561FDD05353AB6B019B3A08A73353D51B6113AB2FA51D975648EE254AF89A230504A236A4658257740BDCBBE1708AB022C3C588A410DB3B9C308A06275BDF5B4859D3A2617A295E1A22F90198BAD0166F4A943417C5B831736CB2C8580ABFDE5714B586ABEEC0A175A08BC710C7A2895DE93AC438061BF7765D0D21CD418167CAF89D1EFC3448BCBB96D69B3E010C82D15CAB6CACC6799D3639669A5B21A633C865F8593B5B7BC800262BB837A924A6C5440E4FC73B41B23092C3912F4C6BEBB4C7B4C62908B03775666C22220DF9C88823E344C7308332345C8B795D34E8C051F21F5A21C214B69841358709B1C305B32CC2C3806AE9CCD3819FFF4507FE520FBFC27199BC23BE6B9B2D2AC1717579AC769279E2A7AAC68A371A47BA3A7DBE016F14E1A727333663C4A5CD1A0F8836CF7B5C49AC51485CA60345C990E06888720003731322C5B8CD5E6907FDA1157F468FD3FC20FA8175EEC95C291A262BA8C5BE990872418930852339D88A19B37FEFA3CFE82175C224407CA414BAEB37923B4D2D83134AE154E490A9B45A0563B06C953C3301450A2176A07C614A74E3478E48509F9A60AE945A8EBC7815121D90A3B0E07091A096CF02C57B25BCA58126AD0C629CE166A7EDB4B33221A0D3F72B85D562EC698B7D0A913D73806F1C5C87B38EC003CB303A3DC51B4B35356A67826D6EDAA8FEB93B98493B2D1C11B676A6AD9506A1AAAE13A824C7C08D1C6C2C4DBA9642C76EA7F6C8264B64A23CCCA9A74635FCBF03E00F1B5722B214376790793B2C4F0A13B5C40760B4218E1D2594DCB30A70D9C1782A5DD30576FA4144BFC8416EDA8118FC6472F56A979586F33BB070FB0F1B0B10BC4897EBE01BCA3893D4E16ADB25093A7417D0708C83A26322E22E6330091E30152BF823597C04CCF4CFC7331578F43A2726CCB428289A90C863259DD180C5FF142BEF41C7717094BE07856DA2B140FA67710967356AA47DFBC8D255B4722AB86D439B7E0A6090251D2D4C1ED5F20BBE6807BF65A90B7CB2EC0102AF02809DC9AC7D0A3ABC69C18365BCFF59185F33996887746185906C0191AED4407E139446459BE29C6822717644353D24AB6339156A9C424909F0A9025BB74720779BE43F16D81C8CC666E99710D8C68BB5CC4E12F314E925A551F09CC59003A1F88103C254BB978D75F394D3540E31E771CDA36E39EC54A62B5832664D821A72F1E6AFBBA27F84295B2694C498498E812BC8E9378FE541CEC5891B25062901CB7212E3CDC46179EC5BCEC10BC0B9311DE05074290687FD6A5392671654284CD9C8CC3EBA80EB3B662EB53EB75116704A1FEB5C2D056338532868DDF24EB8992AB8565D9E490CADF14804360DAA90718EAB616BAB0765D33987B47EFB6599C5563235E61E4BE670E97955AB292D9732CB8930948AC82DF230AC72297A23679D6B94C17F1359483254FEDC2F05819F0D069A443B78E3FC6C3EF4714B05A3FCA81CBBA60242A7060CD885D8F39981BB18092B23DAA59FD9578388688A09BBA079BC809A54843A60385E2310BBCBCC0213CE3DFAAB33B47F9D6305BC95C6107813C585C4B657BF30542833B14949F573C0612AD524BAAE69590C1277B86C286571BF66B3CFF46A3858C09906A794DF4A06E9D4B0A2E43F10F72A6C6C47E5646E2C799B71C33ED2F01EEB45938EB7A4E2E2908C53558A540D350369FA189C616943F7981D7618CF02A5B0A2BCC422E857D1A47871253D08293C1C179BCDC0437069107418205FDB9856623B8CA6B694C96C084B17F13BB6DF12B2CFBBC2B0E0C34B00D0FCD0AECFB27924F6984E747BE2A09D83A8664590A8077331491A4F7D720843F23E652C6FA840308DB4020337AAD37967034A9FB523B67CA70330F02D9EA20C1E84CB8E5757C9E1896B60581441ED618AA5B26DA56C0A5A73C4DCFD755E610B4FC81FF84E21").unwrap() .try_into().unwrap(); @@ -251,8 +267,16 @@ mod mlkem_tests { assert_eq!(pk.encode(), expected_pk_bytes.as_slice()); - let message: [u8; MLKEM_RND_LEN] = hex::decode("59C5154C04AE43AAFF32700F081700389D54BEC4C37C088B1C53F66212B12C72").unwrap().try_into().unwrap(); - let expected_shared_secret: [u8; MLKEM_SS_LEN] = hex::decode("5CF38F578AC4AE95FBFED574B3D8EBF7CB1DC9074F22277360E36D775347C058").unwrap().try_into().unwrap(); + let message: [u8; MLKEM_RND_LEN] = + hex::decode("59C5154C04AE43AAFF32700F081700389D54BEC4C37C088B1C53F66212B12C72") + .unwrap() + .try_into() + .unwrap(); + let expected_shared_secret: [u8; MLKEM_SS_LEN] = + hex::decode("5CF38F578AC4AE95FBFED574B3D8EBF7CB1DC9074F22277360E36D775347C058") + .unwrap() + .try_into() + .unwrap(); let expected_ciphertext: [u8; MLKEM1024_CT_LEN] = hex::decode("8B9FE419250C5FB0463C8181FCF7CEC777136B738E015EBA31067AA4A8C378BBAC0121B88214F1AEB866E4F33C277099E09B4BF7E21CDDA30B5B32C18B0E9660C30601D85DAEC07AAF4B343EC5516FA501DD63088B999FB9A414C6CA593806C08CD4C775139BF0F0BF3676D773EDD56E616A13830D5F5FE35E515DBC84E43AAD0167D57E60A9DE30886ACD3F7F2006CAC26A7A07B4DADBEDFBED7F305764386AAD726D5B2BF14A376BAD8B4896688491733FB34E6EDEA10BFD5E448541CB6E69E3D87DF190AFA7FF62577775BAACEA444A6128A20200251D8FA759DC60FDA6A9730CFFE4997FE7EBCDD1644AE2D55290A4074CDD2CE53C18D22BC33671E68727A9B5A2FEAFB114A8045D96A56981E200A09661375987625ACC233EDE817AF1DEEAA21C7C4377423E73C5AF9BFF58A49DE6DAFD07A3E3BABD891F62BBA41D1856B8BC502CC86EE115A3598431E2B54AB0C5EACC3CE6A03090925C1FD5A251B00576763A963994A7A23EE12EBFC1B994F93C6144178F0BEF88245CE77CD32EF651826A6090AF561A5864DEC2A51D846F1F48F88B4B55F58C2373E0F67BDC95DC23A43E8546232A7B234E49F5226A3A63BDBCED7240FC81C2DB68AAEB2671A2FD231997BF8839C63A7F41F15E7242821D42E80BBC0F43FA9E353DE8B25ED8FFC242EB512C6A5260919AAE89A11176532BCCC762A520A37AEC4E7209AA81CEE0DD4ADD932C47EB8100BE98AA1DEEA9EA698115ADCED950A6C536D19AEB325CEA8C5245C0A2281533FB90809DC2BE90567EBE6AE229FE09B44DA2182585EA694D8A9AB33EBC24B44E09BD510F34B4140E1FB41162F9415F2D9106A0CEA00A26ED0920021F4E5BCFB3DABF5850DAB22B2E889D9611FBE06D0C899708EB5E5FAD2FBBE0D5C0BDE080F8E760EDFA037D55DA77F0F39591BF5B050C905FA538B7228E238A290DF340778DCBD6BE40A3B1DD455FB27ADBE176AEF6CC295BEA570BDC221BA14002E3B113B0EF237452FBC9F1AEC42E0D2B33F19832DB0A6171CAEB0B30EEAD3A54B704B761C7D4AFEA8F6AFC15156666A081C43AEB2E04FEECEF8AABA4049BD78B120B9ABA86A60342A0CF806411C473C26C4BE1540E3312388BCBC8523BA73F40EA28D5564274F3661D7ACAA0F1E8D0F28DCF6B501329963E6857FDB2AAE873A7D9D6C14821F6C0B6AA50AC449075CD6F2A256C5A05959DAB5A5912CC8E8F8B9F59941BFCCE6A28CBA74A20382B1FD3382D056547D5BC5EF4AAE62F96F038C595A4F901D6AE790F8978292AD1CC3A1E800B71A5BBE84533646655E3752FBD6B02B97B204E75D28A34C2F990FB8E8CD31CE6E683FA7E67DA03367E8D47DC626F060FBA2D0425004CAC2A61D982D2E3D85008624B45DB022CF51BA265B5E974712A9372EECAC0EA272B2FC56EBED0D32105521BA2C4A8FE0C678CE4E45902C7BA9D510BD47B2B5F931DD732F27DE9B42FD4AA39EAC765283A9965EE97C0D88E23EFA6F718242C67770B87BF8832858C1D13FC520870BD34F2B9C6FBFD1A528B744F814C93F4F4E87108316FE2AB06E02292DEA7FCF6FEFB17BF5AA7376A4A9BDB7C49BF709EB1E05D60EF14CD85A75239B97BCA9A6A3CC1B28F28979D612431BAAC1ACEE5EF62776B4D51B7EB0F63DF507760097223CA903E16E02DEB7FCABFBEC26DAEDC0ED4CC55726BDC31D1775112EF3C35D1DF928C6EB7830D8CA6570CB5CE348E3F26DDE864F20E5BE7B99E264EBC0E9D8DE9C6E4B7FE3CFBE673833CF7E8B3081529062CB6815C7C0766822B3B31E56BA1FC73FE3DED4B5D435BFCE2F2997C1D4B9CE293220DD461103BE084BF12076372668A69836769C1F6D8C32E2C7BC2E7D66714C814793A2970C90DD94DF14C89C60DD35B52A14778E137E750CE83AC3AAB667FCBDCBA38B7FA6D1C6BF7B99D957078176D9779A09F84B75FBC2A11769EF65532B09ACA4C9A3766B4A1FC717F94648FB8B8D9363E54F1C4201C075C18B1EAE098B83598089585ED9DC06B96E2D1C96DC738086EBBC26C3193B64139E1FC1DFB22A17893506EF7B35792B4EB00196693686EB5DEB3CEB436DD16D2D92A0FD31F468AF8662040F5257BFA0F14991C0D560999EEF775178D14955ADF091DD797AC1FDCEC7776055271C0F130562D0B0A6749B159DD0DB9AC69271AC719B83B683CE8B32342AC4AB257B0F8083C8CC86338AFA4D386C9848F413ED0").unwrap().try_into().unwrap(); // encaps @@ -269,19 +293,22 @@ mod mlkem_tests { #[test] fn keygen_error_cases() { /* - Testing this condition: - if !(seed.key_type() == KeyType::Seed || seed.key_type() == KeyType::BytesFullEntropy) - || seed.key_len() != 64 - */ + Testing this condition: + if !(seed.key_type() == KeyType::Seed || seed.key_type() == KeyType::BytesFullEntropy) + || seed.key_len() != 64 + */ // success case KeyType: seed let mut seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); - + ) + .unwrap(); /* MLKEM512 */ let expected_sk_bytes: [u8; MLKEM512_SK_LEN] = hex::decode("70554fd436344f2785b1b3b1bac184b6679003336c26f15a7de878c4825c6be03f3c4a480f75b7486aad31d3a00518623fd207ab528dd62721495835ae0062c367b74a71baf10aad0e8a2902076be31348beb15ccc0957cdebb4aff226756bbc601b6568ab784acbaeb34702f0f86a26202118b22b23f83558776c79c14dba983379c803e0dcc3160a11757030e69c6919798d81eb698a9a4483a99e5a5cb2c31c9a661799f3cc89c790706ea041629045d42a83aed88860e394c69187e2105d28cc14ec393592d67dd00aa43fe8b4eae4414002866b5c713c6a8d7d16cf78b819d6f12e9e5a74233908f0b15e3c4ba8329c5cdda55c84928e3aa8063e5aa9676403f91735b11010c7f593091364dc86445bc804840a9a21724212469f8a7b0ce0ac698eb86cad39a7f4824d9a5163aac21ee6808b053c8a3facb0b6744b5262bbcb26a43f664c8732b64cfc7acf099605f41c796060976ac433833fe00343fb1828300a424741116e4b45bb276ea81129a0db4c6e60bce611101e8c625474925e0222679308a3e7708d1972a7b423eb232851c36d2ed53d3ed3bb7500637061a5dc2292fa1c466c07354683328bec2c1ed2cb5c99b78eca0969038cf7c34dd118724e31cae086206b34302b520f5d177aded5b3cce02acce808ea26bcc072625fdb93f17458a5fc1d4da394380a1f57e9cc66109438a075f0d2813fcc4a199cc76db3823f270b0061594192940411a37ffbafae2c150165cec5c6bf73c595fb92cd15312607da070778652bd9944bc48bc7d1a534338bad0bad6656c5d502ce7850ab1587244eeb58f439ab5e08574a718c8aac3d77c798bba1542733be73448f23fb70c0e5353a27c88322c5218493afbb38086434d6d60a56ba887dd498c3ab26a0870993815aa6a40975f218adca1582d64ffc8652fbb3a9a6fbc304f91945fa4aaef2878fd715df70113d2379f44886f812c83ff2b719a69e1ec74ae4b15accd3aed5a53ce76a7b0982471633b973cb40a1a0015d0a424fa11a479c023017436d2a2900e993eb5a0a067400c7f4aadf201fc4fa31264a63bae95cc8d65c3995815e597d104355cf29aa5333c93251869d5bcdbe487124f602b8b6a66c16c4761648ad765cf5d8006b515e905a7f0ac076b0c62efa328153e7ca5701699f1305f1e6bc6f90b0e49b693512b6ce992a8b8016ddfc1a662c7e3f9619cbd869dd771af30896ccd5918ac6cb77466c5e779996d67ff9aabc97503f2c7b7e2d000d86450fb1807ca4cabda465825a31c789a1b7a491ab3872765d320d0b71920fa213c94093416b83b8124e69f65e62cb5000dcc37aa9a0fff73970c4772f357d24189ca6f5305568c0e2376a3762a68c605e563c5d209572e0fc7532ca294729535567b5fc413c5e8792d2464536cc808f98add74664f141566f9016a90a541829a98a0464ce41a8bb44c2d4fa3c2c209460728ef14a1a7c4c9b98d12203b4cc3529160a9ab2d7838f7ff6b53ae05aa31a7d646b7afa6c45932526a3c3755619be994c211c2a31c05b3447836cb2150be1829dae6b04c5535cff546e392ba797411720f924f490a5ac5495f21356d550b782a64c1688b6b655bcc7842197a434c2f6563b5b7f09a78bcc488232783561d16f4cbab6755400050781570c66604b817ad1252294736e8b01861a4b5a74519b8b6fe51489a5072392e587626c713776575d33806a1c8e2732af97c2680f51666331c4eb8bbc0431c4f96832daf1b3c45528fba153f6c78b1c198702947ccd337727a46fb53ba11de5cb4191346859516cb6ad72400f3cf209b236aef35a580ac87eb3e30fafd66973ca8a7dd2675af41f7a17b61433cd1af80f7708869f665488497980b1ac10a0cdcb636a00ed8681b35e429124ca80350725b85f83a5eac3a4a3cc1600903e65293560b9b336e5af0d529dac1a048119302cb7a9bcc110b94851bf02117f199dc485a852b7473f09b831a6831d5b54c0b790d225cf6bb92d9462a26cdb33dda5123c7aaf0e26a0b83655eea28bf3a8074725018fd6bae4b601cf61baab71a7a3d35197a343e74b4a272c125d540896426d85b7958d3b38a6ba987ec37225c7b44cdb12dde4539b4ab082363683f04bf7a09cc5c41dfe830a1b162e0b324334362f084a14467723344badd000f8d8c537c48f998f05307cebd1ede0b81c3bc59a065a1b6d63b26c82f101ff648063b376e2bb6c5b7455f655a50c2feadade150efa0e0e6f365aea202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f").unwrap() @@ -297,38 +324,44 @@ mod mlkem_tests { seed.set_key_type(KeyType::BytesFullEntropy).unwrap(); _ = MLKEM512::keygen_from_seed(&seed).unwrap(); - // Failure case: key type != Seed || BytesFullEntropy let mac_seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::MACKey, - ).unwrap(); + ) + .unwrap(); match MLKEM512::keygen_from_seed(&mac_seed) { - Err(KEMError::KeyGenError(_)) => { /* good */ }, + Err(KEMError::KeyGenError(_)) => { /* good */ } _ => panic!("expected KeyGenError"), } // Failure case: key is undersized let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e").unwrap(), + 303132333435363738393a3b3c3d3e", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); assert_eq!(seed.key_len(), 63); match MLKEM512::keygen_from_seed(&seed) { - Err(KEMError::KeyGenError(_)) => { /* good */ }, + Err(KEMError::KeyGenError(_)) => { /* good */ } _ => panic!("expected KeyGenError"), } } - /// test the "Decapsulation input checks" in Section 7.3 #[test] fn test_decapsulation_input_checks() { @@ -336,7 +369,6 @@ mod mlkem_tests { // 𝑑𝑣, and 𝑘 specified by the relevant parameter set, then input checking has failed. // This is already tested in [test_boundary_conditions] - // 2. (Decapsulation key type check) If dk is not a byte array of length 768𝑘 + 96 for the value of // 𝑘 specified by the relevant parameter set, then input checking has failed. // This does not need to be tested because of the static-sizing of the SK array. @@ -354,23 +386,23 @@ mod mlkem_tests { // just to check our array index math, make sure we know how to extract the public key ek from the sk bytes // and that it loads properly and gives the same key. - let pk2_encoded: &[u8] = &sk_encoded[384*MLKEM512_k .. 768*MLKEM512_k + 32]; + let pk2_encoded: &[u8] = &sk_encoded[384 * MLKEM512_k..768 * MLKEM512_k + 32]; let pk2 = MLKEM512PublicKey::from_bytes(pk2_encoded).unwrap(); assert_eq!(pk1, pk2); // flip some bits in the range that contains ek, but in a way that still results in a valid public key ek #[allow(non_upper_case_globals)] const MLKEM512_k: usize = 2; - sk_encoded[384*MLKEM512_k + 2] ^= 0x0F; + sk_encoded[384 * MLKEM512_k + 2] ^= 0x0F; // check that this is still a valid public key, but different from pk1 - let pk3_encoded: &[u8] = &sk_encoded[384*MLKEM512_k .. 768*MLKEM512_k + 32]; + let pk3_encoded: &[u8] = &sk_encoded[384 * MLKEM512_k..768 * MLKEM512_k + 32]; let pk3 = MLKEM512PublicKey::from_bytes(pk3_encoded).unwrap(); assert_ne!(pk1, pk3); // Now for the important part: sk will refuse to load with a KEMError::ConsistencyCheckFailed match MLKEM512PrivateKey::from_bytes(&sk_encoded) { - Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ }, + Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ } Err(e) => panic!("expected ConsistencyCheckFailed, got {:?}", e), Ok(_) => panic!("expected ConsistencyCheckFailed, got Ok()"), } @@ -402,18 +434,21 @@ mod mlkem_tests { /// cest that a corrupted ct returns the implicit rejection value K_bar = J(z||c) fn test_implicit_rejection() { let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3 + &hex::decode( + "49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3 99E3246884181F8E1DD44E0C7629093330221FD67D9B7D6E1510B2DBAD8762F7 - ").unwrap(), + ", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (pk, sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); // encaps let (_ss, ct) = MLKEM512::encaps(&pk).unwrap(); - // decaps with busted ciphertext let mut busted_ciphertext = ct.clone(); busted_ciphertext[17] ^= 0xFF; @@ -429,13 +464,12 @@ mod mlkem_tests { shake.absorb(&seed.ref_to_bytes()[32..64]); shake.absorb(&busted_ciphertext); let mut buf = [0u8; 32]; - _ = shake.squeeze_out(&mut buf); + _ = shake.squeeze_out(&mut buf); assert_eq!(ss.ref_to_bytes(), buf); - }, + } _ => panic!("This should have succeeded but with the wrong ss."), } - } #[test] @@ -443,7 +477,6 @@ mod mlkem_tests { /// /// This test satisfies testing condition #1 in the Decapsulation Input checks in FIPS 203 section 7.3 fn test_boundary_conditions() { - // ct too long / too short // // satisfies testing condition #1 in the Decapsulation Input checks in FIPS 203 section 7.3 @@ -453,11 +486,11 @@ mod mlkem_tests { // MLKEM512 let (pk, sk) = MLKEM512::keygen().unwrap(); - let (_ss, ct) = MLKEM512::encaps(&pk).unwrap(); + let (_ss, ct) = MLKEM512::encaps(&pk).unwrap(); // too short - match MLKEM512::decaps(&sk, &ct[..MLKEM512_CT_LEN-1]) { - Err(KEMError::LengthError(_)) => { /* good */ }, + match MLKEM512::decaps(&sk, &ct[..MLKEM512_CT_LEN - 1]) { + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } // too long @@ -465,17 +498,17 @@ mod mlkem_tests { ct_too_long[..MLKEM512_CT_LEN].copy_from_slice(&ct); ct_too_long[MLKEM512_CT_LEN..].copy_from_slice(&[1u8, 0u8]); match MLKEM512::decaps(&sk, &ct_too_long) { - Err(KEMError::LengthError(_)) => { /* good */ }, + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } // MLKEM768 let (pk, sk) = MLKEM768::keygen().unwrap(); - let (_ss, ct) = MLKEM768::encaps(&pk).unwrap(); + let (_ss, ct) = MLKEM768::encaps(&pk).unwrap(); // too short - match MLKEM768::decaps(&sk, &ct[..MLKEM512_CT_LEN-1]) { - Err(KEMError::LengthError(_)) => { /* good */ }, + match MLKEM768::decaps(&sk, &ct[..MLKEM512_CT_LEN - 1]) { + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } // too long @@ -483,17 +516,17 @@ mod mlkem_tests { ct_too_long[..MLKEM768_CT_LEN].copy_from_slice(&ct); ct_too_long[MLKEM768_CT_LEN..].copy_from_slice(&[1u8, 0u8]); match MLKEM768::decaps(&sk, &ct_too_long) { - Err(KEMError::LengthError(_)) => { /* good */ }, + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } // MLKEM1024 let (pk, sk) = MLKEM1024::keygen().unwrap(); - let (_ss, ct) = MLKEM1024::encaps(&pk).unwrap(); + let (_ss, ct) = MLKEM1024::encaps(&pk).unwrap(); // too short - match MLKEM1024::decaps(&sk, &ct[..MLKEM1024_CT_LEN-1]) { - Err(KEMError::LengthError(_)) => { /* good */ }, + match MLKEM1024::decaps(&sk, &ct[..MLKEM1024_CT_LEN - 1]) { + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } // too long @@ -501,7 +534,7 @@ mod mlkem_tests { ct_too_long[..MLKEM1024_CT_LEN].copy_from_slice(&ct); ct_too_long[MLKEM1024_CT_LEN..].copy_from_slice(&[1u8, 0u8]); match MLKEM1024::decaps(&sk, &ct_too_long) { - Err(KEMError::LengthError(_)) => { /* good */ }, + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } } @@ -520,7 +553,7 @@ mod mlkem_tests { let p = Polynomial::new(); assert_eq!(format!("{:?}", p), "Polynomial (data masked)"); } - + #[test] fn keypair_consistency_check() { // this is common to all parameter sets, so I'll just test MLKEM512 @@ -532,11 +565,11 @@ mod mlkem_tests { // failure case: different but valid key let (pk2, sk2) = MLKEM512::keygen().unwrap(); match MLKEM512::keypair_consistency_check(&pk, &sk2) { - Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ }, + Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ } _ => panic!("Expected error for different key"), }; match MLKEM512::keypair_consistency_check(&pk2, &sk) { - Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ }, + Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ } _ => panic!("Expected error for different key"), }; @@ -545,17 +578,18 @@ mod mlkem_tests { pk_bytes[17] ^= 0x01; let pk2 = MLKEM512PublicKey::from_bytes(&pk_bytes).unwrap(); match MLKEM512::keypair_consistency_check(&pk2, &sk) { - Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ }, + Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ } _ => panic!("Expected error for different key"), }; } #[test] fn test_expanded_keys() { - use bouncycastle_mlkem::{MLKEM512, MLKEM512PublicKeyExpanded, MLKEM512PrivateKeyExpanded}; - use bouncycastle_mlkem::{MLKEM768, MLKEM768PublicKeyExpanded, MLKEM768PrivateKeyExpanded}; - use bouncycastle_mlkem::{MLKEM1024, MLKEM1024PublicKeyExpanded, MLKEM1024PrivateKeyExpanded}; - + use bouncycastle_mlkem::{MLKEM512, MLKEM512PrivateKeyExpanded, MLKEM512PublicKeyExpanded}; + use bouncycastle_mlkem::{MLKEM768, MLKEM768PrivateKeyExpanded, MLKEM768PublicKeyExpanded}; + use bouncycastle_mlkem::{ + MLKEM1024, MLKEM1024PrivateKeyExpanded, MLKEM1024PublicKeyExpanded, + }; /*** ML-KEM-512 ***/ @@ -571,7 +605,6 @@ mod mlkem_tests { }; assert_eq!(ss, ss1); - /*** ML-KEM-768 ***/ let (pk, sk) = MLKEM768::keygen().unwrap(); @@ -586,7 +619,6 @@ mod mlkem_tests { }; assert_eq!(ss, ss1); - /*** ML-KEM-1024 ***/ let (pk, sk) = MLKEM1024::keygen().unwrap(); diff --git a/crypto/mlkem_lowmemory/benches/mlkem_benches.rs b/crypto/mlkem_lowmemory/benches/mlkem_benches.rs index a708f3e..1ecd65a 100644 --- a/crypto/mlkem_lowmemory/benches/mlkem_benches.rs +++ b/crypto/mlkem_lowmemory/benches/mlkem_benches.rs @@ -1,9 +1,12 @@ -use criterion::{Criterion, criterion_group, criterion_main}; use bouncycastle_core::key_material::{KeyMaterial512, KeyType}; -use std::hint::black_box; use bouncycastle_core::traits::KEM; use bouncycastle_hex as hex; -use bouncycastle_mlkem_lowmemory::{MLKEMTrait, MLKEM1024, MLKEM1024_CT_LEN, MLKEM512, MLKEM512_CT_LEN, MLKEM768, MLKEM768_CT_LEN, MLKEM_RND_LEN}; +use bouncycastle_mlkem_lowmemory::{ + MLKEM_RND_LEN, MLKEM512, MLKEM512_CT_LEN, MLKEM768, MLKEM768_CT_LEN, MLKEM1024, + MLKEM1024_CT_LEN, MLKEMTrait, +}; +use criterion::{Criterion, criterion_group, criterion_main}; +use std::hint::black_box; fn bench_mlkem_keygen(c: &mut Criterion) { let mut group = c.benchmark_group("KeyGen"); @@ -18,11 +21,11 @@ fn bench_mlkem_keygen(c: &mut Criterion) { group.throughput(criterion::Throughput::Elements(seeds.len() as u64)); group.bench_function("ML-KEM-512_lowmemory", |b| { - b.iter(|| { - for seed in seeds.iter() { - black_box(MLKEM512::keygen_from_seed(seed)).unwrap(); - } - }) + b.iter(|| { + for seed in seeds.iter() { + black_box(MLKEM512::keygen_from_seed(seed)).unwrap(); + } + }) }); group.bench_function("ML-KEM-768_lowmemory", |b| { @@ -50,12 +53,16 @@ fn bench_mlkem_encaps(c: &mut Criterion) { // set up the seeds outside of the timing loop // Doing different seeds so that the CPU doesn't cache them or do too much branch prediction let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); // create a vector of signing nonces so that we're not measuring the time of the RNG const NUM_ELEMS: usize = 256; @@ -77,7 +84,6 @@ fn bench_mlkem_encaps(c: &mut Criterion) { }) }); - /*** ML-KEM-768 ***/ let (pk, _sk) = MLKEM768::keygen_from_seed(&seed).unwrap(); @@ -113,12 +119,16 @@ fn bench_mlkem_decaps(c: &mut Criterion) { // set up the seeds outside of the timing loop // Doing different seeds so that the CPU doesn't cache them or do too much branch prediction let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); const NUM_ELEMS: usize = 256; @@ -126,7 +136,7 @@ fn bench_mlkem_decaps(c: &mut Criterion) { let (pk, sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); // create a bunch of ciphertexts to decaps - let mut cts = [ [0u8; MLKEM512_CT_LEN]; NUM_ELEMS]; + let mut cts = [[0u8; MLKEM512_CT_LEN]; NUM_ELEMS]; for i in 0..NUM_ELEMS { // create each ct with a unique nonce // encaps_internal() returns (ss, ct) ... we only want ct, hence the ".1" @@ -138,7 +148,7 @@ fn bench_mlkem_decaps(c: &mut Criterion) { group.bench_function("ML-KEM-512_lowmemory", |b| { b.iter(|| { for i in 0..NUM_ELEMS { - _ = black_box( MLKEM512::decaps(&sk, &cts[i]) ); + _ = black_box(MLKEM512::decaps(&sk, &cts[i])); } }) }); @@ -147,7 +157,7 @@ fn bench_mlkem_decaps(c: &mut Criterion) { let (pk, sk) = MLKEM768::keygen_from_seed(&seed).unwrap(); // create a bunch of ciphertexts to decaps - let mut cts = [ [0u8; MLKEM768_CT_LEN]; NUM_ELEMS]; + let mut cts = [[0u8; MLKEM768_CT_LEN]; NUM_ELEMS]; for i in 0..NUM_ELEMS { // create each ct with a unique nonce // encaps_internal() returns (ss, ct) ... we only want ct, hence the ".1" @@ -159,7 +169,7 @@ fn bench_mlkem_decaps(c: &mut Criterion) { group.bench_function("ML-KEM-768_lowmemory", |b| { b.iter(|| { for i in 0..NUM_ELEMS { - _ = black_box( MLKEM768::decaps(&sk, &cts[i]) ); + _ = black_box(MLKEM768::decaps(&sk, &cts[i])); } }) }); @@ -168,7 +178,7 @@ fn bench_mlkem_decaps(c: &mut Criterion) { let (pk, sk) = MLKEM1024::keygen_from_seed(&seed).unwrap(); // create a bunch of ciphertexts to decaps - let mut cts = [ [0u8; MLKEM1024_CT_LEN]; NUM_ELEMS]; + let mut cts = [[0u8; MLKEM1024_CT_LEN]; NUM_ELEMS]; for i in 0..NUM_ELEMS { // create each ct with a unique nonce // encaps_internal() returns (ss, ct) ... we only want ct, hence the ".1" @@ -180,7 +190,7 @@ fn bench_mlkem_decaps(c: &mut Criterion) { group.bench_function("ML-KEM-1024_lowmemory", |b| { b.iter(|| { for i in 0..NUM_ELEMS { - _ = black_box( MLKEM1024::decaps(&sk, &cts[i]) ); + _ = black_box(MLKEM1024::decaps(&sk, &cts[i])); } }) }); diff --git a/crypto/mlkem_lowmemory/src/aux_functions.rs b/crypto/mlkem_lowmemory/src/aux_functions.rs index a8784a6..3ba7e1f 100644 --- a/crypto/mlkem_lowmemory/src/aux_functions.rs +++ b/crypto/mlkem_lowmemory/src/aux_functions.rs @@ -1,7 +1,7 @@ //! Implements auxiliary functions for ML-DSA as defined in Section 7 of FIPS 204. use crate::mlkem::{N, q, q_inv}; -use crate::polynomial::{Polynomial}; +use crate::polynomial::Polynomial; use bouncycastle_core::traits::XOF; use bouncycastle_sha3::{SHAKE128, SHAKE256}; @@ -14,7 +14,7 @@ pub(crate) fn byte_encode(F: &Polynomial) let mut B = [0u8; PACK_LEN]; - for i in 0 .. N { + for i in 0..N { let mut alpha = F[i]; // For efficiency, the library is happy to work with values outside the range [0..q], @@ -28,8 +28,7 @@ pub(crate) fn byte_encode(F: &Polynomial) // 4: 𝑏[𝑖⋅𝑑 + 𝑗] ← 𝑎 mod 2 // constant-time note: yes, % is not constant-time, // but all of the values in (i*d + j) % 8 are loop indices and not part of the secret key. - B[(i*d + j)/8] |= tmp << ((i*d + j) % 8); - + B[(i * d + j) / 8] |= tmp << ((i * d + j) % 8); // 5: 𝑎 ← (𝑎 − 𝑏[𝑖⋅𝑑 + 𝑗])/2 // ▷ note 𝑎 − 𝑏[𝑖⋅𝑑 + 𝑗] is always even @@ -59,11 +58,11 @@ pub(crate) fn byte_decode(B: &[u8; PACK_L // 3: F[i] = SUM_j=0..d-1{ 𝑏[𝑖 ⋅ 𝑑 + 𝑗] ⋅ 2𝑗 } mod m for j in 0..d { // select the next bit, according to bitcount, then shift it up by j - F[i] |= (((B[(i*d + j)/8] >> (i*d + j)%8) & 1) as i16) << j; // there's supposed to be a `mod m` here, but that shouldn't matter; we'll check it below anyway. + F[i] |= (((B[(i * d + j) / 8] >> (i * d + j) % 8) & 1) as i16) << j; // there's supposed to be a `mod m` here, but that shouldn't matter; we'll check it below anyway. } // assert the mod m debug_assert!(F[i] >= 0); - debug_assert!(F[i] <= if d<12 {2< Polynomial { // 6: 𝑑1 ← 𝐶[0] + 256 ⋅ (𝐶[1] mod 16) // ▷ 0 ≤ 𝑑1 < 2^12 - let d1: i16 = (C[idx+0] as i16) | ((C[idx+1] as i32) << 8) as i16 & 0xFFF; + let d1: i16 = (C[idx + 0] as i16) | ((C[idx + 1] as i32) << 8) as i16 & 0xFFF; debug_assert!(d1 < 2 << 12); // 7: 𝑑2 ← ⌊𝐶[1]/16⌋ + 16 ⋅ 𝐶[2] // ▷ 0 ≤ 𝑑2 < 2^12 - let d2: i16 = ((C[idx+1] as i16) >> 4) | ((C[idx+2] as i32) << 4) as i16 & 0xFFF; + let d2: i16 = ((C[idx + 1] as i16) >> 4) | ((C[idx + 2] as i32) << 4) as i16 & 0xFFF; debug_assert!(d2 < 2 << 12); // 8: if 𝑑1 < 𝑞 then @@ -149,8 +148,8 @@ pub(crate) fn sample_poly_cbd(bytes: &[u8]) -> Polynomial { match eta { 2 => { - for i in 0..N/8 { - let t = u32::from_le_bytes(bytes[4*i .. 4*i + 4].try_into().unwrap()); + for i in 0..N / 8 { + let t = u32::from_le_bytes(bytes[4 * i..4 * i + 4].try_into().unwrap()); let mut d = t & 0x55555555; d += (t >> 1) & 0x55555555; for j in 0..8usize { @@ -165,7 +164,7 @@ pub(crate) fn sample_poly_cbd(bytes: &[u8]) -> Polynomial { } } 3 => { - for i in 0..N/4 { + for i in 0..N / 4 { let t = little_endian_to_u24(bytes, 3 * i); let mut d = t & 0x00249249; d += (t >> 1) & 0x00249249; @@ -190,7 +189,6 @@ pub(crate) fn sample_poly_cbd(bytes: &[u8]) -> Polynomial { /// SamplePolyCBD𝜂1(PRF𝜂1 (𝜎, 𝑁 )) /// Performs both the PRF and SamplePolyCBD steps pub(crate) fn sample_poly_CBD(b: &[u8; 32], n: u8) -> Polynomial { - // Alg 13: 9: 𝐬[𝑖] ← SamplePolyCBD𝜂1(PRF𝜂1 (𝜎, 𝑁 )) // ▷ 𝐬[𝑖] ∈ ℤ256 sampled from CBD match eta { @@ -206,7 +204,7 @@ pub(crate) fn sample_poly_CBD(b: &[u8; 32], n: u8) -> Polynomial }; sample_poly_cbd::(&buf) - }, + } 3 => { let buf = { let mut xof = SHAKE256::new(); @@ -218,8 +216,8 @@ pub(crate) fn sample_poly_CBD(b: &[u8; 32], n: u8) -> Polynomial }; sample_poly_cbd::(&buf) - }, - _ => unreachable!() + } + _ => unreachable!(), } } @@ -274,13 +272,20 @@ pub(super) fn cond_sub_q(a: i16) -> i16 { tmp + ((tmp >> 15) & q) } - /// Multiplication of polynomials in Zq\[X]/(X^2-zeta) /// used for multiplication of elements in Rq in NTT domain /// /// Borrowed from: /// https://github.com/pq-crystals/kyber/blob/main/ref/ntt.c#L139 -pub(crate) fn ntt_base_mult(r: &mut [i16], off: usize, a0: i16, a1: i16, b0: i16, b1: i16, zeta: i16) { +pub(crate) fn ntt_base_mult( + r: &mut [i16], + off: usize, + a0: i16, + a1: i16, + b0: i16, + b1: i16, + zeta: i16, +) { let mut out_val0 = mul_mont(a1, b1); out_val0 = mul_mont(out_val0, zeta); out_val0 += mul_mont(a0, b0); diff --git a/crypto/mlkem_lowmemory/src/lib.rs b/crypto/mlkem_lowmemory/src/lib.rs index 32b3254..137afb7 100644 --- a/crypto/mlkem_lowmemory/src/lib.rs +++ b/crypto/mlkem_lowmemory/src/lib.rs @@ -224,20 +224,16 @@ //! constant-time after compilation. #![no_std] - #![forbid(missing_docs)] - #![forbid(unsafe_code)] #![allow(incomplete_features)] // needed because currently generic_const_exprs is experimental #![feature(generic_const_exprs)] #![feature(adt_const_params)] - // These are because I'm matching variable names exactly against FIPS 204, for example both 'K' and 'k', // or 'A' and 'a' are used and have specific meanings. // But need to tell the rust linter to not care. #![allow(non_snake_case)] #![allow(non_upper_case_globals)] - // so I can use private traits to hide internal stuff that needs to be generic within the // MLKEM implementation, but I don't want accessed from outside, such as FIPS-internal functions. #![allow(private_bounds)] @@ -250,28 +246,30 @@ use bouncycastle_core::key_material::KeyMaterialTrait; // todo -- crucible tests +mod aux_functions; +mod low_memory_helpers; pub mod mlkem; mod mlkem_keys; mod polynomial; -mod aux_functions; -mod low_memory_helpers; /*** Exported types ***/ -pub use mlkem::{MLKEMTrait, MLKEM, MLKEM512, MLKEM768, MLKEM1024}; +pub use mlkem::{MLKEM, MLKEM512, MLKEM768, MLKEM1024, MLKEMTrait}; +pub use mlkem_keys::{ + MLKEM512PrivateKey, MLKEM768PrivateKey, MLKEM1024PrivateKey, MLKEMSeedPrivateKey, +}; +pub use mlkem_keys::{MLKEM512PublicKey, MLKEM768PublicKey, MLKEM1024PublicKey, MLKEMPublicKey}; pub use mlkem_keys::{MLKEMPrivateKeyTrait, MLKEMPublicKeyTrait}; -pub use mlkem_keys::{MLKEMPublicKey, MLKEM512PublicKey, MLKEM768PublicKey, MLKEM1024PublicKey}; -pub use mlkem_keys::{MLKEMSeedPrivateKey, MLKEM512PrivateKey, MLKEM768PrivateKey, MLKEM1024PrivateKey}; /*** Exported constants ***/ pub use mlkem::ML_KEM_512_NAME; pub use mlkem::ML_KEM_768_NAME; pub use mlkem::ML_KEM_1024_NAME; -pub use mlkem::{MLKEM_SEED_LEN, MLKEM_SS_LEN, MLKEM_RND_LEN}; +pub use mlkem::{MLKEM_RND_LEN, MLKEM_SEED_LEN, MLKEM_SS_LEN}; -pub use mlkem::{MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM512_CT_LEN}; -pub use mlkem::{MLKEM768_PK_LEN, MLKEM768_SK_LEN, MLKEM768_CT_LEN}; -pub use mlkem::{MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, MLKEM1024_CT_LEN}; +pub use mlkem::{MLKEM512_CT_LEN, MLKEM512_PK_LEN, MLKEM512_SK_LEN}; +pub use mlkem::{MLKEM768_CT_LEN, MLKEM768_PK_LEN, MLKEM768_SK_LEN}; +pub use mlkem::{MLKEM1024_CT_LEN, MLKEM1024_PK_LEN, MLKEM1024_SK_LEN}; // re-export just so it's visible to unit tests -pub use polynomial::Polynomial; \ No newline at end of file +pub use polynomial::Polynomial; diff --git a/crypto/mlkem_lowmemory/src/low_memory_helpers.rs b/crypto/mlkem_lowmemory/src/low_memory_helpers.rs index a7ab96d..d6187b4 100644 --- a/crypto/mlkem_lowmemory/src/low_memory_helpers.rs +++ b/crypto/mlkem_lowmemory/src/low_memory_helpers.rs @@ -3,8 +3,8 @@ //! what it needs in pieces, which generally means handling the matrices and vectors row-wise or entry-wise. use crate::aux_functions::{byte_decode, byte_encode, sample_ntt, sample_poly_CBD}; -use crate::polynomial::{Polynomial}; -use crate::mlkem::{q, N, POLY_BYTES}; +use crate::mlkem::{N, POLY_BYTES, q}; +use crate::polynomial::Polynomial; /// Computes the element [i,j] of the A_hat public matrix pub(crate) fn expandA_elem(rho: &[u8; 32], i: usize, j: usize) -> Polynomial { @@ -27,10 +27,10 @@ pub(crate) fn compute_A_hat_dot_s_hat( A_i0 }; - for j in 1 .. k { + for j in 1..k { let mut A_ij = expandA_elem(rho, row, j); let mut s_j = sample_poly_CBD::(sigma, j as u8); - s_j.ntt(); // now s_hat_j + s_j.ntt(); // now s_hat_j A_ij.base_mult_montgomery(&s_j); t_hat_i.add(&A_ij); } @@ -46,7 +46,7 @@ pub(crate) fn compute_A_hat_dot_s_hat( pub(crate) fn compute_A_hat_dot_y_hat( rho: &[u8; 32], r: &[u8; 32], - row: usize + row: usize, ) -> Polynomial { // 4: for (𝑖 ← 0; 𝑖 < 𝑘; 𝑖++) // ▷ re-generate matrix 𝐀 ∈ (ℤ256_𝑞 )𝑘×𝑘 sampled in Alg. 13 @@ -68,7 +68,7 @@ pub(crate) fn compute_A_hat_dot_y_hat( A_0i }; - for j in 1 .. k { + for j in 1..k { let mut A_ji = expandA_elem(&rho, j, row); let mut y_j = sample_poly_CBD::(r, /*N*/ j as u8); y_j.ntt(); @@ -85,7 +85,7 @@ pub(crate) fn compute_A_hat_dot_y_hat( pub(crate) fn compute_t_hat_dot_y_hat_row( r: &[u8; 32], t_hat_i: &Polynomial, - row: usize + row: usize, ) -> Polynomial { let mut y_i = sample_poly_CBD::(r, /*N*/ row as u8); y_i.ntt(); @@ -95,23 +95,33 @@ pub(crate) fn compute_t_hat_dot_y_hat_row( y_i } -pub(crate) fn pack_t_hat_row(t_hat_i: &Polynomial, row: usize, t_hat_packed: &mut [u8; T_PACKED_LEN]) { - t_hat_packed[row * POLY_BYTES .. (row + 1) * POLY_BYTES].copy_from_slice( - &byte_encode::<12, POLY_BYTES>(&t_hat_i) - ); +pub(crate) fn pack_t_hat_row( + t_hat_i: &Polynomial, + row: usize, + t_hat_packed: &mut [u8; T_PACKED_LEN], +) { + t_hat_packed[row * POLY_BYTES..(row + 1) * POLY_BYTES] + .copy_from_slice(&byte_encode::<12, POLY_BYTES>(&t_hat_i)); } -pub(crate) fn unpack_t_hat_row(t_hat_packed: &[u8; T_PACKED_LEN], row: usize) -> Polynomial { +pub(crate) fn unpack_t_hat_row( + t_hat_packed: &[u8; T_PACKED_LEN], + row: usize, +) -> Polynomial { byte_decode::<12, POLY_BYTES>( - t_hat_packed[row * POLY_BYTES .. (row + 1)*POLY_BYTES].try_into().unwrap()) + t_hat_packed[row * POLY_BYTES..(row + 1) * POLY_BYTES].try_into().unwrap(), + ) } -pub(crate) fn pack_s_hat_row(s_hat_i: &Polynomial, row: usize, s_hat_packed: &mut [u8]) { - debug_assert!(s_hat_packed.len() >= k*POLY_BYTES); - - s_hat_packed[row*POLY_BYTES .. (row+1)*POLY_BYTES].copy_from_slice(&byte_encode::<12, POLY_BYTES>( - s_hat_i, - )); +pub(crate) fn pack_s_hat_row( + s_hat_i: &Polynomial, + row: usize, + s_hat_packed: &mut [u8], +) { + debug_assert!(s_hat_packed.len() >= k * POLY_BYTES); + + s_hat_packed[row * POLY_BYTES..(row + 1) * POLY_BYTES] + .copy_from_slice(&byte_encode::<12, POLY_BYTES>(s_hat_i)); } /// This is an optimized version of @@ -121,7 +131,7 @@ pub(crate) fn pack_s_hat_row(s_hat_i: &Polynomial, row: usize, s pub(crate) fn compress_u_row( u_i: Polynomial, row: usize, - ct: &mut [u8; CT_LEN] + ct: &mut [u8; CT_LEN], ) { // make sure we have received a dv assert!(du == 10 || du == 11); @@ -130,66 +140,61 @@ pub(crate) fn compress_u_row( // let mut u_i = u_i.clone(); // u_i.conditional_sub_q(); - // figure out where in the ct array we're going to write to // each of the N i16's will take du bits, so a polynomial takes N * du bits, then we have k of them let start: usize = row * (N * (du as usize) / 8); let end: usize = (row + 1) * (N * (du as usize) / 8); - let out = &mut ct[start .. end]; + let out = &mut ct[start..end]; let mut idx = 0; match du { - 10 => { // MLKEM512 and MLKEM 768 + 10 => { + // MLKEM512 and MLKEM 768 let mut t = [0i16; 4]; - for j in 0..N/4 { - // fill the temp array t - for (l, item) in t.iter_mut().enumerate() { - *item = (((((u_i[4 * j + l] as u32) << 10) as i32 - + (q as i32 / 2)) - / q as i32) - & 0x3FF) as i16; - } - - out[idx] = t[0] as u8; - out[idx + 1] = ((t[0] >> 8) | (t[1] << 2)) as u8; - out[idx + 2] = ((t[1] >> 6) | (t[2] << 4)) as u8; - out[idx + 3] = ((t[2] >> 4) | (t[3] << 6)) as u8; - out[idx + 4] = (t[3] >> 2) as u8; - idx += 5; + for j in 0..N / 4 { + // fill the temp array t + for (l, item) in t.iter_mut().enumerate() { + *item = (((((u_i[4 * j + l] as u32) << 10) as i32 + (q as i32 / 2)) / q as i32) + & 0x3FF) as i16; } - }, + + out[idx] = t[0] as u8; + out[idx + 1] = ((t[0] >> 8) | (t[1] << 2)) as u8; + out[idx + 2] = ((t[1] >> 6) | (t[2] << 4)) as u8; + out[idx + 3] = ((t[2] >> 4) | (t[3] << 6)) as u8; + out[idx + 4] = (t[3] >> 2) as u8; + idx += 5; + } + } 11 => { let mut t = [0i16; 8]; - for j in 0..N/8 { - for (l, item) in t.iter_mut().enumerate() { - *item = (((((u_i[8 * j + l] as u32) << 11) as i32 - + (q as i32 / 2)) - / q as i32) - & 0x7FF) as i16; - } - - out[idx] = t[0] as u8; - out[idx + 1] = ((t[0] >> 8) | (t[1] << 3)) as u8; - out[idx + 2] = ((t[1] >> 5) | (t[2] << 6)) as u8; - out[idx + 3] = (t[2] >> 2) as u8; - out[idx + 4] = ((t[2] >> 10) | (t[3] << 1)) as u8; - out[idx + 5] = ((t[3] >> 7) | (t[4] << 4)) as u8; - out[idx + 6] = ((t[4] >> 4) | (t[5] << 7)) as u8; - out[idx + 7] = (t[5] >> 1) as u8; - out[idx + 8] = ((t[5] >> 9) | (t[6] << 2)) as u8; - out[idx + 9] = ((t[6] >> 6) | (t[7] << 5)) as u8; - out[idx + 10] = (t[7] >> 3) as u8; - idx += 11; + for j in 0..N / 8 { + for (l, item) in t.iter_mut().enumerate() { + *item = (((((u_i[8 * j + l] as u32) << 11) as i32 + (q as i32 / 2)) / q as i32) + & 0x7FF) as i16; } - }, + + out[idx] = t[0] as u8; + out[idx + 1] = ((t[0] >> 8) | (t[1] << 3)) as u8; + out[idx + 2] = ((t[1] >> 5) | (t[2] << 6)) as u8; + out[idx + 3] = (t[2] >> 2) as u8; + out[idx + 4] = ((t[2] >> 10) | (t[3] << 1)) as u8; + out[idx + 5] = ((t[3] >> 7) | (t[4] << 4)) as u8; + out[idx + 6] = ((t[4] >> 4) | (t[5] << 7)) as u8; + out[idx + 7] = (t[5] >> 1) as u8; + out[idx + 8] = ((t[5] >> 9) | (t[6] << 2)) as u8; + out[idx + 9] = ((t[6] >> 6) | (t[7] << 5)) as u8; + out[idx + 10] = (t[7] >> 3) as u8; + idx += 11; + } + } _ => unreachable!(), } } - pub(crate) fn unpack_ciphertext_u_row( row: usize, - ct: &[u8; CT_LEN] + ct: &[u8; CT_LEN], ) -> Polynomial { let mut u_i = Polynomial::new(); @@ -200,82 +205,78 @@ pub(crate) fn unpack_ciphertext_u_row( // each of the N i16's will take du bits, so a polynomial takes N * du bits, then we have k of them let start: usize = row * (N * (du as usize) / 8); let end: usize = (row + 1) * (N * (du as usize) / 8); - let compressed_u_i = &ct[start .. end]; + let compressed_u_i = &ct[start..end]; let mut idx = 0; match du { - 10 => { // MLKEM512 and MLKEM768 + 10 => { + // MLKEM512 and MLKEM768 let mut t = [0i16; 4]; - for j in 0..(N/4) { - t[0] = ((compressed_u_i[idx] as u16) - | (compressed_u_i[idx + 1] as u16) << 8) - as i16; + for j in 0..(N / 4) { + t[0] = + ((compressed_u_i[idx] as u16) | (compressed_u_i[idx + 1] as u16) << 8) as i16; t[1] = (((compressed_u_i[idx + 1] as u16) >> 2) - | (compressed_u_i[idx + 2] as u16) << 6) - as i16; + | (compressed_u_i[idx + 2] as u16) << 6) as i16; t[2] = (((compressed_u_i[idx + 2] as u16) >> 4) - | (compressed_u_i[idx + 3] as u16) << 4) - as i16; + | (compressed_u_i[idx + 3] as u16) << 4) as i16; t[3] = (((compressed_u_i[idx + 3] as u16) >> 6) - | (compressed_u_i[idx + 4] as u16) << 2) - as i16; + | (compressed_u_i[idx + 4] as u16) << 2) as i16; idx += 5; for (l, item) in t.iter().enumerate() { - u_i[4 * j + l] = - ((((*item & 0x3FF) as i32) * (q as i32) + 512) >> 10) as i16; + u_i[4 * j + l] = ((((*item & 0x3FF) as i32) * (q as i32) + 512) >> 10) as i16; } } - }, - 11 => { // MLKEM1024 + } + 11 => { + // MLKEM1024 let mut t = [0i16; 8]; - for j in 0..N/8 { - t[0] = (compressed_u_i[idx] as i32 - | ((compressed_u_i[idx + 1] as u16) as i32) << 8) + for j in 0..N / 8 { + t[0] = (compressed_u_i[idx] as i32 | ((compressed_u_i[idx + 1] as u16) as i32) << 8) as i16; t[1] = ((compressed_u_i[idx + 1] >> 3) as i32 - | ((compressed_u_i[idx + 2] as u16) as i32) << 5) - as i16; + | ((compressed_u_i[idx + 2] as u16) as i32) << 5) as i16; t[2] = ((compressed_u_i[idx + 2] >> 6) as i32 | ((compressed_u_i[idx + 3] as u16) as i32) << 2 | (((compressed_u_i[idx + 4] as i32) << 10) as u16) as i32) as i16; t[3] = ((compressed_u_i[idx + 4] >> 1) as i32 - | ((compressed_u_i[idx + 5] as u16) as i32) << 7) - as i16; + | ((compressed_u_i[idx + 5] as u16) as i32) << 7) as i16; t[4] = ((compressed_u_i[idx + 5] >> 4) as i32 - | ((compressed_u_i[idx + 6] as u16) as i32) << 4) - as i16; + | ((compressed_u_i[idx + 6] as u16) as i32) << 4) as i16; t[5] = ((compressed_u_i[idx + 6] >> 7) as i32 | ((compressed_u_i[idx + 7] as u16) as i32) << 1 | (((compressed_u_i[idx + 8] as i32) << 9) as u16) as i32) as i16; t[6] = ((compressed_u_i[idx + 8] >> 2) as i32 - | ((compressed_u_i[idx + 9] as u16) as i32) << 6) - as i16; + | ((compressed_u_i[idx + 9] as u16) as i32) << 6) as i16; t[7] = ((compressed_u_i[idx + 9] >> 5) as i32 | ((compressed_u_i[idx + 10] as u16) as i32) << 3) as i16; idx += 11; for (l, item) in t.iter().enumerate() { - u_i[8 * j + l] = - ((((*item & 0x7FF) as i32) * (q as i32) + 1024) >> 11) as i16; + u_i[8 * j + l] = ((((*item & 0x7FF) as i32) * (q as i32) + 1024) >> 11) as i16; } } - }, + } _ => unreachable!(), } u_i } -pub(crate) fn unpack_ciphertext_v( - c: &[u8; CT_LEN] +pub(crate) fn unpack_ciphertext_v< + const k: usize, + const CT_LEN: usize, + const du: i16, + const dv: i16, +>( + c: &[u8; CT_LEN], ) -> Polynomial { // each of the N i16's will take du bits, so a polynomial takes N * du bits, then we have k of them - let lim: usize = k* (N * (du as usize) / 8); + let lim: usize = k * (N * (du as usize) / 8); let v = Polynomial::decompress_poly::(&c[lim..]); v -} \ No newline at end of file +} diff --git a/crypto/mlkem_lowmemory/src/mlkem.rs b/crypto/mlkem_lowmemory/src/mlkem.rs index 13f9c9c..3d75cb3 100644 --- a/crypto/mlkem_lowmemory/src/mlkem.rs +++ b/crypto/mlkem_lowmemory/src/mlkem.rs @@ -1,20 +1,24 @@ //! There are no advanced features in this low memory crate that are not already documented in the standard \[bouncycastle_mlkem] crate. - -use core::marker::PhantomData; -use bouncycastle_core::errors::{KEMError}; -use bouncycastle_core::key_material::{KeyMaterial, KeyType, KeyMaterialTrait}; -use bouncycastle_core::traits::{RNG, SecurityStrength, XOF, Algorithm, Hash, KEM}; -use bouncycastle_rng::{HashDRBG_SHA512}; +use crate::aux_functions::sample_poly_CBD; +use crate::low_memory_helpers::{ + compress_u_row, compute_A_hat_dot_y_hat, compute_t_hat_dot_y_hat_row, unpack_ciphertext_u_row, + unpack_ciphertext_v, unpack_t_hat_row, +}; +use crate::mlkem_keys::{ + MLKEM512PrivateKey, MLKEM512PublicKey, MLKEM768PrivateKey, MLKEM768PublicKey, + MLKEM1024PrivateKey, MLKEM1024PublicKey, +}; +use crate::mlkem_keys::{MLKEMPrivateKeyInternalTrait, MLKEMPrivateKeyTrait}; +use crate::mlkem_keys::{MLKEMPublicKeyInternalTrait, MLKEMPublicKeyTrait}; +use crate::polynomial::Polynomial; +use bouncycastle_core::errors::KEMError; +use bouncycastle_core::key_material::{KeyMaterial, KeyMaterialTrait, KeyType}; +use bouncycastle_core::traits::{Algorithm, Hash, KEM, RNG, SecurityStrength, XOF}; +use bouncycastle_rng::HashDRBG_SHA512; use bouncycastle_sha3::{SHA3_256, SHA3_512, SHAKE256}; use bouncycastle_utils::ct::{conditional_copy_bytes, ct_eq_bytes}; -use crate::aux_functions::{sample_poly_CBD}; -use crate::low_memory_helpers::{compress_u_row, compute_A_hat_dot_y_hat, compute_t_hat_dot_y_hat_row, unpack_ciphertext_u_row, unpack_ciphertext_v, unpack_t_hat_row}; -use crate::mlkem_keys::{MLKEMPublicKeyTrait, MLKEMPublicKeyInternalTrait}; -use crate::mlkem_keys::{MLKEMPrivateKeyTrait, MLKEMPrivateKeyInternalTrait}; -use crate::mlkem_keys::{MLKEM512PublicKey, MLKEM512PrivateKey, MLKEM768PublicKey, MLKEM768PrivateKey, MLKEM1024PublicKey, MLKEM1024PrivateKey}; -use crate::polynomial::{Polynomial}; - +use core::marker::PhantomData; /*** Constants ***/ @@ -40,7 +44,6 @@ pub(crate) const q_inv: i32 = 62209; pub(crate) const ETA2: i16 = 2; pub(crate) const POLY_BYTES: usize = 384; - /* ML-KEM-512 params */ /// Length of the \[u8] holding a ML-KEM-512 public key. @@ -78,11 +81,9 @@ pub(crate) const MLKEM768_DV: i16 = 4; /// Maps to "required RBG strength (bits)" in FIPS 203 Table 2 pub(crate) const MLKEM768_LAMBDA: i16 = 192; - // internal derived values pub(crate) const MLKEM768_T_PACKED_LEN: usize = 12 * MLKEM768_k * 32; - /* ML-KEM-1024 params */ /// Length of the \[u8] holding a ML-KEM-1024 public key. @@ -100,19 +101,14 @@ pub(crate) const MLKEM1024_DV: i16 = 5; /// Maps to "required RBG strength (bits)" in FIPS 203 Table 2 pub(crate) const MLKEM1024_LAMBDA: i16 = 256; - // internal derived values pub(crate) const MLKEM1024_T_PACKED_LEN: usize = 12 * MLKEM1024_k * 32; - - // Typedefs just to make the algorithms look more like the FIPS 204 sample code. pub(crate) type G = SHA3_512; pub(crate) type H = SHA3_256; pub(crate) type J = SHAKE256; - - /*** Pub Types ***/ /// The ML-KEM-512 algorithm. @@ -190,8 +186,10 @@ pub struct MLKEM< const FULL_SK_LEN: usize, const CT_LEN: usize, const SS_LEN: usize, - PK: MLKEMPublicKeyTrait + MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + PK: MLKEMPublicKeyTrait + + MLKEMPublicKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const k: usize, const eta1: i16, const du: i16, @@ -208,35 +206,35 @@ impl< const FULL_SK_LEN: usize, const CT_LEN: usize, const SS_LEN: usize, - PK: MLKEMPublicKeyTrait + MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + PK: MLKEMPublicKeyTrait + + MLKEMPublicKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const k: usize, const eta1: i16, const du: i16, const dv: i16, const LAMBDA: i16, const T_PACKED_LEN: usize, -> MLKEM< - PK_LEN, - SK_LEN, - FULL_SK_LEN, - CT_LEN, - SS_LEN, - PK, - SK, - k, - eta1, - du, - dv, - LAMBDA, - T_PACKED_LEN, > + MLKEM< + PK_LEN, + SK_LEN, + FULL_SK_LEN, + CT_LEN, + SS_LEN, + PK, + SK, + k, + eta1, + du, + dv, + LAMBDA, + T_PACKED_LEN, + > { /// Should still be ok in FIPS mode - pub fn keygen_from_os_rng() -> Result< - (PK, SK), - KEMError, - > { + pub fn keygen_from_os_rng() -> Result<(PK, SK), KEMError> { let mut seed = KeyMaterial::<64>::new(); HashDRBG_SHA512::new_from_os().fill_keymaterial_out(&mut seed)?; // Self::keygen_internal(&seed) @@ -249,26 +247,25 @@ impl< /// the appropriate [SecurityStrength] for the requested ML-KEM parameter set. /// If you happen to have your seed in a larger KeyMaterial, you'll have to copy it using /// [KeyMaterial::from_key]. - pub(crate) fn keygen_internal( - seed: &KeyMaterial<64>, - ) -> Result< - (PK, SK), - KEMError, - > { + pub(crate) fn keygen_internal(seed: &KeyMaterial<64>) -> Result<(PK, SK), KEMError> { let sk = SK::from_keymaterial(seed)?; let pk = sk.pk(); let pk = PK::new(pk.t_hat_packed, pk.rho); // stupid conversion, but it gets around these overly-generified rust types Ok((pk, sk)) } - /// Algorithm 14 K-PKE.Encrypt(ekPKE, 𝑚, 𝑟) /// Uses the encryption key to encrypt a plaintext message using the randomness 𝑟. /// Input: encryption key ekPKE ∈ 𝔹384𝑘+32 . /// Input: message 𝑚 ∈ 𝔹32 . /// Input: randomness 𝑟 ∈ 𝔹32 . /// Output: ciphertext 𝑐 ∈ 𝔹32(𝑑𝑢𝑘+𝑑𝑣). - fn pke_encrypt(t_hat_packed: &[u8; T_PACKED_LEN], rho: &[u8; 32], m: [u8; 32], r: &[u8; 32]) -> [u8; CT_LEN] { + fn pke_encrypt( + t_hat_packed: &[u8; T_PACKED_LEN], + rho: &[u8; 32], + m: [u8; 32], + r: &[u8; 32], + ) -> [u8; CT_LEN] { let mut ct = [0u8; CT_LEN]; // 1: 𝑁 ← 0 @@ -283,9 +280,9 @@ impl< // Note: you need y_hat twice: once here at line 19, and again at line 21. // We'll just generate it twice to save the memory of holding on to it. - for i in 0 .. k { + for i in 0..k { let mut u_i = compute_A_hat_dot_y_hat::(rho, &r, i); - + let e1_i = sample_poly_CBD::(&r, (k + i) as u8); u_i.add(&e1_i); u_i.poly_reduce(); @@ -302,23 +299,25 @@ impl< let mut v = compute_t_hat_dot_y_hat_row::( &r, &unpack_t_hat_row(t_hat_packed, 0), - /*row*/ 0); + /*row*/ 0, + ); - for i in 1 .. k { + for i in 1..k { let v_i = compute_t_hat_dot_y_hat_row::( &r, &unpack_t_hat_row(t_hat_packed, i), - /*row*/ i); + /*row*/ i, + ); v.add(&v_i); } // perform polynomial addition - let e2 = sample_poly_CBD::(&r, 2*k as u8); + let e2 = sample_poly_CBD::(&r, 2 * k as u8); v.add(&e2); - + let mu = Polynomial::from_msg(m); v.add(&mu); - + v.poly_reduce(); v.compress_poly::(&mut ct[CT_LEN - (N * (dv as usize) / 8)..]); @@ -347,7 +346,7 @@ impl< /// If you think you will be clever and invent some scheme that uses a deterministic KEM, /// then you will almost certainly end up with security problems. Please don't do this. pub fn encaps_internal(ek: &PK, m: [u8; 32]) -> ([u8; 32], [u8; CT_LEN]) { - debug_assert_eq!(CT_LEN, 32*( (du as usize)*k + (dv as usize))); + debug_assert_eq!(CT_LEN, 32 * ((du as usize) * k + (dv as usize))); // 1: (𝐾, 𝑟) ← G(𝑚‖H(ek)) // ▷ derive shared secret key 𝐾 and randomness 𝑟 @@ -400,7 +399,7 @@ impl< s_hat_i }; - for i in 1 .. k { + for i in 1..k { let mut s_hat_i = dk.compute_s_hat_row(i); { let mut u_prime_i = unpack_ciphertext_u_row::(i, &ct); @@ -438,11 +437,10 @@ impl< /// Input: ciphertext 𝑐 ∈ 𝔹32(𝑑𝑢𝑘+𝑑𝑣). /// Output: shared secret key 𝐾 ∈ 𝔹32 . fn decaps_internal(dk: &SK, c: [u8; CT_LEN]) -> [u8; MLKEM_SS_LEN] { - // I have tried to keep this as clean as possible for correspondence with the FIPS, // but I have moved things around so that I can use unnamed scopes to limit how many // stack variables are alive at the same time. - + // 1: dkPKE ← dk[0 ∶ 384𝑘] ▷ extract (from KEM decaps key) the PKE decryption key // 2: ekPKE ← dk[384𝑘 ∶ 768𝑘 + 32] ▷ extract PKE encryption key // 3: ℎ ← dk[768𝑘 + 32 ∶ 768𝑘 + 64] ▷ extract hash of PKE encryption key @@ -500,7 +498,10 @@ impl< /// Alternative initialization of the streaming signer where you have your private key /// as a seed and you want to delay its expansion as late as possible for memory-usage reasons. - pub fn decaps_from_seed(seed: &KeyMaterial<64>, ct: &[u8]) -> Result, KEMError> { + pub fn decaps_from_seed( + seed: &KeyMaterial<64>, + ct: &[u8], + ) -> Result, KEMError> { let sk = SK::from_keymaterial(seed)?; Self::decaps(&sk, ct) @@ -513,29 +514,48 @@ impl< const FULL_SK_LEN: usize, const CT_LEN: usize, const SS_LEN: usize, - PK: MLKEMPublicKeyTrait + MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + PK: MLKEMPublicKeyTrait + + MLKEMPublicKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const k: usize, const eta1: i16, const du: i16, const dv: i16, const LAMBDA: i16, const T_PACKED_LEN: usize, -> MLKEMTrait for MLKEM< - PK_LEN, - SK_LEN, - FULL_SK_LEN, - CT_LEN, - SS_LEN, - PK, - SK, - k, - eta1, - du, - dv, - LAMBDA, - T_PACKED_LEN, -> { +> + MLKEMTrait< + PK_LEN, + SK_LEN, + FULL_SK_LEN, + CT_LEN, + SS_LEN, + PK, + SK, + k, + eta1, + du, + dv, + LAMBDA, + T_PACKED_LEN, + > + for MLKEM< + PK_LEN, + SK_LEN, + FULL_SK_LEN, + CT_LEN, + SS_LEN, + PK, + SK, + k, + eta1, + du, + dv, + LAMBDA, + T_PACKED_LEN, + > +{ /// Imports a secret key from a seed. fn keygen_from_seed(seed: &KeyMaterial<64>) -> Result<(PK, SK), KEMError> { Self::keygen_internal(seed) @@ -549,10 +569,7 @@ impl< fn keygen_from_seed_and_encoded( seed: &KeyMaterial<64>, encoded_sk: &[u8; SK_LEN], - ) -> Result< - (PK, SK), - KEMError, - > { + ) -> Result<(PK, SK), KEMError> { let (pk, sk) = Self::keygen_internal(seed)?; let sk_from_bytes = SK::sk_decode(encoded_sk); @@ -572,10 +589,7 @@ impl< /// (in which case a keygen_from_seed is run and then the pk's compared). /// /// Returns either `()` or [KEMError::ConsistencyCheckFailed]. - fn keypair_consistency_check( - pk: &PK, - sk: &SK, - ) -> Result<(), KEMError> { + fn keypair_consistency_check(pk: &PK, sk: &SK) -> Result<(), KEMError> { let derived_pk = sk.pk(); if derived_pk.compute_hash() == pk.compute_hash() { Ok(()) @@ -592,15 +606,18 @@ pub trait MLKEMTrait< const FULL_SK_LEN: usize, const CT_LEN: usize, const SS_LEN: usize, - PK: MLKEMPublicKeyTrait + MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + PK: MLKEMPublicKeyTrait + + MLKEMPublicKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const k: usize, const eta: i16, const du: i16, const dv: i16, const LAMBDA: i16, const T_PACKED_LEN: usize, -> : Sized { +>: Sized +{ /// Imports a secret key from a seed. fn keygen_from_seed(seed: &KeyMaterial<64>) -> Result<(PK, SK), KEMError>; /// Imports a secret key from both a seed and an encoded_sk. @@ -612,10 +629,7 @@ pub trait MLKEMTrait< fn keygen_from_seed_and_encoded( seed: &KeyMaterial<64>, encoded_sk: &[u8; SK_LEN], - ) -> Result< - (PK, SK), - KEMError, - >; + ) -> Result<(PK, SK), KEMError>; /// Given a public key and a secret key, check that the public key matches the secret key. /// This is a sanity check that the public key was generated correctly from the secret key. /// @@ -624,10 +638,7 @@ pub trait MLKEMTrait< /// (in which case a keygen_from_seed is run and then the pk's compared). /// /// Returns either `()` or [KEMError::ConsistencyCheckFailed]. - fn keypair_consistency_check( - pk: &PK, - sk: &SK, - ) -> Result<(), KEMError>; + fn keypair_consistency_check(pk: &PK, sk: &SK) -> Result<(), KEMError>; } impl< @@ -636,29 +647,33 @@ impl< const FULL_SK_LEN: usize, const CT_LEN: usize, const SS_LEN: usize, - PK: MLKEMPublicKeyTrait + MLKEMPublicKeyInternalTrait, - SK: MLKEMPrivateKeyTrait + MLKEMPrivateKeyInternalTrait, + PK: MLKEMPublicKeyTrait + + MLKEMPublicKeyInternalTrait, + SK: MLKEMPrivateKeyTrait + + MLKEMPrivateKeyInternalTrait, const k: usize, const eta: i16, const du: i16, const dv: i16, const LAMBDA: i16, const T_PACKED_LEN: usize, -> KEM for MLKEM< - PK_LEN, - SK_LEN, - FULL_SK_LEN, - CT_LEN, - SS_LEN, - PK, - SK, - k, - eta, - du, - dv, - LAMBDA, - T_PACKED_LEN, -> { +> KEM + for MLKEM< + PK_LEN, + SK_LEN, + FULL_SK_LEN, + CT_LEN, + SS_LEN, + PK, + SK, + k, + eta, + du, + dv, + LAMBDA, + T_PACKED_LEN, + > +{ /// Generates a fresh key pair. fn keygen() -> Result<(PK, SK), KEMError> { Self::keygen_from_os_rng() @@ -670,26 +685,26 @@ impl< let (ss_bytes, ct) = Self::encaps_internal(pk, m); - let mut ss_keymaterial = KeyMaterial::::from_bytes_as_type(&ss_bytes, KeyType::BytesFullEntropy)?; + let mut ss_keymaterial = + KeyMaterial::::from_bytes_as_type(&ss_bytes, KeyType::BytesFullEntropy)?; ss_keymaterial.allow_hazardous_operations(); - ss_keymaterial.set_security_strength( SecurityStrength::from_bits(LAMBDA as usize) )?; + ss_keymaterial.set_security_strength(SecurityStrength::from_bits(LAMBDA as usize))?; ss_keymaterial.drop_hazardous_operations(); Ok((ss_keymaterial, ct)) - } fn decaps(sk: &SK, ct: &[u8]) -> Result, KEMError> { - if ct.len() != CT_LEN - { + if ct.len() != CT_LEN { return Err(KEMError::LengthError("Invalid ciphertext length")); } let ss_bytes = Self::decaps_internal(sk, ct.try_into().unwrap()); - let mut ss_keymaterial = KeyMaterial::::from_bytes_as_type(&ss_bytes, KeyType::BytesFullEntropy)?; + let mut ss_keymaterial = + KeyMaterial::::from_bytes_as_type(&ss_bytes, KeyType::BytesFullEntropy)?; ss_keymaterial.allow_hazardous_operations(); - ss_keymaterial.set_security_strength( SecurityStrength::from_bits(LAMBDA as usize) )?; + ss_keymaterial.set_security_strength(SecurityStrength::from_bits(LAMBDA as usize))?; ss_keymaterial.drop_hazardous_operations(); Ok(ss_keymaterial) diff --git a/crypto/mlkem_lowmemory/src/mlkem_keys.rs b/crypto/mlkem_lowmemory/src/mlkem_keys.rs index 5571ab9..8cbcac5 100644 --- a/crypto/mlkem_lowmemory/src/mlkem_keys.rs +++ b/crypto/mlkem_lowmemory/src/mlkem_keys.rs @@ -1,17 +1,26 @@ -use crate::aux_functions::{sample_poly_CBD}; -use crate::mlkem::{POLY_BYTES, H, G}; +use crate::aux_functions::sample_poly_CBD; +use crate::low_memory_helpers::{compute_A_hat_dot_s_hat, pack_s_hat_row, pack_t_hat_row}; +use crate::mlkem::{G, H, POLY_BYTES}; +use crate::mlkem::{ + MLKEM512_ETA1, MLKEM512_FULL_SK_LEN, MLKEM512_LAMBDA, MLKEM512_PK_LEN, MLKEM512_SK_LEN, + MLKEM512_T_PACKED_LEN, MLKEM512_k, +}; +use crate::mlkem::{ + MLKEM768_ETA1, MLKEM768_FULL_SK_LEN, MLKEM768_LAMBDA, MLKEM768_PK_LEN, MLKEM768_SK_LEN, + MLKEM768_T_PACKED_LEN, MLKEM768_k, +}; +use crate::mlkem::{ + MLKEM1024_ETA1, MLKEM1024_FULL_SK_LEN, MLKEM1024_LAMBDA, MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, + MLKEM1024_T_PACKED_LEN, MLKEM1024_k, +}; +use crate::polynomial::Polynomial; use crate::{ML_KEM_512_NAME, ML_KEM_768_NAME, ML_KEM_1024_NAME}; -use crate::mlkem::{MLKEM512_k, MLKEM512_ETA1, MLKEM512_LAMBDA, MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM512_FULL_SK_LEN, MLKEM512_T_PACKED_LEN}; -use crate::mlkem::{MLKEM768_k, MLKEM768_ETA1, MLKEM768_LAMBDA, MLKEM768_PK_LEN, MLKEM768_SK_LEN, MLKEM768_FULL_SK_LEN, MLKEM768_T_PACKED_LEN}; -use crate::mlkem::{MLKEM1024_k, MLKEM1024_ETA1, MLKEM1024_LAMBDA, MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, MLKEM1024_FULL_SK_LEN, MLKEM1024_T_PACKED_LEN}; -use bouncycastle_core::key_material::{KeyMaterialTrait, KeyMaterial, KeyType}; +use bouncycastle_core::errors::KEMError; +use bouncycastle_core::key_material::{KeyMaterial, KeyMaterialTrait, KeyType}; use bouncycastle_core::traits::{Hash, KEMPrivateKey, KEMPublicKey, Secret, SecurityStrength}; -use bouncycastle_core::errors::{KEMError}; +use bouncycastle_sha3::SHA3_256; use core::fmt; use core::fmt::{Debug, Display, Formatter}; -use bouncycastle_sha3::SHA3_256; -use crate::low_memory_helpers::{compute_A_hat_dot_s_hat, pack_s_hat_row, pack_t_hat_row}; -use crate::polynomial::{Polynomial}; // imports just for docs @@ -20,16 +29,39 @@ use crate::polynomial::{Polynomial}; /// ML-KEM-512 Public Key pub type MLKEM512PublicKey = MLKEMPublicKey; /// ML-KEM-512 Private Key -pub type MLKEM512PrivateKey = MLKEMSeedPrivateKey; +pub type MLKEM512PrivateKey = MLKEMSeedPrivateKey< + MLKEM512_k, + MLKEM512_ETA1, + MLKEM512_LAMBDA, + MLKEM512_SK_LEN, + MLKEM512_FULL_SK_LEN, + MLKEM512_PK_LEN, + MLKEM512_T_PACKED_LEN, +>; /// ML-KEM-768 Public Key pub type MLKEM768PublicKey = MLKEMPublicKey; /// ML-KEM-768 Private Key -pub type MLKEM768PrivateKey = MLKEMSeedPrivateKey; +pub type MLKEM768PrivateKey = MLKEMSeedPrivateKey< + MLKEM768_k, + MLKEM768_ETA1, + MLKEM768_LAMBDA, + MLKEM768_SK_LEN, + MLKEM768_FULL_SK_LEN, + MLKEM768_PK_LEN, + MLKEM768_T_PACKED_LEN, +>; /// ML-KEM-1024 Public Key pub type MLKEM1024PublicKey = MLKEMPublicKey; /// ML-KEM-1024 Private Key -pub type MLKEM1024PrivateKey = MLKEMSeedPrivateKey; - +pub type MLKEM1024PrivateKey = MLKEMSeedPrivateKey< + MLKEM1024_k, + MLKEM1024_ETA1, + MLKEM1024_LAMBDA, + MLKEM1024_SK_LEN, + MLKEM1024_FULL_SK_LEN, + MLKEM1024_PK_LEN, + MLKEM1024_T_PACKED_LEN, +>; /// An ML-KEM public key. #[derive(Clone)] @@ -39,7 +71,9 @@ pub struct MLKEMPublicKey : KEMPublicKey { +pub trait MLKEMPublicKeyTrait: + KEMPublicKey +{ /// Algorithm 23 pkDecode(𝑝𝑘) /// Reverses the procedure pkEncode. /// Input: Public key 𝑝𝑘 ∈ 𝔹32+32𝑘(bitlen (𝑞−1)−𝑑). @@ -59,15 +93,17 @@ pub trait MLKEMPublicKeyTrait : MLKEMPublicKeyTrait { + const PK_LEN: usize, +>: MLKEMPublicKeyTrait +{ /// Not exposing a constructor publicly because you should have to get an instance either by /// running a keygen, or by decoding an existing key. fn new(t_hat: [u8; T_PACKED_LEN], rho: [u8; 32]) -> Self; } impl -MLKEMPublicKeyTrait for MLKEMPublicKey { + MLKEMPublicKeyTrait for MLKEMPublicKey +{ fn pk_decode(pk: &[u8; PK_LEN]) -> Self { Self::new(pk[..T_PACKED_LEN].try_into().unwrap(), pk[T_PACKED_LEN..].try_into().unwrap()) } @@ -94,20 +130,23 @@ MLKEMPublicKeyTrait for MLKEMPublicKey -MLKEMPublicKeyInternalTrait for MLKEMPublicKey { + MLKEMPublicKeyInternalTrait + for MLKEMPublicKey +{ fn new(t_hat_packed: [u8; T_PACKED_LEN], rho: [u8; 32]) -> Self { Self { rho, t_hat_packed } } } -impl -KEMPublicKey for MLKEMPublicKey { +impl KEMPublicKey + for MLKEMPublicKey +{ /// Algorithm 22 pkEncode(𝜌, 𝐭1) /// Encodes a public key for ML-DSA into a byte string. /// Input:𝜌 ∈ 𝔹32, 𝐭1 ∈ 𝑅𝑘 with coefficients in [0, 2bitlen (𝑞−1)−𝑑 − 1]. /// Output: Public key 𝑝𝑘 ∈ 𝔹32+32𝑘(bitlen (𝑞−1)−𝑑). fn encode(&self) -> [u8; PK_LEN] { - debug_assert_eq!(PK_LEN, 32 + 12*k*32); + debug_assert_eq!(PK_LEN, 32 + 12 * k * 32); let mut pk = [0u8; PK_LEN]; self.encode_out(&mut pk); @@ -117,7 +156,7 @@ KEMPublicKey for MLKEMPublicKey { fn encode_out(&self, out: &mut [u8; PK_LEN]) -> usize { debug_assert_eq!(self.t_hat_packed.len(), T_PACKED_LEN); - out[.. T_PACKED_LEN].copy_from_slice(&self.t_hat_packed); + out[..T_PACKED_LEN].copy_from_slice(&self.t_hat_packed); debug_assert_eq!(out[T_PACKED_LEN..].len(), 32); out[T_PACKED_LEN..].copy_from_slice(&self.rho); @@ -125,24 +164,30 @@ KEMPublicKey for MLKEMPublicKey { } fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != PK_LEN { return Err(KEMError::DecodingError("Provided key bytes are the incorrect length")) } + if bytes.len() != PK_LEN { + return Err(KEMError::DecodingError("Provided key bytes are the incorrect length")); + } let bytes_sized: [u8; PK_LEN] = bytes[..PK_LEN].try_into().unwrap(); Ok(Self::pk_decode(&bytes_sized)) } } -impl -Eq for MLKEMPublicKey { } +impl Eq + for MLKEMPublicKey +{ +} -impl -PartialEq for MLKEMPublicKey { +impl PartialEq + for MLKEMPublicKey +{ fn eq(&self, other: &Self) -> bool { bouncycastle_utils::ct::ct_eq_bytes(&self.encode(), &other.encode()) } } -impl -Debug for MLKEMPublicKey { +impl Debug + for MLKEMPublicKey +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let alg = match k { 2 => ML_KEM_512_NAME, @@ -155,8 +200,9 @@ Debug for MLKEMPublicKey { } } -impl -Display for MLKEMPublicKey { +impl Display + for MLKEMPublicKey +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let alg = match k { 2 => ML_KEM_512_NAME, @@ -169,10 +215,6 @@ Display for MLKEMPublicKey { } } - - - - /// An ML-KEM private key. #[derive(Clone)] pub struct MLKEMSeedPrivateKey< @@ -182,7 +224,7 @@ pub struct MLKEMSeedPrivateKey< const SK_LEN: usize, const FULL_SK_LEN: usize, const PK_LEN: usize, - const T_PACKED_LEN: usize + const T_PACKED_LEN: usize, > { rho: [u8; 32], sigma: [u8; 32], @@ -198,8 +240,9 @@ impl< const SK_LEN: usize, const FULL_SK_LEN: usize, const PK_LEN: usize, - const T_PACKED_LEN: usize -> MLKEMSeedPrivateKey { + const T_PACKED_LEN: usize, +> MLKEMSeedPrivateKey +{ /// Create a new MLKEMSeedPrivateKey from a 64-byte KeyMaterial. /// Seed SecurityStrength must match algorithm security strength: 128-bit (ML-KEM-512), 192-bit (ML-KEM-768), or 256-bit (ML-KEM-1024). pub fn new(seed: &KeyMaterial<64>) -> Result { @@ -241,7 +284,6 @@ impl< } } - /// General trait for all ML-KEM private keys types. pub trait MLKEMPrivateKeyTrait< const k: usize, @@ -249,7 +291,8 @@ pub trait MLKEMPrivateKeyTrait< const FULL_SK_LEN: usize, const PK_LEN: usize, const T_PACKED_LEN: usize, -> : KEMPrivateKey { +>: KEMPrivateKey +{ /// New from KeyMaterial. Can throw a KEMError if the KeyMaterial does not contain sufficient entropy. fn from_keymaterial(seed: &KeyMaterial<64>) -> Result; /// Get a ref to the seed, which there always will be for a MLKEMSeedPrivateKey @@ -286,9 +329,13 @@ pub trait MLKEMPrivateKeyTrait< fn sk_decode(sk: &[u8; SK_LEN]) -> Self; } -pub(crate) trait MLKEMPrivateKeyInternalTrait { - +pub(crate) trait MLKEMPrivateKeyInternalTrait< + const k: usize, + const SK_LEN: usize, + const PK_LEN: usize, + const T_PACKED_LEN: usize, +> +{ fn z(&self) -> &[u8; 32]; fn compute_s_hat_row(&self, idx: usize) -> Polynomial; @@ -299,7 +346,6 @@ pub(crate) trait MLKEMPrivateKeyInternalTrait [u8; T_PACKED_LEN]; } - impl< const k: usize, const eta1: i16, @@ -307,8 +353,10 @@ impl< const SK_LEN: usize, const FULL_SK_LEN: usize, const PK_LEN: usize, - const T_PACKED_LEN: usize -> MLKEMPrivateKeyTrait for MLKEMSeedPrivateKey { + const T_PACKED_LEN: usize, +> MLKEMPrivateKeyTrait + for MLKEMSeedPrivateKey +{ fn from_keymaterial(seed: &KeyMaterial<64>) -> Result { Self::new(seed) } @@ -318,12 +366,13 @@ impl< tmp[32..].copy_from_slice(&self.z); let mut seed = KeyMaterial::<64>::from_bytes_as_type(&tmp, KeyType::Seed).unwrap(); seed.allow_hazardous_operations(); - seed.set_security_strength( match k { + seed.set_security_strength(match k { 2 => SecurityStrength::_128bit, 3 => SecurityStrength::_192bit, 4 => SecurityStrength::_256bit, _ => unreachable!("Invalid mlkem param set"), - }).unwrap(); + }) + .unwrap(); seed.drop_hazardous_operations(); Some(seed) @@ -377,16 +426,15 @@ impl< /* ek */ // Alg 13; line 19: ekPKE ← ByteEncode12(𝐭)‖𝜌 let pk = self.pk(); - out[pos .. pos + PK_LEN].copy_from_slice(&pk.encode()); + out[pos..pos + PK_LEN].copy_from_slice(&pk.encode()); pos += PK_LEN; /* H(ek) */ - out[pos .. pos + 32].copy_from_slice(&pk.compute_hash()); + out[pos..pos + 32].copy_from_slice(&pk.compute_hash()); pos += 32; /* z */ - out[pos .. pos + 32].copy_from_slice(&self.z); - + out[pos..pos + 32].copy_from_slice(&self.z); FULL_SK_LEN } @@ -403,10 +451,13 @@ impl< const SK_LEN: usize, const FULL_SK_LEN: usize, const PK_LEN: usize, - const T_PACKED_LEN: usize -> MLKEMPrivateKeyInternalTrait for MLKEMSeedPrivateKey { - - fn z(&self) -> &[u8; 32] { &self.z } + const T_PACKED_LEN: usize, +> MLKEMPrivateKeyInternalTrait + for MLKEMSeedPrivateKey +{ + fn z(&self) -> &[u8; 32] { + &self.z + } fn compute_s_hat_row(&self, idx: usize) -> Polynomial { debug_assert!(idx < k); @@ -433,7 +484,7 @@ impl< fn t_hat_packed(&self) -> [u8; T_PACKED_LEN] { let mut t_hat_packed = [0u8; T_PACKED_LEN]; - for i in 0 .. k { + for i in 0..k { // first half of // 18: 𝐭_hat ← 𝐀_hat ∘ 𝐬_hat + 𝐞_hat let mut t_hat_i = compute_A_hat_dot_s_hat::(&self.rho, &self.sigma, i); @@ -449,7 +500,7 @@ impl< // Note: here n = k let mut e_i = sample_poly_CBD::(&self.sigma, (k + i) as u8); - e_i.ntt(); // technically now e_hat_i + e_i.ntt(); // technically now e_hat_i t_hat_i.add(&e_i); } t_hat_i.poly_reduce(); @@ -469,7 +520,9 @@ impl< const FULL_SK_LEN: usize, const PK_LEN: usize, const T_PACKED_LEN: usize, -> KEMPrivateKey for MLKEMSeedPrivateKey { +> KEMPrivateKey + for MLKEMSeedPrivateKey +{ /// Encode the private key as a 64-byte seed (d || z) fn encode(&self) -> [u8; SK_LEN] { let mut sk = [0u8; SK_LEN]; @@ -509,7 +562,9 @@ impl< const FULL_SK_LEN: usize, const PK_LEN: usize, const T_PACKED_LEN: usize, -> Eq for MLKEMSeedPrivateKey {} +> Eq for MLKEMSeedPrivateKey +{ +} impl< const k: usize, @@ -536,7 +591,9 @@ impl< const FULL_SK_LEN: usize, const PK_LEN: usize, const T_PACKED_LEN: usize, -> Secret for MLKEMSeedPrivateKey {} +> Secret for MLKEMSeedPrivateKey +{ +} /// Debug impl mainly to prevent the secret key from being printed in logs. impl< @@ -550,19 +607,14 @@ impl< > fmt::Debug for MLKEMSeedPrivateKey { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let alg = match k { - 2 => ML_KEM_512_NAME, - 3 => ML_KEM_768_NAME, - 4 => ML_KEM_1024_NAME, - _ => panic!("Unsupported key length"), - }; + let alg = match k { + 2 => ML_KEM_512_NAME, + 3 => ML_KEM_768_NAME, + 4 => ML_KEM_1024_NAME, + _ => panic!("Unsupported key length"), + }; let pk_hash = self.pk().compute_hash(); - write!( - f, - "MLKEMSeedPrivateKey {{ alg: {}, pub_key_hash: {:x?} }}", - alg, - &pk_hash, - ) + write!(f, "MLKEMSeedPrivateKey {{ alg: {}, pub_key_hash: {:x?} }}", alg, &pk_hash,) } } @@ -585,12 +637,7 @@ impl< _ => panic!("Unsupported key length"), }; let pk_hash = self.pk().compute_hash(); - write!( - f, - "MLKEMSeedPrivateKey {{ alg: {}, pub_key_hash: {:x?} }}", - alg, - &pk_hash, - ) + write!(f, "MLKEMSeedPrivateKey {{ alg: {}, pub_key_hash: {:x?} }}", alg, &pk_hash,) } } diff --git a/crypto/mlkem_lowmemory/src/polynomial.rs b/crypto/mlkem_lowmemory/src/polynomial.rs index a8c7420..985ddcd 100644 --- a/crypto/mlkem_lowmemory/src/polynomial.rs +++ b/crypto/mlkem_lowmemory/src/polynomial.rs @@ -1,18 +1,22 @@ //! Represents a polynomial over the ML-DSA ring. +use crate::aux_functions::{ + ZETAS, ZETAS_INV, barrett_reduce, cond_sub_q, montgomery_reduce, mul_mont, ntt_base_mult, +}; +use crate::mlkem::{N, q}; +use bouncycastle_core::traits::Secret; use core::fmt; use core::fmt::{Debug, Display, Formatter}; use core::ops::{Index, IndexMut}; -use bouncycastle_core::traits::Secret; -use crate::aux_functions::{barrett_reduce, cond_sub_q, montgomery_reduce, mul_mont, ntt_base_mult, ZETAS, ZETAS_INV}; -use crate::mlkem::{N, q}; /// A polynomial over the ML-KEM ring. /// Dev note: this doesn't strictly need to be pub ... ie there's no good reason for a caller to use this class directly, /// but in order to test the Debug and Display traits, you need STD, so those can't be tested from inline tests in this file /// and the real unit tests are in a different crate, so here we are. #[derive(Clone)] -pub struct Polynomial{ pub(crate) coeffs: [i16; N] } +pub struct Polynomial { + pub(crate) coeffs: [i16; N], +} /// Convenience function to avoid ".0" all over the place. impl Index for Polynomial { @@ -39,7 +43,7 @@ impl Polynomial { pub(crate) fn from_msg(m: [u8; 32]) -> Self { let mut w = Polynomial::new(); - for (i, b) in m.iter().enumerate().take(N/8) { + for (i, b) in m.iter().enumerate().take(N / 8) { for j in 0..8 { let mask = -(((*b >> j) & 1) as i16); w[8 * i + j] = mask /*as i32*/ & ((q + 1) / 2); @@ -51,8 +55,7 @@ impl Polynomial { /// Convert a Polynomial back into a message m pub(crate) fn to_msg(mut self) -> [u8; 32] { - - const LOWER: i32 = q as i32 >> 2; // 832 + const LOWER: i32 = q as i32 >> 2; // 832 const UPPER: i32 = q as i32 - LOWER; // 2497 let mut msg = [0u8; 32]; @@ -62,7 +65,7 @@ impl Polynomial { self.cond_sub_q(); // for (i, item) in msg.iter_mut().enumerate().take(N/8) { - for i in 0 .. N/8 { + for i in 0..N / 8 { for j in 0..8 { let c_j = self[8 * i + j] as i32; let t = (((LOWER - c_j) & (c_j - UPPER)) >> 31) & 0x0000000000000001; @@ -98,18 +101,10 @@ impl Polynomial { /// Borrowed from: /// https://github.com/pq-crystals/kyber/blob/main/ref/poly.c#L290 pub(crate) fn base_mult_montgomery(&mut self, b: &Polynomial) { - for i in 0..(N/4) { + for i in 0..(N / 4) { let a1: i16 = self[4 * i]; let a2: i16 = self[4 * i + 1]; - ntt_base_mult( - &mut self.coeffs, - 4 * i, - a1, - a2, - b[4 * i], - b[4 * i + 1], - ZETAS[64 + i], - ); + ntt_base_mult(&mut self.coeffs, 4 * i, a1, a2, b[4 * i], b[4 * i + 1], ZETAS[64 + i]); let a1: i16 = self[4 * i + 2]; let a2: i16 = self[4 * i + 3]; @@ -162,12 +157,12 @@ impl Polynomial { // s.cond_sub_q(); match dv { - 4 => { // MLKEM512 and MLKEM768 - for i in 0..N/8 { + 4 => { + // MLKEM512 and MLKEM768 + for i in 0..N / 8 { // fill the temp array t for (j, item) in t.iter_mut().enumerate() { - *item = ((((self[8 * i + j] as i32) << 4) + (q as i32 /2)) - / (q as i32) + *item = ((((self[8 * i + j] as i32) << 4) + (q as i32 / 2)) / (q as i32) & 15) as u8; } @@ -177,13 +172,13 @@ impl Polynomial { out[idx + 3] = t[6] | (t[7] << 4); idx += 4; } - }, - 5 => { // MLKEM1024 - for i in 0..N/8 { + } + 5 => { + // MLKEM1024 + for i in 0..N / 8 { // fill the temp array t for (j, item) in t.iter_mut().enumerate() { - *item = (((((self[8 * i + j] as i32) << 5) + (q as i32 /2)) - / (q as i32)) + *item = (((((self[8 * i + j] as i32) << 5) + (q as i32 / 2)) / (q as i32)) & 31) as u8; } @@ -194,7 +189,7 @@ impl Polynomial { out[idx + 4] = (t[6] >> 2) | (t[7] << 3); idx += 5; } - }, + } _ => unreachable!(), }; } @@ -216,38 +211,34 @@ impl Polynomial { // if self.m_engine.poly_compressed_bytes() == 128 { match dv { - 4 => { // MLKEM512 and MLKEM768 - for i in 0..N/2 { + 4 => { + // MLKEM512 and MLKEM768 + for i in 0..N / 2 { v[2 * i] = - (((((compressed_v[idx] & 15) as i16) as i32 * (q as i32)) + 8) >> 4) - as i16; + (((((compressed_v[idx] & 15) as i16) as i32 * (q as i32)) + 8) >> 4) as i16; v[2 * i + 1] = - (((((compressed_v[idx] >> 4) as i16) as i32 * (q as i32)) + 8) >> 4) - as i16; + (((((compressed_v[idx] >> 4) as i16) as i32 * (q as i32)) + 8) >> 4) as i16; idx += 1; } - }, - 5 => { // MLKEM1024 + } + 5 => { + // MLKEM1024 let mut t = [0u8; 8]; - for i in 0..N/8 { + for i in 0..N / 8 { t[0] = compressed_v[idx]; - t[1] = - (compressed_v[idx] >> 5) | (compressed_v[idx + 1] << 3); + t[1] = (compressed_v[idx] >> 5) | (compressed_v[idx + 1] << 3); t[2] = compressed_v[idx + 1] >> 2; - t[3] = (compressed_v[idx + 1] >> 7) - | (compressed_v[idx + 2] << 1); - t[4] = (compressed_v[idx + 2] >> 4) - | (compressed_v[idx + 3] << 4); + t[3] = (compressed_v[idx + 1] >> 7) | (compressed_v[idx + 2] << 1); + t[4] = (compressed_v[idx + 2] >> 4) | (compressed_v[idx + 3] << 4); t[5] = compressed_v[idx + 3] >> 1; - t[6] = (compressed_v[idx + 3] >> 6) - | (compressed_v[idx + 4] << 2); + t[6] = (compressed_v[idx + 3] >> 6) | (compressed_v[idx + 4] << 2); t[7] = compressed_v[idx + 4] >> 3; idx += 5; for (j, item) in t.iter_mut().enumerate() { v[8 * i + j] = (((*item & 31) as i32 * (q as i32) + 16) >> 5) as i16; } } - }, + } _ => unreachable!(), } diff --git a/crypto/mlkem_lowmemory/tests/bc_test_data.rs b/crypto/mlkem_lowmemory/tests/bc_test_data.rs index 848a60f..c6db20d 100644 --- a/crypto/mlkem_lowmemory/tests/bc_test_data.rs +++ b/crypto/mlkem_lowmemory/tests/bc_test_data.rs @@ -290,4 +290,4 @@ // } // } // } -// } \ No newline at end of file +// } diff --git a/crypto/mlkem_lowmemory/tests/mlkem_key_tests.rs b/crypto/mlkem_lowmemory/tests/mlkem_key_tests.rs index 01e708a..440ff8d 100644 --- a/crypto/mlkem_lowmemory/tests/mlkem_key_tests.rs +++ b/crypto/mlkem_lowmemory/tests/mlkem_key_tests.rs @@ -1,17 +1,23 @@ #[cfg(test)] mod mlkem_key_tests { use bouncycastle_core::key_material::{KeyMaterial512, KeyType}; - use bouncycastle_core::traits::{KEMPrivateKey, KEMPublicKey, KEM}; - use bouncycastle_mlkem_lowmemory::{MLKEMPrivateKeyTrait, MLKEMPublicKeyTrait, MLKEMTrait}; - use bouncycastle_mlkem_lowmemory::{MLKEM512, MLKEM768, MLKEM1024}; - use bouncycastle_mlkem_lowmemory::{MLKEM512PrivateKey, MLKEM512PublicKey, MLKEM768PrivateKey, MLKEM768PublicKey, MLKEM1024PrivateKey, MLKEM1024PublicKey}; - use bouncycastle_mlkem_lowmemory::{MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM512_CT_LEN, MLKEM768_PK_LEN, MLKEM768_SK_LEN, MLKEM768_CT_LEN, MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, MLKEM1024_CT_LEN, MLKEM_SS_LEN}; + use bouncycastle_core::traits::{KEM, KEMPrivateKey, KEMPublicKey}; use bouncycastle_hex as hex; use bouncycastle_mlkem_lowmemory::mlkem::MLKEM512_FULL_SK_LEN; + use bouncycastle_mlkem_lowmemory::{ + MLKEM_SS_LEN, MLKEM512_CT_LEN, MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM768_CT_LEN, + MLKEM768_PK_LEN, MLKEM768_SK_LEN, MLKEM1024_CT_LEN, MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, + }; + use bouncycastle_mlkem_lowmemory::{MLKEM512, MLKEM768, MLKEM1024}; + use bouncycastle_mlkem_lowmemory::{ + MLKEM512PrivateKey, MLKEM512PublicKey, MLKEM768PrivateKey, MLKEM768PublicKey, + MLKEM1024PrivateKey, MLKEM1024PublicKey, + }; + use bouncycastle_mlkem_lowmemory::{MLKEMPrivateKeyTrait, MLKEMPublicKeyTrait, MLKEMTrait}; #[test] fn core_framework_tests() { - use bouncycastle_core_test_framework::kem::{TestFrameworkKEMKeys}; + use bouncycastle_core_test_framework::kem::TestFrameworkKEMKeys; let tf = TestFrameworkKEMKeys::new(); tf.test_keys::(); @@ -21,7 +27,6 @@ mod mlkem_key_tests { #[test] fn pk_from_sk() { - /* MLDSA44 */ let seed_bytes: [u8; MLKEM512_SK_LEN] = hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f").unwrap().try_into().unwrap(); let expected_sk_bytes: [u8; MLKEM512_FULL_SK_LEN] = hex::decode("70554fd436344f2785b1b3b1bac184b6679003336c26f15a7de878c4825c6be03f3c4a480f75b7486aad31d3a00518623fd207ab528dd62721495835ae0062c367b74a71baf10aad0e8a2902076be31348beb15ccc0957cdebb4aff226756bbc601b6568ab784acbaeb34702f0f86a26202118b22b23f83558776c79c14dba983379c803e0dcc3160a11757030e69c6919798d81eb698a9a4483a99e5a5cb2c31c9a661799f3cc89c790706ea041629045d42a83aed88860e394c69187e2105d28cc14ec393592d67dd00aa43fe8b4eae4414002866b5c713c6a8d7d16cf78b819d6f12e9e5a74233908f0b15e3c4ba8329c5cdda55c84928e3aa8063e5aa9676403f91735b11010c7f593091364dc86445bc804840a9a21724212469f8a7b0ce0ac698eb86cad39a7f4824d9a5163aac21ee6808b053c8a3facb0b6744b5262bbcb26a43f664c8732b64cfc7acf099605f41c796060976ac433833fe00343fb1828300a424741116e4b45bb276ea81129a0db4c6e60bce611101e8c625474925e0222679308a3e7708d1972a7b423eb232851c36d2ed53d3ed3bb7500637061a5dc2292fa1c466c07354683328bec2c1ed2cb5c99b78eca0969038cf7c34dd118724e31cae086206b34302b520f5d177aded5b3cce02acce808ea26bcc072625fdb93f17458a5fc1d4da394380a1f57e9cc66109438a075f0d2813fcc4a199cc76db3823f270b0061594192940411a37ffbafae2c150165cec5c6bf73c595fb92cd15312607da070778652bd9944bc48bc7d1a534338bad0bad6656c5d502ce7850ab1587244eeb58f439ab5e08574a718c8aac3d77c798bba1542733be73448f23fb70c0e5353a27c88322c5218493afbb38086434d6d60a56ba887dd498c3ab26a0870993815aa6a40975f218adca1582d64ffc8652fbb3a9a6fbc304f91945fa4aaef2878fd715df70113d2379f44886f812c83ff2b719a69e1ec74ae4b15accd3aed5a53ce76a7b0982471633b973cb40a1a0015d0a424fa11a479c023017436d2a2900e993eb5a0a067400c7f4aadf201fc4fa31264a63bae95cc8d65c3995815e597d104355cf29aa5333c93251869d5bcdbe487124f602b8b6a66c16c4761648ad765cf5d8006b515e905a7f0ac076b0c62efa328153e7ca5701699f1305f1e6bc6f90b0e49b693512b6ce992a8b8016ddfc1a662c7e3f9619cbd869dd771af30896ccd5918ac6cb77466c5e779996d67ff9aabc97503f2c7b7e2d000d86450fb1807ca4cabda465825a31c789a1b7a491ab3872765d320d0b71920fa213c94093416b83b8124e69f65e62cb5000dcc37aa9a0fff73970c4772f357d24189ca6f5305568c0e2376a3762a68c605e563c5d209572e0fc7532ca294729535567b5fc413c5e8792d2464536cc808f98add74664f141566f9016a90a541829a98a0464ce41a8bb44c2d4fa3c2c209460728ef14a1a7c4c9b98d12203b4cc3529160a9ab2d7838f7ff6b53ae05aa31a7d646b7afa6c45932526a3c3755619be994c211c2a31c05b3447836cb2150be1829dae6b04c5535cff546e392ba797411720f924f490a5ac5495f21356d550b782a64c1688b6b655bcc7842197a434c2f6563b5b7f09a78bcc488232783561d16f4cbab6755400050781570c66604b817ad1252294736e8b01861a4b5a74519b8b6fe51489a5072392e587626c713776575d33806a1c8e2732af97c2680f51666331c4eb8bbc0431c4f96832daf1b3c45528fba153f6c78b1c198702947ccd337727a46fb53ba11de5cb4191346859516cb6ad72400f3cf209b236aef35a580ac87eb3e30fafd66973ca8a7dd2675af41f7a17b61433cd1af80f7708869f665488497980b1ac10a0cdcb636a00ed8681b35e429124ca80350725b85f83a5eac3a4a3cc1600903e65293560b9b336e5af0d529dac1a048119302cb7a9bcc110b94851bf02117f199dc485a852b7473f09b831a6831d5b54c0b790d225cf6bb92d9462a26cdb33dda5123c7aaf0e26a0b83655eea28bf3a8074725018fd6bae4b601cf61baab71a7a3d35197a343e74b4a272c125d540896426d85b7958d3b38a6ba987ec37225c7b44cdb12dde4539b4ab082363683f04bf7a09cc5c41dfe830a1b162e0b324334362f084a14467723344badd000f8d8c537c48f998f05307cebd1ede0b81c3bc59a065a1b6d63b26c82f101ff648063b376e2bb6c5b7455f655a50c2feadade150efa0e0e6f365aea202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f").unwrap() @@ -40,7 +45,6 @@ mod mlkem_key_tests { // Also test the export to fully expanded sk assert_eq!(&sk.encode_full_sk(), &expected_sk_bytes); - // Decode and re-encode the pk, make sure you get the same thing let decoded_pk = MLKEM512PublicKey::from_bytes(&expected_pk_bytes).unwrap(); let pk_bytes = decoded_pk.encode(); @@ -58,12 +62,16 @@ mod mlkem_key_tests { // 3) does it reject a private key if the H(ek) is wrong? let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (_pk, mut sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); let expected_pk_bytes: [u8; MLKEM512_PK_LEN] = hex::decode("3995815e597d104355cf29aa5333c93251869d5bcdbe487124f602b8b6a66c16c4761648ad765cf5d8006b515e905a7f0ac076b0c62efa328153e7ca5701699f1305f1e6bc6f90b0e49b693512b6ce992a8b8016ddfc1a662c7e3f9619cbd869dd771af30896ccd5918ac6cb77466c5e779996d67ff9aabc97503f2c7b7e2d000d86450fb1807ca4cabda465825a31c789a1b7a491ab3872765d320d0b71920fa213c94093416b83b8124e69f65e62cb5000dcc37aa9a0fff73970c4772f357d24189ca6f5305568c0e2376a3762a68c605e563c5d209572e0fc7532ca294729535567b5fc413c5e8792d2464536cc808f98add74664f141566f9016a90a541829a98a0464ce41a8bb44c2d4fa3c2c209460728ef14a1a7c4c9b98d12203b4cc3529160a9ab2d7838f7ff6b53ae05aa31a7d646b7afa6c45932526a3c3755619be994c211c2a31c05b3447836cb2150be1829dae6b04c5535cff546e392ba797411720f924f490a5ac5495f21356d550b782a64c1688b6b655bcc7842197a434c2f6563b5b7f09a78bcc488232783561d16f4cbab6755400050781570c66604b817ad1252294736e8b01861a4b5a74519b8b6fe51489a5072392e587626c713776575d33806a1c8e2732af97c2680f51666331c4eb8bbc0431c4f96832daf1b3c45528fba153f6c78b1c198702947ccd337727a46fb53ba11de5cb4191346859516cb6ad72400f3cf209b236aef35a580ac87eb3e30fafd66973ca8a7dd2675af41f7a17b61433cd1af80f7708869f665488497980b1ac10a0cdcb636a00ed8681b35e429124ca80350725b85f83a5eac3a4a3cc1600903e65293560b9b336e5af0d529dac1a048119302cb7a9bcc110b94851bf02117f199dc485a852b7473f09b831a6831d5b54c0b790d225cf6bb92d9462a26cdb33dda5123c7aaf0e26a0b83655eea28bf3a8074725018fd6bae4b601cf61baab71a7a3d35197a343e74b4a272c125d540896426d85b7958d3b38a6ba987ec37225c7b44cdb12dde4539b4ab082363683f04bf7a09cc5c41dfe830a1b162e0b324334362f084a14467723344badd000f8d8c537c48f998f05307cebd1ede0b81c3bc59a065a1b6d63b26c").unwrap() @@ -73,7 +81,11 @@ mod mlkem_key_tests { // generation of KAT // let h_ek = pk.compute_hash(); // println!("H(ek) for public key: {}", hex::encode(h_ek)); - let expected_h_ek: [u8; 32] = hex::decode("82f101ff648063b376e2bb6c5b7455f655a50c2feadade150efa0e0e6f365aea").unwrap().try_into().unwrap(); + let expected_h_ek: [u8; 32] = + hex::decode("82f101ff648063b376e2bb6c5b7455f655a50c2feadade150efa0e0e6f365aea") + .unwrap() + .try_into() + .unwrap(); assert_eq!(pk.compute_hash(), expected_h_ek); assert_eq!(sk.pk_hash(), &expected_h_ek); @@ -82,12 +94,16 @@ mod mlkem_key_tests { #[test] fn encode_decode() { let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (pk1, sk1) = MLKEM512::keygen_from_seed(&seed).unwrap(); let pk1_bytes = pk1.encode(); @@ -106,12 +122,16 @@ mod mlkem_key_tests { #[test] fn seed() { let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (_pk, sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); @@ -121,7 +141,6 @@ mod mlkem_key_tests { #[test] fn test_eq() { - // MLKEM512 let (pk, sk) = MLKEM512::keygen().unwrap(); @@ -144,7 +163,6 @@ mod mlkem_key_tests { bytes[17] ^= 0x01; assert_ne!(sk, MLKEM512PrivateKey::from_bytes(&bytes).unwrap()); - // MLKEM768 let (pk, sk) = MLKEM768::keygen().unwrap(); @@ -167,7 +185,6 @@ mod mlkem_key_tests { bytes[17] ^= 0x01; assert_ne!(sk, MLKEM768PrivateKey::from_bytes(&bytes).unwrap()); - // MLKEM1024 let (pk, sk) = MLKEM1024::keygen().unwrap(); @@ -198,7 +215,6 @@ mod mlkem_key_tests { let (pk768, sk768) = MLKEM768::keygen().unwrap(); let (pk1024, sk1024) = MLKEM1024::keygen().unwrap(); - /*** MLDSAPublicKey ***/ // fmt @@ -221,8 +237,6 @@ mod mlkem_key_tests { let pk_str = format!("{:?}", pk1024); assert!(pk_str.contains("MLKEMPublicKey { alg: ML-KEM-1024, pub_key_hash:")); - - /*** MLDSAPrivateKey ***/ // fmt let sk_str = format!("{}", sk512); @@ -244,4 +258,4 @@ mod mlkem_key_tests { let sk_str = format!("{:?}", sk1024); assert!(sk_str.contains("MLKEMSeedPrivateKey { alg: ML-KEM-1024, pub_key_hash:")); } -} \ No newline at end of file +} diff --git a/crypto/mlkem_lowmemory/tests/mlkem_tests.rs b/crypto/mlkem_lowmemory/tests/mlkem_tests.rs index 328c90c..ff8cc5c 100644 --- a/crypto/mlkem_lowmemory/tests/mlkem_tests.rs +++ b/crypto/mlkem_lowmemory/tests/mlkem_tests.rs @@ -2,14 +2,24 @@ #[cfg(test)] mod mlkem_tests { use bouncycastle_core::errors::KEMError; - use bouncycastle_core::key_material::{KeyMaterialTrait, KeyMaterial512, KeyType}; - use bouncycastle_core::traits::{KEMPrivateKey, KEMPublicKey, SecurityStrength, KEM, XOF}; - use bouncycastle_mlkem_lowmemory::{MLKEM512, MLKEM768, MLKEM1024, MLKEM_RND_LEN, MLKEM_SEED_LEN, Polynomial}; - use bouncycastle_mlkem_lowmemory::{MLKEM512PrivateKey, MLKEM512PublicKey, MLKEM768PrivateKey, MLKEM768PublicKey, MLKEM1024PrivateKey, MLKEM1024PublicKey}; - use bouncycastle_mlkem_lowmemory::{MLKEMPrivateKeyTrait, MLKEMTrait}; - use bouncycastle_mlkem_lowmemory::{MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM768_PK_LEN, MLKEM768_SK_LEN, MLKEM768_CT_LEN, MLKEM512_CT_LEN, MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, MLKEM1024_CT_LEN, MLKEM_SS_LEN}; + use bouncycastle_core::key_material::{KeyMaterial512, KeyMaterialTrait, KeyType}; + use bouncycastle_core::traits::{KEM, KEMPrivateKey, KEMPublicKey, SecurityStrength, XOF}; use bouncycastle_hex as hex; - use bouncycastle_mlkem_lowmemory::mlkem::{MLKEM1024_FULL_SK_LEN, MLKEM512_FULL_SK_LEN, MLKEM768_FULL_SK_LEN}; + use bouncycastle_mlkem_lowmemory::mlkem::{ + MLKEM512_FULL_SK_LEN, MLKEM768_FULL_SK_LEN, MLKEM1024_FULL_SK_LEN, + }; + use bouncycastle_mlkem_lowmemory::{ + MLKEM_RND_LEN, MLKEM_SEED_LEN, MLKEM512, MLKEM768, MLKEM1024, Polynomial, + }; + use bouncycastle_mlkem_lowmemory::{ + MLKEM_SS_LEN, MLKEM512_CT_LEN, MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM768_CT_LEN, + MLKEM768_PK_LEN, MLKEM768_SK_LEN, MLKEM1024_CT_LEN, MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, + }; + use bouncycastle_mlkem_lowmemory::{ + MLKEM512PrivateKey, MLKEM512PublicKey, MLKEM768PrivateKey, MLKEM768PublicKey, + MLKEM1024PrivateKey, MLKEM1024PublicKey, + }; + use bouncycastle_mlkem_lowmemory::{MLKEMPrivateKeyTrait, MLKEMTrait}; use bouncycastle_sha3::SHAKE256; // #[test] @@ -32,7 +42,7 @@ mod mlkem_tests { #[test] fn core_framework_tests() { - use bouncycastle_core_test_framework::kem::{TestFrameworkKEM}; + use bouncycastle_core_test_framework::kem::TestFrameworkKEM; let tf = TestFrameworkKEM::new(false, true); @@ -58,16 +68,15 @@ mod mlkem_tests { fn rfc9935_keygen() { // note: same seed for MLKEM512, MLKEM768, MLKEM1024 let sk_seed_bytes: [u8; MLKEM_SEED_LEN] = hex::decode( - "000102030405060708090a0b0c0d0e0f + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap().try_into().unwrap(); - let seed = KeyMaterial512::from_bytes_as_type( - &sk_seed_bytes, - KeyType::Seed, - ).unwrap(); - - + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap() + .try_into() + .unwrap(); + let seed = KeyMaterial512::from_bytes_as_type(&sk_seed_bytes, KeyType::Seed).unwrap(); /* MLKEM512 */ let expected_full_sk_bytes: [u8; MLKEM512_FULL_SK_LEN] = hex::decode("70554fd436344f2785b1b3b1bac184b6679003336c26f15a7de878c4825c6be03f3c4a480f75b7486aad31d3a00518623fd207ab528dd62721495835ae0062c367b74a71baf10aad0e8a2902076be31348beb15ccc0957cdebb4aff226756bbc601b6568ab784acbaeb34702f0f86a26202118b22b23f83558776c79c14dba983379c803e0dcc3160a11757030e69c6919798d81eb698a9a4483a99e5a5cb2c31c9a661799f3cc89c790706ea041629045d42a83aed88860e394c69187e2105d28cc14ec393592d67dd00aa43fe8b4eae4414002866b5c713c6a8d7d16cf78b819d6f12e9e5a74233908f0b15e3c4ba8329c5cdda55c84928e3aa8063e5aa9676403f91735b11010c7f593091364dc86445bc804840a9a21724212469f8a7b0ce0ac698eb86cad39a7f4824d9a5163aac21ee6808b053c8a3facb0b6744b5262bbcb26a43f664c8732b64cfc7acf099605f41c796060976ac433833fe00343fb1828300a424741116e4b45bb276ea81129a0db4c6e60bce611101e8c625474925e0222679308a3e7708d1972a7b423eb232851c36d2ed53d3ed3bb7500637061a5dc2292fa1c466c07354683328bec2c1ed2cb5c99b78eca0969038cf7c34dd118724e31cae086206b34302b520f5d177aded5b3cce02acce808ea26bcc072625fdb93f17458a5fc1d4da394380a1f57e9cc66109438a075f0d2813fcc4a199cc76db3823f270b0061594192940411a37ffbafae2c150165cec5c6bf73c595fb92cd15312607da070778652bd9944bc48bc7d1a534338bad0bad6656c5d502ce7850ab1587244eeb58f439ab5e08574a718c8aac3d77c798bba1542733be73448f23fb70c0e5353a27c88322c5218493afbb38086434d6d60a56ba887dd498c3ab26a0870993815aa6a40975f218adca1582d64ffc8652fbb3a9a6fbc304f91945fa4aaef2878fd715df70113d2379f44886f812c83ff2b719a69e1ec74ae4b15accd3aed5a53ce76a7b0982471633b973cb40a1a0015d0a424fa11a479c023017436d2a2900e993eb5a0a067400c7f4aadf201fc4fa31264a63bae95cc8d65c3995815e597d104355cf29aa5333c93251869d5bcdbe487124f602b8b6a66c16c4761648ad765cf5d8006b515e905a7f0ac076b0c62efa328153e7ca5701699f1305f1e6bc6f90b0e49b693512b6ce992a8b8016ddfc1a662c7e3f9619cbd869dd771af30896ccd5918ac6cb77466c5e779996d67ff9aabc97503f2c7b7e2d000d86450fb1807ca4cabda465825a31c789a1b7a491ab3872765d320d0b71920fa213c94093416b83b8124e69f65e62cb5000dcc37aa9a0fff73970c4772f357d24189ca6f5305568c0e2376a3762a68c605e563c5d209572e0fc7532ca294729535567b5fc413c5e8792d2464536cc808f98add74664f141566f9016a90a541829a98a0464ce41a8bb44c2d4fa3c2c209460728ef14a1a7c4c9b98d12203b4cc3529160a9ab2d7838f7ff6b53ae05aa31a7d646b7afa6c45932526a3c3755619be994c211c2a31c05b3447836cb2150be1829dae6b04c5535cff546e392ba797411720f924f490a5ac5495f21356d550b782a64c1688b6b655bcc7842197a434c2f6563b5b7f09a78bcc488232783561d16f4cbab6755400050781570c66604b817ad1252294736e8b01861a4b5a74519b8b6fe51489a5072392e587626c713776575d33806a1c8e2732af97c2680f51666331c4eb8bbc0431c4f96832daf1b3c45528fba153f6c78b1c198702947ccd337727a46fb53ba11de5cb4191346859516cb6ad72400f3cf209b236aef35a580ac87eb3e30fafd66973ca8a7dd2675af41f7a17b61433cd1af80f7708869f665488497980b1ac10a0cdcb636a00ed8681b35e429124ca80350725b85f83a5eac3a4a3cc1600903e65293560b9b336e5af0d529dac1a048119302cb7a9bcc110b94851bf02117f199dc485a852b7473f09b831a6831d5b54c0b790d225cf6bb92d9462a26cdb33dda5123c7aaf0e26a0b83655eea28bf3a8074725018fd6bae4b601cf61baab71a7a3d35197a343e74b4a272c125d540896426d85b7958d3b38a6ba987ec37225c7b44cdb12dde4539b4ab082363683f04bf7a09cc5c41dfe830a1b162e0b324334362f084a14467723344badd000f8d8c537c48f998f05307cebd1ede0b81c3bc59a065a1b6d63b26c82f101ff648063b376e2bb6c5b7455f655a50c2feadade150efa0e0e6f365aea202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f").unwrap() @@ -111,11 +120,10 @@ mod mlkem_tests { let mut wrong_sk_bytes = sk_bytes.clone(); wrong_sk_bytes[4..8].copy_from_slice(&[0u8, 0u8, 0u8, 0u8]); match MLKEM512::keygen_from_seed_and_encoded(&seed, &wrong_sk_bytes) { - Err(KEMError::KeyGenError(_)) => { /* good */ }, + Err(KEMError::KeyGenError(_)) => { /* good */ } _ => panic!("sk_from_seed_and_encoded should fail with InvalidSignature"), } - /* MLKEM768 */ let expected_full_sk_bytes: [u8; MLKEM768_FULL_SK_LEN] = hex::decode("27d2a77f33756f61208ef113abe82595873d4abc730e5b5d679529bf6a4ceb6383427231a8612f41550515acba52e48ead8b942833bbe6865d13d14a79d2c5c3e07f0a056d8de7aadfcaba058c493c80b37cab8c562753bb3ba6b6ec8297f885eaa7540d530015a84406e55b1366b577e236ce58a26d8a1eb5a44d542323c2167d9bf4a47f985699ca05bae43b8dec617f02380a3890afd4b8c7ec7ede26553a025f3ce5bc5d7a62130304235cb1ad4836b566b5b863bd9bdb45a2844a7047b6c8d383e448525e040b4dc8a2b48c6c37c96d62d43f3fd88e2881c40a205c9e248f652b592781a779f86880f2a147b67863f391cc1a5a908c0095e07212291e2ef8a36eb9a9c0c6073225b34703a4af049382c47573da68fde9245ad444e31b1fbdb521f1f61f37bc0cef292067e670d28a1ffd904f6f1190a996918a13037a6cabf3c373bf8296cd37ab33ba7746809cc3f8ade1b3639bd57bfcc69650aaaf1de198fc4c0463299e52c461780cc428fc5d04a5c51850cba6c2a5274340675793dda09be44c29e6395c65f85d2a0a7c6df411e6911b1f2cb6c351cd2e875f51b638be776097e93e2f2b2f83da0beef4aa85ba9e763ab64502a0ca5222e9eab5b3b7088ed52060e8c8269b943a71ab0ae1c5b1b687d2e019cf8036bcf9bf6e7bac3aaa36e41660faa4540f2648cd93a189ec5c2dea70bacaaa4ffc906f90810ea1b67bf24f2c78cf6ba881aaea61c0652bff95b1bae4426d1773b9cc2ca82c21e38c636e3b1c523244986b0be8a83f5dd5cf2d54762fb3c5ebf59b8e885302b1ce47033edf760f4e029be40b6d566b19dd758acd5c7412878131244f90172c53f26663c21d905301d48baf91c917cc7779e9d8802cc10d89a3705099a2ad3a3a8896743c1144698093be257dacb66dc785228b912c8d965d14aa28342c3ac4a93fefa532b20945ddc1020139c14d638b908c4ddde9a0645b95b2e4414d40bb79f04413830f15a873c28bb7059c2741002015f20408f058e715b0bf995b5380b7dd325a056ab97e659a2be0cdf6c33731c683a634b771e8c92a139aee4bb0e49c7077321d42fc199f7c1f298ca625d223a5c263a03cc48159b7812665b78637e4e18720b2c29a6b99f42766a4cbc4dc508ba94ba83b89c3a5c78f8bb26bbd9b79beb8c8182490f5793ee5b96013b74b7e169e29d162f1315464ea7d72436d89b755161192c81cc2dd1c8b8bba795ef426ee1cc01c37aaa37b2cff8b0a378b47cbd0b4d49398cfc2712959699fa0bd8cd84666acc61f541b84fa96b9c854e4e75e9144addb44b8566a57dfbb545ce423c03346f2b2c1a91780d152a8de1a4d4c9cacde7392c996888cc2399c02c38b3353adf8acab283924da00a05b76e738c72c930d6cba09ae168990faa1fef2226e780861d416eff402f4f759fc648ab1f97100109087f96e4b148d2cb31e4805314ea0cd95fb023eac0d989474ba4201d7b41d26f5394b217eea5b34b71a8b37931c0e594271e0b7c733257240233e7ba735603e425a87dee77079e37cb28a21764594ce5350d8da2b62a07174943032ec89c98809c73b6423d30c1d283a766a64d89703c3d629b497828d48320c346210797a298aa10d423c8dda069d02bc59e6cdf03a096b8b3da4cab9b80ca4a14907672ccef1ec4faf234a0bc5b7e9d473f2b3133b3b26a1d175cb67a7805919699c02f76531b99c5f89180704bb4ca4535c5b8972679c660a07c5e514b87009c862eb8f5157695efb3fc40a9def6b81c1cc02a249ae4f094ad0d9bd3485c1c1c68080520a7c8c632032cee738154e5c5176c07da56024776a430fe76eacf665a3f7b832102215bc82f10939c8355704336a8fac1d81e4bb0485aa5d7c74d6b59bbe5c5e972a0d8bac411b55b5d5557cd680a1a8f71b4eb86bc48c9a0509731a54bd9d7290b27963e4372dc9b199cfdcac0b01acd28a62395112e4c43648d622c48c8234d01440e8cc376c927f23a5afc9ac0474c662274e424525c8552ece3b3fe26516de901bc7d515bde89558e626c95c80b93342f8010004f39e6c6c94871c5e344cab3966c835f9a96a59afd31c40286b38b1c1a78470bab947518934453ce86736a919f1f5a6d510a86f5454fc3980cb5c765bd2bd5f7b36b1410d6635c8ceb47c4dda0d76a28eac939c71c3024804866c71626658442163c2c22117e50acefce6378a985652302a4ef0c2ce0cc716b7796e2b6b2e3777dfa1ac3da259a31b5a9b530f8cb638a81a62ac301849abaf95a7301bda30068909bfdb7e67dbccbb38a5551a25b1a3a0f685748ad5753d8880f0016c627486166384c5571fe2365900364d038311e2d875db366686932b5ec602430a369e87a6ef5c338786657825bd4c057aceb923eb0935e6905e63b4ced7f80857a773dd64b150d26612ea9ac12052db2017bf1843ccb4b3281b690dc728adfa85c00281b8e3c09287335f856b4fc2892f69a2f57921ada01914c40988662d57769662a786351b9b66493dab79594d986de2100d65ba0ff4ea58b81538d24a4435a258fac25404aa7f41f658b1385065e158dcb60115732720f40459aaac15e406953a90ac52997d1ccd070060efc65db9e653354467fad56ec713c86e7540c423acf2669f52fa6f4ac6888d871ef3e847c029a8aafbb92e17b24aa079b1f419ba6175b442afb11909d4a56b70a0335b28739218aa7c9348e2c3c2f3eb3d15a41e6417c0dd94bfeb21419b311a7bb13a180bbe833218a9a6b17447cc85f225859587a73077049acbcfd44d0f025438e15d1538270d586e1bf83192a9459cf63c0e972f85297679831ecf121509851cb8340f6f107b0fa1a0efd1b36a8189bc085c4f5cb784e553f41b918f80397ce1956f785bee377ca9aa8be6998ada30c26b7c3d8c6b55254cc96203b20c42aee0ac4e1ebb408e49a9e3f879d0ab0785eb7025425d1305a2299c015e120d163b0e19494ce57253d0246d182745cb8197ab7438b3c1bb7972bec5a306eba3567855c014699fef65ae54c770a0d85c18400cf642aedc660777ba4b138502bd5a7812f621f84a48296b98dd4322b6f15828b8a8f0e00a8ba44a53c3a8b143571b0740abd567daf1cde9c79c204b6d5e259d1766a31bbbcb4e6a05cf4502176b301c1c2f41247750157bcec85e809b30a4d60d7747cdd0f5b99aa8c826987517793aaa8080a0b124a8558df72bbe37b75f4edbb6be8216d6c633fb2b2280e25113d8695e43481c3eeb397eb192505229b67a201ea893c3e2cb32da8bc342fa4dea0578a24e16d8f8f9383a95b77050f4d9fd2f5733eec1d63ef3c23ebf9918173669a7202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f").unwrap() .try_into().unwrap(); @@ -158,11 +166,10 @@ mod mlkem_tests { let mut wrong_sk_bytes = sk_bytes.clone(); wrong_sk_bytes[4..8].copy_from_slice(&[0u8, 0u8, 0u8, 0u8]); match MLKEM768::keygen_from_seed_and_encoded(&seed, &wrong_sk_bytes) { - Err(KEMError::KeyGenError(_)) => { /* good */ }, + Err(KEMError::KeyGenError(_)) => { /* good */ } _ => panic!("sk_from_seed_and_encoded should fail with InvalidSignature"), } - /* MLKEM1024 */ let expected_full_sk_bytes: [u8; MLKEM1024_FULL_SK_LEN] = hex::decode("f77b7f6b15c73fe2cc546b67fb774ca19b42cd463ea9fbb984ca477a77b6c71087cbf051abe4736a9072c6e870c8311c55963f500a3c7b1b8f2a58558f49c62527b6c594b5e7acb3bcf597273a5743517d151208bd4aa61e75ba67b0bd594a994919627ac0a804d489e171336bc339f4666706e5134412b366823d50318c8bf261ab120a28a04fec01cc15f2b71912cee54aa8eed854694b6ba886b5eb7661e6d56aac213cc1d814d592b395554fae74476d34371163129bf864527250606cc21a53746b20997077bba155733b28a4e7fa0776399524763eb481ceaa11366c3474a04685f40c3f08b0424f40bff949a0ac92704c3ba0c6eb36f1f5b621d8bf2b6327beb57cd3facb94186fe3fc9ab0a1434bb291d2c9bb70723057e2254059656f565919a32cf74579de89681cd2c5a935a52b4aaa2d24cb5d5c9e20729ec5492ec36961efb8a28cbc00ac303523295f3d8036abc1603307ce70d7848a35657a5687dd589927ea63731626abb26ec4e431b8eb6b3b0bc1e82573ee73b1a021183183528108ae2eacaddb95b464a0b98469c319cc27bfa01bc31054a68c05502b1662b879fe98a1711c3426f6436cb0214cea379ac3a7e5fb60184a37c1da1eda61c6c39c1dd4e847845811f2a358a43731528536d4a3291b04158c2c3dc641624882678bc7805f58a9d94c7104567846a2044e65aece2a225372b6024799a5477d60237504aa5c0ac57bc70a3558c08c4de687ef1302b4fcb5594413d22cb959bc31be423450403c6bc57dc411b3fefac1052ac4bb162c44545a4ca80892657fa13a0b2c482ced629cc4999d969c593d4aadf073cc3e3a458e78a8aa039408e652be93b20c8b42ec5b0e50239dac726052851a6d15312ec39ed208b72209a577c6b2770112895749d5260e7dd446c0b0118c1000be6801d2611fcf00792a9cc4f4b49922f9a2d4b9c8fa5a5d0d60506631a7e971cee840b08fa63c13729d7ea5aac70352a984cdb669331cba758fe87ec3931b3e3161fcc747aa749424689feae14bf7c9a2ffba1302b212b80372d8e9049db69a3a1261d0a2859a9b4d57899e0ba41607a1b67a7c0e12923689f8c6395377d970c7490a4129611a1d05c3b7813bed945420723f7f9525a87793fafbbfca982e66bb80681c83248a89da084c19882f48f31e7fc09093a49e9fd09691b021edf463afc519b62853816118346115fb0b882cc6482f3c5cbcc1c1894697e1239598b34b2a9a7acd15244d0690c88194097a9beda585e87c437124624c210768e6215d376482653eb89947877c118d370c696a6ffcc1018ae413a08a8d0ffaa819945da7a167c229913290cad1c80a369258762610ea253e62dc24226a30c892c12136c326f13f4446664712b0b90bc063b4028593cbde06cdc22289e240c7e296b59172c1aeda8c99e0512d1a0163a942ea33148e6937c026029424b81b996b1df22ea0623ec65c6bf093500cf3bf35374adc392035ca7c583b99685bca541a0807b163acd0888be0385dea820da46e4dbb44d2e462c734b83a473fed1364273159257cc259a8c5676c1c76d41d56b9907ec1c3599c9e8907403a27a705e3619b04b0ad046e8ec8169c17b460d44c0c0c4464d044c946186bc725965083a892bcc495c0540311ff9b3e5192c303d88f8ba46a901c782ef02388f1b2addab6a5350fc3639700e3154337337e4a178d351cd2b56ee1f0bfea34aacfa33d2ec791e50752d4d034cb1c951572caaa5c4d90947b6b175a6dd3c62a77bb8f7ac9ae24719b53c2b120a2876986e217b72bd7cee44a7265b11cee1ab2261762b31a3738386969c0825fb79452e652e1142fc73c9df6fba411795b4717922b29ba2d53abe5a8c0dcc1601b096c96d7938fd5a68a8797c7b9477a86a472eb5da250cb2fec318d83c8f43bbe8e11c35e377d349366c85c4382597f6fc27a0051c0fb00b02c01ca20f9a427f172599477ca690cc1327e0f025f80ec338a80a159e308c12a27db1a7e1b960a99d37dfc22872e51930f28c651ab221f53abaee20bad9a3eabcbab913251bf135beb29617b5754333c4daadb2238341c2ad9378186280f6449440b784ba78f5dac44d8f65b3b7421950397c3913a2dd23ec6d1cb717b36a5fc95af191e278296948c1254ea86b4ec004b94c29450111191823b3514c9ac1ea3d9825ccb86393a2dfb04654fa2192d37bfad1c497c6502eee5ca80a73bfce0baf5a54a88585a401397a3d232f426a7afb082bc21a44317090eaac7592c2ea88a653c4491ea193931335f52e989a3c4cc56d9c553732d57c470fb41ab759b65d2d04445382fcd9c4e344a1128fa9e11e04358e192ed014b23232a7ee2b22e23717f44111ee33575399c37646da9813ec9b212afe94e5dc5c2330a7294cc1f4234a6d3fbb4f1685ab8892c04acb17cd1c170d7b0611b6a7176c794cc8c67f55fc923c2ad203100f365991882c30243d77813843b5ec7c964032263706092ecf00c7516be64e4598ca4226c069bb5e67e4175cf2286c8dd5c488a6c5861f31baa0bd0269470e8b551dd3bcd38c86c12f9cdb176c77dc8b6c02a701f478902c8553f694c0d82727b4c4a5c2c1041212aa1274808b82111b377ec75214e9b1978f76004d4139d98613f4b8e98d20af7b534073a509a959b7a7564f9b40ca218bf61829320a8502017954d328d7ac6c769ec29700756e7b0685b340d5e118059504a49a9a50a10198eb10a5784678eb427d7b4babb9552933b062897973e1318eaf0a0eac37584a65401b1703e042accd837531483f241cadcd1c1d378119e694429db199ac891e4c5343757085bb3ae783667350c4458d97672e861e80b1d2679510ea3a6f2360c77a46942c7a06a554d228080c84b47aef14db17620cb16c06ab30a1be4cda7082be9f87e9c211c46916349a5ba8eaa5201c7294a3c0885b53b657452108825ec646c90a04612324ee7d031afe5343132cbef67b6efb1a5ec2809b773538ce77b3d8b04eb0b3c2256011e4c716c19a8ba0752bf71492117649f0615c3290fc29a46fde4bd52db9286d603388244259c15a7ac2b640a60cc03376a5841a3fb8a473568fa9b1a267215f34c01697b0f0e627175d72105b7707c29b9e614bdc33a6f6c818a95370b427882d7b476796a9ec6eb993274cd9b2391a82ba45e3393d2e9ae9721ca9d6c1b988b5827713f90a6585de9433528c02b03ce10bb5f720138d0fbb4c30c1266b918e52925dfe17b37f95d22bca54f475919ac859098c0f0d08ac5875ef29b56fd141e6ef15f700a0b66f39595c588177373c4669b21bc071e4c3aa5f0b4a31b6258f35da24ac3cd29c7f2092410c5078355b138fb53a6b9ae6e0b9c08243e7baa45c47376eb8c7f13d4cf51aa736fa31540c9241f370da544bf9f9c28d9a57e2f2a7ca95a4e4b466e641ab3bcc76adf1139d567a6f12b52f3a65e7ec0aae26bcaa8c55833b04e59998ebc9a1930fbb6d2233c53d2c1f8b9518e3c2de73a19dee6b380a5b32971cf64e129fd6c1fa6e75d4a234501e966dd3a540af5c8f4f34a6b4a253ee28492566d5e67c6f55855fcb0506fb06c156744d9a03a31a26fa94cad14f157b7f303d07a69c773768fcb4d079c09059703a0c3a94de4b99ea3a2f16583d0f9170a3950db07b4f0bc30802927f9f7961b6259892636a9502a2705303637799dd344da451c1cf7bf67840ceb3079ab8c6b8c1927f64053c612450c45c9e603bc16666e596b3471e103b6f15447424d17022048111ffbd37e1c670f64f14b8a7b32b94c1a49b45dd2fc38cd5289d910ad63602cf5e13042c64ac6797b89fb551ad08e05a92d200cccb7e712ef23c9312cb350f029ab537e287347fd3075ac10906a783f1c6c07ccb88f41228c4be1c640f790b5c3a5d5d3ca792495d74bc461562658c07ac600276b924ab5bc9be1f0494cb76f82f460a7480972663381e169996061d799859ec54d4f5ca5c411c01db1597b165977669de13a928a34afbac258fea8c4764239c9421dc3119bf5b47699206978327b1c5345ef746a7983841f056e2534100ab24d4e9abbd0b17c6a95bd4c3c0e40f69e1612aceeb28b99086c95116e7204273893390bf46b899b36286b0ebf1947bb9884f732ca27da82b19b5dc0cc7f8885714910888b2310c4f9319d410b34e6433b9003e2176bb995257456106e8952163b8ba592530cc5aa0aeb43ad398fe9e97baa523d7a4431677c3d3af0719e475db85ca95af5089beabeb05b2faab4896ba60f81c88472a57b46a828826a0cdfb446f8189182d2bf5eac4ec1cc5deaf599c8a13e48235406d17ffddc8344b6c66984a868aa92fa02227a086950eb0c8701ed58dc628776b983882e117561349e5c131a7e116a0463861d7d18663c5627c38c7147ddaadfd48acd7a4535202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f").unwrap() .try_into().unwrap(); @@ -205,23 +212,23 @@ mod mlkem_tests { let mut wrong_sk_bytes = sk_bytes.clone(); wrong_sk_bytes[4..8].copy_from_slice(&[0u8, 0u8, 0u8, 0u8]); match MLKEM1024::keygen_from_seed_and_encoded(&seed, &wrong_sk_bytes) { - Err(KEMError::KeyGenError(_)) => { /* good */ }, + Err(KEMError::KeyGenError(_)) => { /* good */ } _ => panic!("sk_from_seed_and_encoded should fail with InvalidSignature"), } } - #[test] /// Mirror of bc-java MLKEMTest.java : testMLKEM fn test_mlkem() { let seed_bytes: [u8; MLKEM_SEED_LEN] = hex::decode( - "49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3 - 99E3246884181F8E1DD44E0C7629093330221FD67D9B7D6E1510B2DBAD8762F7").unwrap().try_into().unwrap(); + "49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3 + 99E3246884181F8E1DD44E0C7629093330221FD67D9B7D6E1510B2DBAD8762F7", + ) + .unwrap() + .try_into() + .unwrap(); - let seed = KeyMaterial512::from_bytes_as_type( - &seed_bytes, - KeyType::Seed, - ).unwrap(); + let seed = KeyMaterial512::from_bytes_as_type(&seed_bytes, KeyType::Seed).unwrap(); let expected_full_sk_bytes: [u8; MLKEM1024_FULL_SK_LEN] = hex::decode("8C8B3722A82E550565521611EBBC63079944C9B1ABB3B0020FF12F631891A9C468D3A67BF6271280DA58D03CB042B3A461441637F929C273469AD15311E910DE18CB9537BA1BE42E98BB59E498A13FD440D0E69EE832B45CD95C382177D67096A18C07F1781663651BDCAC90DEDA3DDD143485864181C91FA2080F6DAB3F86204CEB64A7B4446895C03987A031CB4B6D9E0462FDA829172B6C012C638B29B5CD75A2C930A5596A3181C33A22D574D30261196BC350738D4FD9183A763336243ACED99B3221C71D8866895C4E52C119BF3280DAF80A95E15209A795C4435FBB3570FDB8AA9BF9AEFD43B094B781D5A81136DAB88B8799696556FEC6AE14B0BB8BE4695E9A124C2AB8FF4AB1229B8AAA8C6F41A60C34C7B56182C55C2C685E737C6CA00A23FB8A68C1CD61F30D3993A1653C1675AC5F0901A7160A73966408B8876B715396CFA4903FC69D60491F8146808C97CD5C533E71017909E97B835B86FF847B42A696375435E006061CF7A479463272114A89EB3EAF2246F0F8C104A14986828E0AD20420C9B37EA23F5C514949E77AD9E9AD12290DD1215E11DA274457AC86B1CE6864B122677F3718AA31B02580E64317178D38F25F609BC6C55BC374A1BF78EA8ECC219B30B74CBB3272A599238C93985170048F176775FB19962AC3B135AA59DB104F7114DBC2C2D42949ADECA6A85B323EE2B2B23A77D9DB235979A8E2D67CF7D2136BBBA71F269574B38888E1541340C19284074F9B7C8CF37EB01384E6E3822EC4882DFBBEC4E6098EF2B2FC177A1F0BCB65A57FDAA89315461BEB7885FB68B3CD096EDA596AC0E61DD7A9C507BC6345E0827DFCC8A3AC2DCE51AD731AA0EB932A6D0983992347CBEB3CD0D9C9719797CC21CF0062B0AD94CAD734C63E6B5D859CBE19F0368245351BF464D7505569790D2BB724D8659A9FEB1C7C473DC4D061E29863A2714BAC42ADCD1A8372776556F7928A7A44E94B6A25322D03C0A1622A7FD261522B7358F085BDFB60758762CB901031901B5EECF4920C81020A9B1781BCB9DD19A9DFB66458E7757C52CEC75B4BA740A24099CB56BB60A76B6901AA3E0169C9E83496D73C4C99435A28D613E97A1177F58B6CC595D3B2331E9CA7B57B74DC2C5277D26F2FE19240A55C35D6CFCA26C73E9A2D7C980D97960AE1A04698C16B398A5F20C35A0914145CE1674B71ABC6066A909A3E4B911E69D5A849430361F731B07246A6329B52361904225082D0AAC5B21D6B34862481A890C3C360766F04263603A6B73E802B1F70B2EB00046836B8F493BF10B90B8737C6C548449B294C47253BE26CA72336A632063AD3D0B48C8B0F4A34447EF13B764020DE739EB79ABA20E2BE1951825F293BEDD1089FCB0A91F560C8E17CDF52541DC2B81F972A7375B201F10C08D9B5BC8B95100054A3D0AAFF89BD08D6A0E7F2115A435231290460C9AD435A3B3CF35E52091EDD1890047BCC0AABB1ACEBC75F4A32BC1451ACC4969940788E89412188946C9143C5046BD1B458DF617C5DF533B052CD6038B7754034A23C2F7720134C7B4EACE01FAC0A2853A9285847ABBD06A3343A778AC6062E458BC5E61ECE1C0DE0206E6FE8A84034A7C5F1B005FB0A584051D3229B86C909AC5647B3D75569E05A88279D80E5C30F574DC327512C6BBE8101239EC62861F4BE67B05B9CDA9C545C13E7EB53CFF260AD9870199C21F8C63D64F0458A7141285023FEB829290872389644B0C3B73AC2C8E121A29BB1C43C19A233D56BED82740EB021C97B8EBBA40FF328B541760FCC372B52D3BC4FCBC06F424EAF253804D4CB46F41FF254C0C5BA483B44A87C219654555EC7C163C79B9CB760A2AD9BB722B93E0C28BD4B1685949C496EAB1AFF90919E3761B346838ABB2F01A91E554375AFDAAAF3826E6DB79FE7353A7A578A7C0598CE28B6D9915214236BBFFA6D45B6376A07924A39A7BE818286715C8A3C110CD76C02E0417AF138BDB95C3CCA798AC809ED69CFB672B6FDDC24D89C06A6558814AB0C21C62B2F84C0E3E0803DB337A4E0C7127A6B4C8C08B1D1A76BF07EB6E5B5BB47A16C74BC548375FB29CD789A5CFF91BDBD071859F4846E355BB0D29484E264DFF36C9177A7ACA78908879695CA87F25436BC12630724BB22F0CB64897FE5C41195280DA04184D4BC7B532A0F70A54D7757CDE6175A6843B861CB2BC4830C0012554CFC5D2C8A2027AA3CD967130E9B96241B11C4320C7649CC23A71BAFE691AFC08E680BCEF42907000718E4EACE8DA28214197BE1C269DA9CB541E1A3CE97CFADF9C6058780FE6793DBFA8218A2760B802B8DA2AA271A38772523A76736A7A31B9D3037AD21CEBB11A472B8792EB17558B940E70883F264592C689B240BB43D5408BF446432F412F4B9A5F6865CC252A43CF40A320391555591D67561FDD05353AB6B019B3A08A73353D51B6113AB2FA51D975648EE254AF89A230504A236A4658257740BDCBBE1708AB022C3C588A410DB3B9C308A06275BDF5B4859D3A2617A295E1A22F90198BAD0166F4A943417C5B831736CB2C8580ABFDE5714B586ABEEC0A175A08BC710C7A2895DE93AC438061BF7765D0D21CD418167CAF89D1EFC3448BCBB96D69B3E010C82D15CAB6CACC6799D3639669A5B21A633C865F8593B5B7BC800262BB837A924A6C5440E4FC73B41B23092C3912F4C6BEBB4C7B4C62908B03775666C22220DF9C88823E344C7308332345C8B795D34E8C051F21F5A21C214B69841358709B1C305B32CC2C3806AE9CCD3819FFF4507FE520FBFC27199BC23BE6B9B2D2AC1717579AC769279E2A7AAC68A371A47BA3A7DBE016F14E1A727333663C4A5CD1A0F8836CF7B5C49AC51485CA60345C990E06888720003731322C5B8CD5E6907FDA1157F468FD3FC20FA8175EEC95C291A262BA8C5BE990872418930852339D88A19B37FEFA3CFE82175C224407CA414BAEB37923B4D2D83134AE154E490A9B45A0563B06C953C3301450A2176A07C614A74E3478E48509F9A60AE945A8EBC7815121D90A3B0E07091A096CF02C57B25BCA58126AD0C629CE166A7EDB4B33221A0D3F72B85D562EC698B7D0A913D73806F1C5C87B38EC003CB303A3DC51B4B35356A67826D6EDAA8FEB93B98493B2D1C11B676A6AD9506A1AAAE13A824C7C08D1C6C2C4DBA9642C76EA7F6C8264B64A23CCCA9A74635FCBF03E00F1B5722B214376790793B2C4F0A13B5C40760B4218E1D2594DCB30A70D9C1782A5DD30576FA4144BFC8416EDA8118FC6472F56A979586F33BB070FB0F1B0B10BC4897EBE01BCA3893D4E16ADB25093A7417D0708C83A26322E22E6330091E30152BF823597C04CCF4CFC7331578F43A2726CCB428289A90C863259DD180C5FF142BEF41C7717094BE07856DA2B140FA67710967356AA47DFBC8D255B4722AB86D439B7E0A6090251D2D4C1ED5F20BBE6807BF65A90B7CB2EC0102AF02809DC9AC7D0A3ABC69C18365BCFF59185F33996887746185906C0191AED4407E139446459BE29C6822717644353D24AB6339156A9C424909F0A9025BB74720779BE43F16D81C8CC666E99710D8C68BB5CC4E12F314E925A551F09CC59003A1F88103C254BB978D75F394D3540E31E771CDA36E39EC54A62B5832664D821A72F1E6AFBBA27F84295B2694C498498E812BC8E9378FE541CEC5891B25062901CB7212E3CDC46179EC5BCEC10BC0B9311DE05074290687FD6A5392671654284CD9C8CC3EBA80EB3B662EB53EB75116704A1FEB5C2D056338532868DDF24EB8992AB8565D9E490CADF14804360DAA90718EAB616BAB0765D33987B47EFB6599C5563235E61E4BE670E97955AB292D9732CB8930948AC82DF230AC72297A23679D6B94C17F1359483254FEDC2F05819F0D069A443B78E3FC6C3EF4714B05A3FCA81CBBA60242A7060CD885D8F39981BB18092B23DAA59FD9578388688A09BBA079BC809A54843A60385E2310BBCBCC0213CE3DFAAB33B47F9D6305BC95C6107813C585C4B657BF30542833B14949F573C0612AD524BAAE69590C1277B86C286571BF66B3CFF46A3858C09906A794DF4A06E9D4B0A2E43F10F72A6C6C47E5646E2C799B71C33ED2F01EEB45938EB7A4E2E2908C53558A540D350369FA189C616943F7981D7618CF02A5B0A2BCC422E857D1A47871253D08293C1C179BCDC0437069107418205FDB9856623B8CA6B694C96C084B17F13BB6DF12B2CFBBC2B0E0C34B00D0FCD0AECFB27924F6984E747BE2A09D83A8664590A8077331491A4F7D720843F23E652C6FA840308DB4020337AAD37967034A9FB523B67CA70330F02D9EA20C1E84CB8E5757C9E1896B60581441ED618AA5B26DA56C0A5A73C4DCFD755E610B4FC81FF84E21D2E574DFD8CD0AE893AA7E125B44B924F45223EC09F2AD1141EA93A68050DBF699E3246884181F8E1DD44E0C7629093330221FD67D9B7D6E1510B2DBAD8762F7").unwrap() .try_into().unwrap(); @@ -233,8 +240,16 @@ mod mlkem_tests { assert_eq!(sk.encode_full_sk(), expected_full_sk_bytes.as_slice()); assert_eq!(pk.encode(), expected_pk_bytes.as_slice()); - let message: [u8; MLKEM_RND_LEN] = hex::decode("59C5154C04AE43AAFF32700F081700389D54BEC4C37C088B1C53F66212B12C72").unwrap().try_into().unwrap(); - let expected_shared_secret: [u8; MLKEM_SS_LEN] = hex::decode("5CF38F578AC4AE95FBFED574B3D8EBF7CB1DC9074F22277360E36D775347C058").unwrap().try_into().unwrap(); + let message: [u8; MLKEM_RND_LEN] = + hex::decode("59C5154C04AE43AAFF32700F081700389D54BEC4C37C088B1C53F66212B12C72") + .unwrap() + .try_into() + .unwrap(); + let expected_shared_secret: [u8; MLKEM_SS_LEN] = + hex::decode("5CF38F578AC4AE95FBFED574B3D8EBF7CB1DC9074F22277360E36D775347C058") + .unwrap() + .try_into() + .unwrap(); let expected_ciphertext: [u8; MLKEM1024_CT_LEN] = hex::decode("8B9FE419250C5FB0463C8181FCF7CEC777136B738E015EBA31067AA4A8C378BBAC0121B88214F1AEB866E4F33C277099E09B4BF7E21CDDA30B5B32C18B0E9660C30601D85DAEC07AAF4B343EC5516FA501DD63088B999FB9A414C6CA593806C08CD4C775139BF0F0BF3676D773EDD56E616A13830D5F5FE35E515DBC84E43AAD0167D57E60A9DE30886ACD3F7F2006CAC26A7A07B4DADBEDFBED7F305764386AAD726D5B2BF14A376BAD8B4896688491733FB34E6EDEA10BFD5E448541CB6E69E3D87DF190AFA7FF62577775BAACEA444A6128A20200251D8FA759DC60FDA6A9730CFFE4997FE7EBCDD1644AE2D55290A4074CDD2CE53C18D22BC33671E68727A9B5A2FEAFB114A8045D96A56981E200A09661375987625ACC233EDE817AF1DEEAA21C7C4377423E73C5AF9BFF58A49DE6DAFD07A3E3BABD891F62BBA41D1856B8BC502CC86EE115A3598431E2B54AB0C5EACC3CE6A03090925C1FD5A251B00576763A963994A7A23EE12EBFC1B994F93C6144178F0BEF88245CE77CD32EF651826A6090AF561A5864DEC2A51D846F1F48F88B4B55F58C2373E0F67BDC95DC23A43E8546232A7B234E49F5226A3A63BDBCED7240FC81C2DB68AAEB2671A2FD231997BF8839C63A7F41F15E7242821D42E80BBC0F43FA9E353DE8B25ED8FFC242EB512C6A5260919AAE89A11176532BCCC762A520A37AEC4E7209AA81CEE0DD4ADD932C47EB8100BE98AA1DEEA9EA698115ADCED950A6C536D19AEB325CEA8C5245C0A2281533FB90809DC2BE90567EBE6AE229FE09B44DA2182585EA694D8A9AB33EBC24B44E09BD510F34B4140E1FB41162F9415F2D9106A0CEA00A26ED0920021F4E5BCFB3DABF5850DAB22B2E889D9611FBE06D0C899708EB5E5FAD2FBBE0D5C0BDE080F8E760EDFA037D55DA77F0F39591BF5B050C905FA538B7228E238A290DF340778DCBD6BE40A3B1DD455FB27ADBE176AEF6CC295BEA570BDC221BA14002E3B113B0EF237452FBC9F1AEC42E0D2B33F19832DB0A6171CAEB0B30EEAD3A54B704B761C7D4AFEA8F6AFC15156666A081C43AEB2E04FEECEF8AABA4049BD78B120B9ABA86A60342A0CF806411C473C26C4BE1540E3312388BCBC8523BA73F40EA28D5564274F3661D7ACAA0F1E8D0F28DCF6B501329963E6857FDB2AAE873A7D9D6C14821F6C0B6AA50AC449075CD6F2A256C5A05959DAB5A5912CC8E8F8B9F59941BFCCE6A28CBA74A20382B1FD3382D056547D5BC5EF4AAE62F96F038C595A4F901D6AE790F8978292AD1CC3A1E800B71A5BBE84533646655E3752FBD6B02B97B204E75D28A34C2F990FB8E8CD31CE6E683FA7E67DA03367E8D47DC626F060FBA2D0425004CAC2A61D982D2E3D85008624B45DB022CF51BA265B5E974712A9372EECAC0EA272B2FC56EBED0D32105521BA2C4A8FE0C678CE4E45902C7BA9D510BD47B2B5F931DD732F27DE9B42FD4AA39EAC765283A9965EE97C0D88E23EFA6F718242C67770B87BF8832858C1D13FC520870BD34F2B9C6FBFD1A528B744F814C93F4F4E87108316FE2AB06E02292DEA7FCF6FEFB17BF5AA7376A4A9BDB7C49BF709EB1E05D60EF14CD85A75239B97BCA9A6A3CC1B28F28979D612431BAAC1ACEE5EF62776B4D51B7EB0F63DF507760097223CA903E16E02DEB7FCABFBEC26DAEDC0ED4CC55726BDC31D1775112EF3C35D1DF928C6EB7830D8CA6570CB5CE348E3F26DDE864F20E5BE7B99E264EBC0E9D8DE9C6E4B7FE3CFBE673833CF7E8B3081529062CB6815C7C0766822B3B31E56BA1FC73FE3DED4B5D435BFCE2F2997C1D4B9CE293220DD461103BE084BF12076372668A69836769C1F6D8C32E2C7BC2E7D66714C814793A2970C90DD94DF14C89C60DD35B52A14778E137E750CE83AC3AAB667FCBDCBA38B7FA6D1C6BF7B99D957078176D9779A09F84B75FBC2A11769EF65532B09ACA4C9A3766B4A1FC717F94648FB8B8D9363E54F1C4201C075C18B1EAE098B83598089585ED9DC06B96E2D1C96DC738086EBBC26C3193B64139E1FC1DFB22A17893506EF7B35792B4EB00196693686EB5DEB3CEB436DD16D2D92A0FD31F468AF8662040F5257BFA0F14991C0D560999EEF775178D14955ADF091DD797AC1FDCEC7776055271C0F130562D0B0A6749B159DD0DB9AC69271AC719B83B683CE8B32342AC4AB257B0F8083C8CC86338AFA4D386C9848F413ED0").unwrap().try_into().unwrap(); // encaps @@ -251,11 +266,15 @@ mod mlkem_tests { #[test] fn test_decaps_from_seed() { let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3 + &hex::decode( + "49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3 99E3246884181F8E1DD44E0C7629093330221FD67D9B7D6E1510B2DBAD8762F7 - ").unwrap(), + ", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let expected_pk_bytes: [u8; MLKEM1024_PK_LEN] = hex::decode("A04184D4BC7B532A0F70A54D7757CDE6175A6843B861CB2BC4830C0012554CFC5D2C8A2027AA3CD967130E9B96241B11C4320C7649CC23A71BAFE691AFC08E680BCEF42907000718E4EACE8DA28214197BE1C269DA9CB541E1A3CE97CFADF9C6058780FE6793DBFA8218A2760B802B8DA2AA271A38772523A76736A7A31B9D3037AD21CEBB11A472B8792EB17558B940E70883F264592C689B240BB43D5408BF446432F412F4B9A5F6865CC252A43CF40A320391555591D67561FDD05353AB6B019B3A08A73353D51B6113AB2FA51D975648EE254AF89A230504A236A4658257740BDCBBE1708AB022C3C588A410DB3B9C308A06275BDF5B4859D3A2617A295E1A22F90198BAD0166F4A943417C5B831736CB2C8580ABFDE5714B586ABEEC0A175A08BC710C7A2895DE93AC438061BF7765D0D21CD418167CAF89D1EFC3448BCBB96D69B3E010C82D15CAB6CACC6799D3639669A5B21A633C865F8593B5B7BC800262BB837A924A6C5440E4FC73B41B23092C3912F4C6BEBB4C7B4C62908B03775666C22220DF9C88823E344C7308332345C8B795D34E8C051F21F5A21C214B69841358709B1C305B32CC2C3806AE9CCD3819FFF4507FE520FBFC27199BC23BE6B9B2D2AC1717579AC769279E2A7AAC68A371A47BA3A7DBE016F14E1A727333663C4A5CD1A0F8836CF7B5C49AC51485CA60345C990E06888720003731322C5B8CD5E6907FDA1157F468FD3FC20FA8175EEC95C291A262BA8C5BE990872418930852339D88A19B37FEFA3CFE82175C224407CA414BAEB37923B4D2D83134AE154E490A9B45A0563B06C953C3301450A2176A07C614A74E3478E48509F9A60AE945A8EBC7815121D90A3B0E07091A096CF02C57B25BCA58126AD0C629CE166A7EDB4B33221A0D3F72B85D562EC698B7D0A913D73806F1C5C87B38EC003CB303A3DC51B4B35356A67826D6EDAA8FEB93B98493B2D1C11B676A6AD9506A1AAAE13A824C7C08D1C6C2C4DBA9642C76EA7F6C8264B64A23CCCA9A74635FCBF03E00F1B5722B214376790793B2C4F0A13B5C40760B4218E1D2594DCB30A70D9C1782A5DD30576FA4144BFC8416EDA8118FC6472F56A979586F33BB070FB0F1B0B10BC4897EBE01BCA3893D4E16ADB25093A7417D0708C83A26322E22E6330091E30152BF823597C04CCF4CFC7331578F43A2726CCB428289A90C863259DD180C5FF142BEF41C7717094BE07856DA2B140FA67710967356AA47DFBC8D255B4722AB86D439B7E0A6090251D2D4C1ED5F20BBE6807BF65A90B7CB2EC0102AF02809DC9AC7D0A3ABC69C18365BCFF59185F33996887746185906C0191AED4407E139446459BE29C6822717644353D24AB6339156A9C424909F0A9025BB74720779BE43F16D81C8CC666E99710D8C68BB5CC4E12F314E925A551F09CC59003A1F88103C254BB978D75F394D3540E31E771CDA36E39EC54A62B5832664D821A72F1E6AFBBA27F84295B2694C498498E812BC8E9378FE541CEC5891B25062901CB7212E3CDC46179EC5BCEC10BC0B9311DE05074290687FD6A5392671654284CD9C8CC3EBA80EB3B662EB53EB75116704A1FEB5C2D056338532868DDF24EB8992AB8565D9E490CADF14804360DAA90718EAB616BAB0765D33987B47EFB6599C5563235E61E4BE670E97955AB292D9732CB8930948AC82DF230AC72297A23679D6B94C17F1359483254FEDC2F05819F0D069A443B78E3FC6C3EF4714B05A3FCA81CBBA60242A7060CD885D8F39981BB18092B23DAA59FD9578388688A09BBA079BC809A54843A60385E2310BBCBCC0213CE3DFAAB33B47F9D6305BC95C6107813C585C4B657BF30542833B14949F573C0612AD524BAAE69590C1277B86C286571BF66B3CFF46A3858C09906A794DF4A06E9D4B0A2E43F10F72A6C6C47E5646E2C799B71C33ED2F01EEB45938EB7A4E2E2908C53558A540D350369FA189C616943F7981D7618CF02A5B0A2BCC422E857D1A47871253D08293C1C179BCDC0437069107418205FDB9856623B8CA6B694C96C084B17F13BB6DF12B2CFBBC2B0E0C34B00D0FCD0AECFB27924F6984E747BE2A09D83A8664590A8077331491A4F7D720843F23E652C6FA840308DB4020337AAD37967034A9FB523B67CA70330F02D9EA20C1E84CB8E5757C9E1896B60581441ED618AA5B26DA56C0A5A73C4DCFD755E610B4FC81FF84E21").unwrap() .try_into().unwrap(); @@ -265,8 +284,16 @@ mod mlkem_tests { assert_eq!(pk.encode(), expected_pk_bytes.as_slice()); - let message: [u8; MLKEM_RND_LEN] = hex::decode("59C5154C04AE43AAFF32700F081700389D54BEC4C37C088B1C53F66212B12C72").unwrap().try_into().unwrap(); - let expected_shared_secret: [u8; MLKEM_SS_LEN] = hex::decode("5CF38F578AC4AE95FBFED574B3D8EBF7CB1DC9074F22277360E36D775347C058").unwrap().try_into().unwrap(); + let message: [u8; MLKEM_RND_LEN] = + hex::decode("59C5154C04AE43AAFF32700F081700389D54BEC4C37C088B1C53F66212B12C72") + .unwrap() + .try_into() + .unwrap(); + let expected_shared_secret: [u8; MLKEM_SS_LEN] = + hex::decode("5CF38F578AC4AE95FBFED574B3D8EBF7CB1DC9074F22277360E36D775347C058") + .unwrap() + .try_into() + .unwrap(); let expected_ciphertext: [u8; MLKEM1024_CT_LEN] = hex::decode("8B9FE419250C5FB0463C8181FCF7CEC777136B738E015EBA31067AA4A8C378BBAC0121B88214F1AEB866E4F33C277099E09B4BF7E21CDDA30B5B32C18B0E9660C30601D85DAEC07AAF4B343EC5516FA501DD63088B999FB9A414C6CA593806C08CD4C775139BF0F0BF3676D773EDD56E616A13830D5F5FE35E515DBC84E43AAD0167D57E60A9DE30886ACD3F7F2006CAC26A7A07B4DADBEDFBED7F305764386AAD726D5B2BF14A376BAD8B4896688491733FB34E6EDEA10BFD5E448541CB6E69E3D87DF190AFA7FF62577775BAACEA444A6128A20200251D8FA759DC60FDA6A9730CFFE4997FE7EBCDD1644AE2D55290A4074CDD2CE53C18D22BC33671E68727A9B5A2FEAFB114A8045D96A56981E200A09661375987625ACC233EDE817AF1DEEAA21C7C4377423E73C5AF9BFF58A49DE6DAFD07A3E3BABD891F62BBA41D1856B8BC502CC86EE115A3598431E2B54AB0C5EACC3CE6A03090925C1FD5A251B00576763A963994A7A23EE12EBFC1B994F93C6144178F0BEF88245CE77CD32EF651826A6090AF561A5864DEC2A51D846F1F48F88B4B55F58C2373E0F67BDC95DC23A43E8546232A7B234E49F5226A3A63BDBCED7240FC81C2DB68AAEB2671A2FD231997BF8839C63A7F41F15E7242821D42E80BBC0F43FA9E353DE8B25ED8FFC242EB512C6A5260919AAE89A11176532BCCC762A520A37AEC4E7209AA81CEE0DD4ADD932C47EB8100BE98AA1DEEA9EA698115ADCED950A6C536D19AEB325CEA8C5245C0A2281533FB90809DC2BE90567EBE6AE229FE09B44DA2182585EA694D8A9AB33EBC24B44E09BD510F34B4140E1FB41162F9415F2D9106A0CEA00A26ED0920021F4E5BCFB3DABF5850DAB22B2E889D9611FBE06D0C899708EB5E5FAD2FBBE0D5C0BDE080F8E760EDFA037D55DA77F0F39591BF5B050C905FA538B7228E238A290DF340778DCBD6BE40A3B1DD455FB27ADBE176AEF6CC295BEA570BDC221BA14002E3B113B0EF237452FBC9F1AEC42E0D2B33F19832DB0A6171CAEB0B30EEAD3A54B704B761C7D4AFEA8F6AFC15156666A081C43AEB2E04FEECEF8AABA4049BD78B120B9ABA86A60342A0CF806411C473C26C4BE1540E3312388BCBC8523BA73F40EA28D5564274F3661D7ACAA0F1E8D0F28DCF6B501329963E6857FDB2AAE873A7D9D6C14821F6C0B6AA50AC449075CD6F2A256C5A05959DAB5A5912CC8E8F8B9F59941BFCCE6A28CBA74A20382B1FD3382D056547D5BC5EF4AAE62F96F038C595A4F901D6AE790F8978292AD1CC3A1E800B71A5BBE84533646655E3752FBD6B02B97B204E75D28A34C2F990FB8E8CD31CE6E683FA7E67DA03367E8D47DC626F060FBA2D0425004CAC2A61D982D2E3D85008624B45DB022CF51BA265B5E974712A9372EECAC0EA272B2FC56EBED0D32105521BA2C4A8FE0C678CE4E45902C7BA9D510BD47B2B5F931DD732F27DE9B42FD4AA39EAC765283A9965EE97C0D88E23EFA6F718242C67770B87BF8832858C1D13FC520870BD34F2B9C6FBFD1A528B744F814C93F4F4E87108316FE2AB06E02292DEA7FCF6FEFB17BF5AA7376A4A9BDB7C49BF709EB1E05D60EF14CD85A75239B97BCA9A6A3CC1B28F28979D612431BAAC1ACEE5EF62776B4D51B7EB0F63DF507760097223CA903E16E02DEB7FCABFBEC26DAEDC0ED4CC55726BDC31D1775112EF3C35D1DF928C6EB7830D8CA6570CB5CE348E3F26DDE864F20E5BE7B99E264EBC0E9D8DE9C6E4B7FE3CFBE673833CF7E8B3081529062CB6815C7C0766822B3B31E56BA1FC73FE3DED4B5D435BFCE2F2997C1D4B9CE293220DD461103BE084BF12076372668A69836769C1F6D8C32E2C7BC2E7D66714C814793A2970C90DD94DF14C89C60DD35B52A14778E137E750CE83AC3AAB667FCBDCBA38B7FA6D1C6BF7B99D957078176D9779A09F84B75FBC2A11769EF65532B09ACA4C9A3766B4A1FC717F94648FB8B8D9363E54F1C4201C075C18B1EAE098B83598089585ED9DC06B96E2D1C96DC738086EBBC26C3193B64139E1FC1DFB22A17893506EF7B35792B4EB00196693686EB5DEB3CEB436DD16D2D92A0FD31F468AF8662040F5257BFA0F14991C0D560999EEF775178D14955ADF091DD797AC1FDCEC7776055271C0F130562D0B0A6749B159DD0DB9AC69271AC719B83B683CE8B32342AC4AB257B0F8083C8CC86338AFA4D386C9848F413ED0").unwrap().try_into().unwrap(); // encaps @@ -283,20 +310,21 @@ mod mlkem_tests { #[test] fn keygen_error_cases() { /* - Testing this condition: - if !(seed.key_type() == KeyType::Seed || seed.key_type() == KeyType::BytesFullEntropy) - || seed.key_len() != 64 - */ + Testing this condition: + if !(seed.key_type() == KeyType::Seed || seed.key_type() == KeyType::BytesFullEntropy) + || seed.key_len() != 64 + */ // success case KeyType: seed - let seed_bytes: [u8; 64] = hex::decode("000102030405060708090a0b0c0d0e0f + let seed_bytes: [u8; 64] = hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap().try_into().unwrap(); - let mut seed = KeyMaterial512::from_bytes_as_type( - &seed_bytes, - KeyType::Seed, - ).unwrap(); - + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap() + .try_into() + .unwrap(); + let mut seed = KeyMaterial512::from_bytes_as_type(&seed_bytes, KeyType::Seed).unwrap(); /* MLKEM512 */ let expected_pk_bytes: [u8; MLKEM512_PK_LEN] = hex::decode("3995815e597d104355cf29aa5333c93251869d5bcdbe487124f602b8b6a66c16c4761648ad765cf5d8006b515e905a7f0ac076b0c62efa328153e7ca5701699f1305f1e6bc6f90b0e49b693512b6ce992a8b8016ddfc1a662c7e3f9619cbd869dd771af30896ccd5918ac6cb77466c5e779996d67ff9aabc97503f2c7b7e2d000d86450fb1807ca4cabda465825a31c789a1b7a491ab3872765d320d0b71920fa213c94093416b83b8124e69f65e62cb5000dcc37aa9a0fff73970c4772f357d24189ca6f5305568c0e2376a3762a68c605e563c5d209572e0fc7532ca294729535567b5fc413c5e8792d2464536cc808f98add74664f141566f9016a90a541829a98a0464ce41a8bb44c2d4fa3c2c209460728ef14a1a7c4c9b98d12203b4cc3529160a9ab2d7838f7ff6b53ae05aa31a7d646b7afa6c45932526a3c3755619be994c211c2a31c05b3447836cb2150be1829dae6b04c5535cff546e392ba797411720f924f490a5ac5495f21356d550b782a64c1688b6b655bcc7842197a434c2f6563b5b7f09a78bcc488232783561d16f4cbab6755400050781570c66604b817ad1252294736e8b01861a4b5a74519b8b6fe51489a5072392e587626c713776575d33806a1c8e2732af97c2680f51666331c4eb8bbc0431c4f96832daf1b3c45528fba153f6c78b1c198702947ccd337727a46fb53ba11de5cb4191346859516cb6ad72400f3cf209b236aef35a580ac87eb3e30fafd66973ca8a7dd2675af41f7a17b61433cd1af80f7708869f665488497980b1ac10a0cdcb636a00ed8681b35e429124ca80350725b85f83a5eac3a4a3cc1600903e65293560b9b336e5af0d529dac1a048119302cb7a9bcc110b94851bf02117f199dc485a852b7473f09b831a6831d5b54c0b790d225cf6bb92d9462a26cdb33dda5123c7aaf0e26a0b83655eea28bf3a8074725018fd6bae4b601cf61baab71a7a3d35197a343e74b4a272c125d540896426d85b7958d3b38a6ba987ec37225c7b44cdb12dde4539b4ab082363683f04bf7a09cc5c41dfe830a1b162e0b324334362f084a14467723344badd000f8d8c537c48f998f05307cebd1ede0b81c3bc59a065a1b6d63b26c").unwrap() @@ -310,33 +338,40 @@ mod mlkem_tests { seed.set_key_type(KeyType::BytesFullEntropy).unwrap(); _ = MLKEM512::keygen_from_seed(&seed).unwrap(); - // Failure case: key type != Seed || BytesFullEntropy let mac_seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f").unwrap(), + 303132333435363738393a3b3c3d3e3f", + ) + .unwrap(), KeyType::MACKey, - ).unwrap(); + ) + .unwrap(); match MLKEM512::keygen_from_seed(&mac_seed) { - Err(KEMError::KeyGenError(_)) => { /* good */ }, + Err(KEMError::KeyGenError(_)) => { /* good */ } _ => panic!("expected KeyGenError"), } // Failure case: key is undersized let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("000102030405060708090a0b0c0d0e0f + &hex::decode( + "000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e").unwrap(), + 303132333435363738393a3b3c3d3e", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); assert_eq!(seed.key_len(), 63); match MLKEM512::keygen_from_seed(&seed) { - Err(KEMError::KeyGenError(_)) => { /* good */ }, + Err(KEMError::KeyGenError(_)) => { /* good */ } _ => panic!("expected KeyGenError"), } } @@ -367,18 +402,21 @@ mod mlkem_tests { /// cest that a corrupted ct returns the implicit rejection value K_bar = J(z||c) fn test_implicit_rejection() { let seed = KeyMaterial512::from_bytes_as_type( - &hex::decode("49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3 + &hex::decode( + "49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3 99E3246884181F8E1DD44E0C7629093330221FD67D9B7D6E1510B2DBAD8762F7 - ").unwrap(), + ", + ) + .unwrap(), KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (pk, sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); // encaps let (_ss, ct) = MLKEM512::encaps(&pk).unwrap(); - // decaps with busted ciphertext let mut busted_ciphertext = ct.clone(); busted_ciphertext[17] ^= 0xFF; @@ -397,7 +435,7 @@ mod mlkem_tests { _ = shake.squeeze_out(&mut buf); assert_eq!(ss.ref_to_bytes(), buf); - }, + } _ => panic!("This should have succeeded but with the wrong ss."), } } @@ -407,7 +445,6 @@ mod mlkem_tests { /// /// This test satisfies testing condition #1 in the Decapsulation Input checks in FIPS 203 section 7.3 fn test_boundary_conditions() { - // ct too long / too short // // satisfies testing condition #1 in the Decapsulation Input checks in FIPS 203 section 7.3 @@ -421,7 +458,7 @@ mod mlkem_tests { // too short match MLKEM512::decaps(&sk, &ct[..MLKEM512_CT_LEN - 1]) { - Err(KEMError::LengthError(_)) => { /* good */ }, + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } // too long @@ -429,7 +466,7 @@ mod mlkem_tests { ct_too_long[..MLKEM512_CT_LEN].copy_from_slice(&ct); ct_too_long[MLKEM512_CT_LEN..].copy_from_slice(&[1u8, 0u8]); match MLKEM512::decaps(&sk, &ct_too_long) { - Err(KEMError::LengthError(_)) => { /* good */ }, + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } @@ -439,7 +476,7 @@ mod mlkem_tests { // too short match MLKEM768::decaps(&sk, &ct[..MLKEM512_CT_LEN - 1]) { - Err(KEMError::LengthError(_)) => { /* good */ }, + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } // too long @@ -447,7 +484,7 @@ mod mlkem_tests { ct_too_long[..MLKEM768_CT_LEN].copy_from_slice(&ct); ct_too_long[MLKEM768_CT_LEN..].copy_from_slice(&[1u8, 0u8]); match MLKEM768::decaps(&sk, &ct_too_long) { - Err(KEMError::LengthError(_)) => { /* good */ }, + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } @@ -457,7 +494,7 @@ mod mlkem_tests { // too short match MLKEM1024::decaps(&sk, &ct[..MLKEM1024_CT_LEN - 1]) { - Err(KEMError::LengthError(_)) => { /* good */ }, + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } // too long @@ -465,7 +502,7 @@ mod mlkem_tests { ct_too_long[..MLKEM1024_CT_LEN].copy_from_slice(&ct); ct_too_long[MLKEM1024_CT_LEN..].copy_from_slice(&[1u8, 0u8]); match MLKEM1024::decaps(&sk, &ct_too_long) { - Err(KEMError::LengthError(_)) => { /* good */ }, + Err(KEMError::LengthError(_)) => { /* good */ } _ => panic!("Expected error for sig too short"), } } @@ -484,7 +521,7 @@ mod mlkem_tests { let p = Polynomial::new(); assert_eq!(format!("{:?}", p), "Polynomial (data masked)"); } - + #[test] fn keypair_consistency_check() { // this is common to all parameter sets, so I'll just test MLKEM512 @@ -496,11 +533,11 @@ mod mlkem_tests { // failure case: different but valid key let (pk2, sk2) = MLKEM512::keygen().unwrap(); match MLKEM512::keypair_consistency_check(&pk, &sk2) { - Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ }, + Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ } _ => panic!("Expected error for different key"), }; match MLKEM512::keypair_consistency_check(&pk2, &sk) { - Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ }, + Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ } _ => panic!("Expected error for different key"), }; @@ -509,7 +546,7 @@ mod mlkem_tests { pk_bytes[17] ^= 0x01; let pk2 = MLKEM512PublicKey::from_bytes(&pk_bytes).unwrap(); match MLKEM512::keypair_consistency_check(&pk2, &sk) { - Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ }, + Err(KEMError::ConsistencyCheckFailed(_)) => { /* good */ } _ => panic!("Expected error for different key"), }; } diff --git a/crypto/rng/benches/hash_drbg_benches.rs b/crypto/rng/benches/hash_drbg_benches.rs index 0efa434..1aa6138 100644 --- a/crypto/rng/benches/hash_drbg_benches.rs +++ b/crypto/rng/benches/hash_drbg_benches.rs @@ -1,8 +1,8 @@ use bouncycastle_core::key_material::{KeyMaterial0, KeyMaterial256, KeyMaterial512, KeyType}; use bouncycastle_core::traits::{RNG, SecurityStrength}; use bouncycastle_core_test_framework::DUMMY_SEED_512; -use criterion::{Criterion, Throughput, criterion_group, criterion_main}; use bouncycastle_rng::{HashDRBG_SHA256, HashDRBG_SHA512, Sp80090ADrbg}; +use criterion::{Criterion, Throughput, criterion_group, criterion_main}; use std::hint::black_box; fn bench_hash_drbg_sha256(c: &mut Criterion) { diff --git a/crypto/rng/src/hash_drbg80090a.rs b/crypto/rng/src/hash_drbg80090a.rs index 4614692..6debdd8 100644 --- a/crypto/rng/src/hash_drbg80090a.rs +++ b/crypto/rng/src/hash_drbg80090a.rs @@ -6,7 +6,7 @@ use crate::Sp80090ADrbg; use bouncycastle_core::errors::{KeyMaterialError, RNGError}; -use bouncycastle_core::key_material::{KeyMaterial512, KeyType, KeyMaterialTrait}; +use bouncycastle_core::key_material::{KeyMaterial512, KeyMaterialTrait, KeyType}; use bouncycastle_core::traits::{Hash, HashAlgParams, RNG, SecurityStrength}; use bouncycastle_sha2::{SHA256, SHA512}; use bouncycastle_utils::min; @@ -266,7 +266,11 @@ impl Sp80090ADrbg for HashDRBG80090A { Ok(()) } - fn reseed(&mut self, seed: &impl KeyMaterialTrait, additional_input: &[u8]) -> Result<(), RNGError> { + fn reseed( + &mut self, + seed: &impl KeyMaterialTrait, + additional_input: &[u8], + ) -> Result<(), RNGError> { // Hash_DRBG Reseed Process: // 1. seed_material = 0x01 || V || entropy_input || additional_input. // 2. seed = Hash_df (seed_material, seedlen). @@ -475,7 +479,10 @@ impl RNG for HashDRBG80090A { // todo!() // } - fn add_seed_keymaterial(&mut self, additional_seed: impl KeyMaterialTrait) -> Result<(), RNGError> { + fn add_seed_keymaterial( + &mut self, + additional_seed: impl KeyMaterialTrait, + ) -> Result<(), RNGError> { self.reseed(&additional_seed, "add_seed_keymaterial".as_bytes()) } @@ -572,7 +579,19 @@ fn test_hash_df() { assert_ne!(out, [0u8; 100]); // repeatability test // println!("out: {:?}", out); - assert_eq!(out, [150u8, 177u8, 87u8, 145u8, 138u8, 4u8, 164u8, 14u8, 162u8, 43u8, 159u8, 152u8, 121u8, 117u8, 6u8, 18u8, 253u8, 84u8, 41u8, 64u8, 40u8, 209u8, 16u8, 176u8, 106u8, 115u8, 172u8, 193u8, 246u8, 228u8, 208u8, 79u8, 37u8, 31u8, 134u8, 141u8, 200u8, 7u8, 42u8, 199u8, 229u8, 236u8, 236u8, 186u8, 28u8, 87u8, 200u8, 14u8, 127u8, 36u8, 132u8, 23u8, 36u8, 150u8, 23u8, 215u8, 247u8, 121u8, 175u8, 82u8, 99u8, 187u8, 235u8, 25u8, 213u8, 18u8, 106u8, 22u8, 4u8, 99u8, 1u8, 184u8, 211u8, 160u8, 177u8, 67u8, 78u8, 181u8, 69u8, 51u8, 117u8, 2u8, 72u8, 36u8, 134u8, 72u8, 2u8, 9u8, 105u8, 149u8, 136u8, 35u8, 81u8, 114u8, 142u8, 80u8, 94u8, 42u8, 85u8, 155]); + assert_eq!( + out, + [ + 150u8, 177u8, 87u8, 145u8, 138u8, 4u8, 164u8, 14u8, 162u8, 43u8, 159u8, 152u8, 121u8, + 117u8, 6u8, 18u8, 253u8, 84u8, 41u8, 64u8, 40u8, 209u8, 16u8, 176u8, 106u8, 115u8, + 172u8, 193u8, 246u8, 228u8, 208u8, 79u8, 37u8, 31u8, 134u8, 141u8, 200u8, 7u8, 42u8, + 199u8, 229u8, 236u8, 236u8, 186u8, 28u8, 87u8, 200u8, 14u8, 127u8, 36u8, 132u8, 23u8, + 36u8, 150u8, 23u8, 215u8, 247u8, 121u8, 175u8, 82u8, 99u8, 187u8, 235u8, 25u8, 213u8, + 18u8, 106u8, 22u8, 4u8, 99u8, 1u8, 184u8, 211u8, 160u8, 177u8, 67u8, 78u8, 181u8, 69u8, + 51u8, 117u8, 2u8, 72u8, 36u8, 134u8, 72u8, 2u8, 9u8, 105u8, 149u8, 136u8, 35u8, 81u8, + 114u8, 142u8, 80u8, 94u8, 42u8, 85u8, 155 + ] + ); // Test success with out.len() at the maximum allowed for SHA256 (255 * 32 = 8160) let mut out_max_sha256 = vec![0u8; 255 * 32]; diff --git a/crypto/rng/tests/hash_drbg80090a_tests.rs b/crypto/rng/tests/hash_drbg80090a_tests.rs index 8ab4408..e4fd534 100644 --- a/crypto/rng/tests/hash_drbg80090a_tests.rs +++ b/crypto/rng/tests/hash_drbg80090a_tests.rs @@ -1,7 +1,9 @@ #[cfg(test)] mod tests { use bouncycastle_core::errors::{KeyMaterialError, RNGError}; - use bouncycastle_core::key_material::{KeyMaterial0, KeyMaterial256, KeyMaterial, KeyType, KeyMaterialTrait}; + use bouncycastle_core::key_material::{ + KeyMaterial, KeyMaterial0, KeyMaterial256, KeyMaterialTrait, KeyType, + }; use bouncycastle_core::traits::{RNG, SecurityStrength}; use bouncycastle_core_test_framework::DUMMY_SEED_512; use bouncycastle_rng::Sp80090ADrbg; diff --git a/crypto/sha2/src/sha256.rs b/crypto/sha2/src/sha256.rs index 10d45e1..a2effd6 100644 --- a/crypto/sha2/src/sha256.rs +++ b/crypto/sha2/src/sha256.rs @@ -1,8 +1,8 @@ -use crate::{SHA2Params}; -use core::slice; +use crate::SHA2Params; use bouncycastle_core::errors::HashError; use bouncycastle_core::traits::{Hash, SecurityStrength}; use bouncycastle_utils::min; +use core::slice; const SHA256_K: [u32; 64] = [ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, @@ -160,7 +160,8 @@ pub struct SHA256Internal { impl Drop for SHA256Internal { fn drop(&mut self) { self.x_buf.fill(0); - }} + } +} impl SHA256Internal { pub fn new() -> Self { diff --git a/crypto/sha2/src/sha512.rs b/crypto/sha2/src/sha512.rs index 66d5265..9857dcc 100644 --- a/crypto/sha2/src/sha512.rs +++ b/crypto/sha2/src/sha512.rs @@ -1,8 +1,8 @@ use crate::SHA2Params; -use core::slice; use bouncycastle_core::errors::HashError; use bouncycastle_core::traits::{Hash, SecurityStrength}; use bouncycastle_utils::min; +use core::slice; const SHA512_K: [u64; 80] = [ 0x428A2F98D728AE22, 0x7137449123EF65CD, 0xB5C0FBCFEC4D3B2F, 0xE9B5DBA58189DBBC, diff --git a/crypto/sha3/benches/sha3_benches.rs b/crypto/sha3/benches/sha3_benches.rs index a0d0577..e2006a6 100644 --- a/crypto/sha3/benches/sha3_benches.rs +++ b/crypto/sha3/benches/sha3_benches.rs @@ -1,5 +1,5 @@ -use criterion::{Criterion, Throughput, criterion_group, criterion_main}; use bouncycastle_rng as rng; +use criterion::{Criterion, Throughput, criterion_group, criterion_main}; use std::hint::black_box; use bouncycastle_core::traits::{Hash, RNG, XOF}; diff --git a/crypto/sha3/src/sha3.rs b/crypto/sha3/src/sha3.rs index a55ac26..986675c 100644 --- a/crypto/sha3/src/sha3.rs +++ b/crypto/sha3/src/sha3.rs @@ -1,9 +1,9 @@ +use crate::SHA3Params; +use crate::keccak::KeccakDigest; use bouncycastle_core::errors::{HashError, KDFError}; use bouncycastle_core::key_material::{KeyMaterial, KeyMaterialTrait, KeyType}; -use bouncycastle_core::traits::{Hash, SecurityStrength, KDF}; +use bouncycastle_core::traits::{Hash, KDF, SecurityStrength}; use bouncycastle_utils::{max, min}; -use crate::keccak::KeccakDigest; -use crate::SHA3Params; #[derive(Clone)] pub struct SHA3 { @@ -46,7 +46,7 @@ impl SHA3 { &self.kdf_security_strength, &SecurityStrength::from_bits(PARAMS::OUTPUT_LEN * 8 / 2), ) - .clone(); + .clone(); } self.do_update(key.ref_to_bytes()) @@ -246,4 +246,4 @@ impl KDF for SHA3 { fn max_security_strength(&self) -> SecurityStrength { SecurityStrength::from_bytes(PARAMS::OUTPUT_LEN / 2) } -} \ No newline at end of file +} diff --git a/crypto/sha3/src/shake.rs b/crypto/sha3/src/shake.rs index f7cd88e..84c63a1 100644 --- a/crypto/sha3/src/shake.rs +++ b/crypto/sha3/src/shake.rs @@ -1,10 +1,9 @@ +use crate::SHAKEParams; +use crate::keccak::KeccakDigest; use bouncycastle_core::errors::{HashError, KDFError}; use bouncycastle_core::key_material::{KeyMaterial, KeyMaterialTrait, KeyType}; -use bouncycastle_core::traits::{Algorithm, SecurityStrength, KDF, XOF}; +use bouncycastle_core::traits::{Algorithm, KDF, SecurityStrength, XOF}; use bouncycastle_utils::{max, min}; -use crate::keccak::KeccakDigest; -use crate::SHAKEParams; - /// Note: FIPS 202 section 7 states: /// @@ -67,9 +66,11 @@ impl SHAKE { self.kdf_entropy += key.key_len(); self.kdf_security_strength = max(&self.kdf_security_strength, &key.security_strength()).clone(); - self.kdf_security_strength = - min(&self.kdf_security_strength, &SecurityStrength::from_bits(PARAMS::SIZE as usize)) - .clone(); + self.kdf_security_strength = min( + &self.kdf_security_strength, + &SecurityStrength::from_bits(PARAMS::SIZE as usize), + ) + .clone(); } self.absorb(key.ref_to_bytes()) @@ -108,7 +109,11 @@ impl SHAKE { // let mut buf = [0u8; 64]; output_key.allow_hazardous_operations(); - let bytes_written = self.squeeze_out(output_key.mut_ref_to_bytes().expect("We just set .allow_hazardous_operations(), so this should be fine.")); + let bytes_written = self.squeeze_out( + output_key + .mut_ref_to_bytes() + .expect("We just set .allow_hazardous_operations(), so this should be fine."), + ); output_key.set_key_len(bytes_written)?; // since we've done some computation, the result will not actually be zeroized, even if all input key material was zeroized. @@ -271,4 +276,4 @@ impl XOF for SHAKE { fn max_security_strength(&self) -> SecurityStrength { SecurityStrength::from_bits(PARAMS::SIZE as usize) } -} \ No newline at end of file +} diff --git a/crypto/sha3/tests/sha3_tests.rs b/crypto/sha3/tests/sha3_tests.rs index 787e9fb..59a252e 100644 --- a/crypto/sha3/tests/sha3_tests.rs +++ b/crypto/sha3/tests/sha3_tests.rs @@ -1,7 +1,9 @@ #[cfg(test)] mod sha3_tests { use super::sha3_test_helpers::*; - use bouncycastle_core::key_material::{KeyMaterial256, KeyMaterial512, KeyMaterial, KeyType, KeyMaterialTrait,}; + use bouncycastle_core::key_material::{ + KeyMaterial, KeyMaterial256, KeyMaterial512, KeyMaterialTrait, KeyType, + }; use bouncycastle_core::traits::{Hash, HashAlgParams, KDF, SecurityStrength}; use bouncycastle_core_test_framework::DUMMY_SEED_512; use bouncycastle_core_test_framework::hash::TestFrameworkHash; @@ -20,10 +22,10 @@ mod sha3_tests { assert_eq!(SHA3_384::BLOCK_LEN, 104); assert_eq!(SHA3_512::BLOCK_LEN, 72); - assert_eq!(SHA3_224::new().block_bitlen(), 144*8); - assert_eq!(SHA3_256::new().block_bitlen(), 136*8); - assert_eq!(SHA3_384::new().block_bitlen(), 104*8); - assert_eq!(SHA3_512::new().block_bitlen(), 72*8); + assert_eq!(SHA3_224::new().block_bitlen(), 144 * 8); + assert_eq!(SHA3_256::new().block_bitlen(), 136 * 8); + assert_eq!(SHA3_384::new().block_bitlen(), 104 * 8); + assert_eq!(SHA3_512::new().block_bitlen(), 72 * 8); } #[test] diff --git a/crypto/utils/src/ct.rs b/crypto/utils/src/ct.rs index 24ca9bf..eaf92cc 100644 --- a/crypto/utils/src/ct.rs +++ b/crypto/utils/src/ct.rs @@ -143,82 +143,82 @@ impl Condition { // impl Condition { // pub const TRUE: Self = Self(1); // pub const FALSE: Self = Self(0); -// +// // pub const fn new() -> Self { // Self((VALUE as u64).wrapping_neg()) // } -// +// // pub const fn from_bool(value: bool) -> Self { // Self((value as u64).wrapping_neg()) // } -// +// // pub const fn is_bit_set(value: u64, bit: u64) -> Self { // Self(((value >> bit) & 1).wrapping_neg()) // } -// +// // // MikeO: TODO ?? What does "negative" mean for an unsigned value? // pub const fn is_negative(value: u64) -> Self { // Self(((value as i64) >> 63) as u64) // } -// +// // pub const fn is_not_zero(value: u64) -> Self { // Self::is_negative(Self::or_halves(value).wrapping_neg()) // } -// +// // pub const fn is_zero(value: u64) -> Self { // Self::is_negative(Self::or_halves(value).wrapping_sub(1)) // } -// +// // // MikeO: TODO: I borrowed this formula from Botan, but rust complains about u64 subtraction overflow if x < y, so this works in C but won't work in rust. // // MikeO: TODO: I played with u64.wrapping_sub(y) but that doesn't work either. // pub const fn is_lt(x: u64, y: u64) -> Self { // Self::is_zero(x ^ ((x ^ y) | (x.wrapping_sub(y)) ^ x)) // } -// +// // // Note: haven't found a clever way to make this const, since it either needs a (non-const) not (!) or a boolean OR is_zero. // // pub fn is_lte(x: i64, y: i64) -> Self { !Self::is_gt(x, y) } -// +// // // pub const fn is_gt(x: i64, y: i64) -> Self { Self::is_lt(y, x) } -// +// // // Note: haven't found a clever way to make this const, since it either needs a (non-const) not (!) or a boolean OR is_zero. // // pub fn is_gte(x: i64, y: i64) -> Self { !Self::is_lt(x, y) } -// +// // pub fn is_in_list(value: u64, list: &[u64]) -> Self { // // Research question: is this actually constant-time? // // A clever compiler might turn this into a short-circuiting loop. // // A quick google search shows that rust doesn't have the ability to annotate specific code blocks // // as no-optimize; the only option is to insert direct assembly. -// +// // let mut c = Self::FALSE; // for i in 0..list.len() { // let diff = value ^ list[i]; // c |= Condition::::is_zero(diff); // } -// +// // c // } -// +// // pub fn mov(self, src: u64, dst: &mut u64) { // *dst = self.select(src, *dst); // } -// +// // // MikeO: TODO: This needs a docstring because I have no idea what this does. // pub const fn negate(self, value: u64) -> u64 { // (value ^ self.0).wrapping_sub(self.0) // } -// +// // const fn or_halves(value: u64) -> u64 { // (value & 0xFFFFFFFF) | (value >> 32) // } -// +// // pub const fn select(self, true_value: u64, false_value: u64) -> u64 { // (true_value & self.0) | (false_value & !self.0) // } -// +// // pub const fn swap(self, lhs: u64, rhs: u64) -> (u64, u64) { // (self.select(rhs, lhs), self.select(lhs, rhs)) // } -// +// // pub const fn to_bool_var(self) -> bool { // self.0 != 0 // } @@ -327,22 +327,22 @@ pub fn conditional_copy_bytes( a: &[u8; LEN], b: &[u8; LEN], out: &mut [u8; LEN], - take_a: bool) { - - // we want the behaviour of + take_a: bool, +) { + // we want the behaviour of // if take_a { 0xFF } else { 0x00 } // but without using any branches that could leak timing signals - let mask: u8 = (take_a as u8) | - (take_a as u8) <<1 | - (take_a as u8) <<2 | - (take_a as u8) <<3 | - (take_a as u8) <<4 | - (take_a as u8) <<5 | - (take_a as u8) <<6 | - (take_a as u8) <<7; - + let mask: u8 = (take_a as u8) + | (take_a as u8) << 1 + | (take_a as u8) << 2 + | (take_a as u8) << 3 + | (take_a as u8) << 4 + | (take_a as u8) << 5 + | (take_a as u8) << 6 + | (take_a as u8) << 7; + debug_assert_eq!(mask, if take_a { 0xFF } else { 0x00 }); - + for i in 0..LEN { out[i] = std::hint::black_box(a[i] & mask) | std::hint::black_box(b[i] & !mask); } diff --git a/mem_usage_benches/bench_mlkem_mem_usage.rs b/mem_usage_benches/bench_mlkem_mem_usage.rs index 494621f..bd93ac4 100644 --- a/mem_usage_benches/bench_mlkem_mem_usage.rs +++ b/mem_usage_benches/bench_mlkem_mem_usage.rs @@ -11,7 +11,7 @@ //! //! //! To measure code size, Claude suggests: -//! +//! //! To see code size separately: size ./your_binary or readelf -S ./your_binary (look at .text). //! //! Make sure you build in release mode! @@ -26,9 +26,12 @@ #![allow(unused_imports)] use bouncycastle::core::key_material::{KeyMaterial512, KeyType}; -use bouncycastle::core::traits::{KEMPublicKey, KEM}; -use bouncycastle::mlkem::mlkem::{MLKEMTrait}; -use bouncycastle::mlkem::{MLKEM1024_CT_LEN, MLKEM1024_PK_LEN, MLKEM512_CT_LEN, MLKEM512_PK_LEN, MLKEM768_CT_LEN, MLKEM768_PK_LEN}; +use bouncycastle::core::traits::{KEM, KEMPublicKey}; +use bouncycastle::mlkem::mlkem::MLKEMTrait; +use bouncycastle::mlkem::{ + MLKEM512_CT_LEN, MLKEM512_PK_LEN, MLKEM768_CT_LEN, MLKEM768_PK_LEN, MLKEM1024_CT_LEN, + MLKEM1024_PK_LEN, +}; /// This exists so I can use /usr/bin/time to measure the base memory footprint of the cargo bench harness fn bench_do_nothing() { @@ -39,135 +42,209 @@ fn bench_do_nothing() { /// This prints the in-memory size of all the public and private key structs fn print_struct_sizes() { - use core::mem::size_of; use bouncycastle::mlkem; use bouncycastle::mlkem_lowmemory; - + use core::mem::size_of; println!("\nML-KEM-512"); println!("size_of: {}", size_of::()); - println!("size_of: {}", size_of::()); + println!( + "size_of: {}", + size_of::() + ); println!("size_of: {}", size_of::()); - println!("size_of: {}", size_of::()); - + println!( + "size_of: {}", + size_of::() + ); println!("\nML-KEM-768"); println!("size_of: {}", size_of::()); - println!("size_of: {}", size_of::()); + println!( + "size_of: {}", + size_of::() + ); println!("size_of: {}", size_of::()); - println!("size_of: {}", size_of::()); + println!( + "size_of: {}", + size_of::() + ); println!("\nML-KEM-1024"); println!("size_of: {}", size_of::()); - println!("size_of: {}", size_of::()); + println!( + "size_of: {}", + size_of::() + ); println!("size_of: {}", size_of::()); - println!("size_of: {}", size_of::()); + println!( + "size_of: {}", + size_of::() + ); println!("\n\nlowmemory"); println!("\nML-KEM-512_lowmemory"); - println!("size_of: {}", size_of::()); - println!("size_of: {}", size_of::()); - + println!( + "size_of: {}", + size_of::() + ); + println!( + "size_of: {}", + size_of::() + ); println!("\nML-KEM-768_lowmemory"); - println!("size_of: {}", size_of::()); - println!("size_of: {}", size_of::()); + println!( + "size_of: {}", + size_of::() + ); + println!( + "size_of: {}", + size_of::() + ); println!("\nML-KEM-1024_lowmemory"); - println!("size_of: {}", size_of::()); - println!("size_of: {}", size_of::()); + println!( + "size_of: {}", + size_of::() + ); + println!( + "size_of: {}", + size_of::() + ); } fn bench_mlkem512_keygen() { - use bouncycastle::mlkem::{MLKEM512}; + use bouncycastle::mlkem::MLKEM512; eprintln!("MLKEM512/KeyGen"); let seed = KeyMaterial512::from_bytes_as_type( - &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ], KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (pk, _sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); println!("{:x?}", pk.encode()); } fn bench_mlkem512_lowmemory_keygen() { - use bouncycastle::mlkem_lowmemory::{MLKEMTrait, MLKEM512}; + use bouncycastle::mlkem_lowmemory::{MLKEM512, MLKEMTrait}; eprintln!("MLKEM512_lowmemory/KeyGen"); let seed = KeyMaterial512::from_bytes_as_type( - &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ], KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (pk, _sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); println!("{:x?}", pk.encode()); } fn bench_mlkem768_keygen() { - use bouncycastle::mlkem::{MLKEM768}; + use bouncycastle::mlkem::MLKEM768; eprintln!("MLKEM768/KeyGen"); let seed = KeyMaterial512::from_bytes_as_type( - &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ], KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (pk, _sk) = MLKEM768::keygen_from_seed(&seed).unwrap(); println!("{:x?}", pk.encode()); } fn bench_mlkem768_lowmemory_keygen() { - use bouncycastle::mlkem_lowmemory::{MLKEMTrait, MLKEM768}; + use bouncycastle::mlkem_lowmemory::{MLKEM768, MLKEMTrait}; eprintln!("MLKEM768_lowmemory/KeyGen"); let seed = KeyMaterial512::from_bytes_as_type( - &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ], KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (pk, _sk) = MLKEM768::keygen_from_seed(&seed).unwrap(); println!("{:x?}", pk.encode()); } fn bench_mlkem1024_keygen() { - use bouncycastle::mlkem::{MLKEM1024}; + use bouncycastle::mlkem::MLKEM1024; eprintln!("MLKEM1024/KeyGen"); let seed = KeyMaterial512::from_bytes_as_type( - &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ], KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (pk, _sk) = MLKEM1024::keygen_from_seed(&seed).unwrap(); println!("{:x?}", pk.encode()); } fn bench_mlkem1024_lowmemory_keygen() { - use bouncycastle::mlkem_lowmemory::{MLKEMTrait, MLKEM1024}; + use bouncycastle::mlkem_lowmemory::{MLKEM1024, MLKEMTrait}; eprintln!("MLKEM1024_lowmemory/KeyGen"); let seed = KeyMaterial512::from_bytes_as_type( - &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ], KeyType::Seed, - ).unwrap(); + ) + .unwrap(); let (pk, _sk) = MLKEM1024::keygen_from_seed(&seed).unwrap(); println!("{:x?}", pk.encode()); } fn bench_mlkem512_encaps() { - use bouncycastle::mlkem::{MLKEMTrait, MLKEM512, MLKEM512PublicKey}; + use bouncycastle::mlkem::{MLKEM512, MLKEM512PublicKey, MLKEMTrait}; eprintln!("MLKEM512/Encaps"); - /* One-time setup of the KAT -- commented out so that we're not capturing keygen in the bench */ // let seed = KeyMaterial512::from_bytes_as_type( // &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], @@ -178,7 +255,62 @@ fn bench_mlkem512_encaps() { // use bouncycastle_hex as hex; // eprintln!("pk:\n{}", &hex::encode(pk.encode())); - let pk_bytes: [u8; MLKEM512_PK_LEN] = [0x39,0x95,0x81,0x5e,0x59,0x7d,0x10,0x43,0x55,0xcf,0x29,0xaa,0x53,0x33,0xc9,0x32,0x51,0x86,0x9d,0x5b,0xcd,0xbe,0x48,0x71,0x24,0xf6,0x02,0xb8,0xb6,0xa6,0x6c,0x16,0xc4,0x76,0x16,0x48,0xad,0x76,0x5c,0xf5,0xd8,0x00,0x6b,0x51,0x5e,0x90,0x5a,0x7f,0x0a,0xc0,0x76,0xb0,0xc6,0x2e,0xfa,0x32,0x81,0x53,0xe7,0xca,0x57,0x01,0x69,0x9f,0x13,0x05,0xf1,0xe6,0xbc,0x6f,0x90,0xb0,0xe4,0x9b,0x69,0x35,0x12,0xb6,0xce,0x99,0x2a,0x8b,0x80,0x16,0xdd,0xfc,0x1a,0x66,0x2c,0x7e,0x3f,0x96,0x19,0xcb,0xd8,0x69,0xdd,0x77,0x1a,0xf3,0x08,0x96,0xcc,0xd5,0x91,0x8a,0xc6,0xcb,0x77,0x46,0x6c,0x5e,0x77,0x99,0x96,0xd6,0x7f,0xf9,0xaa,0xbc,0x97,0x50,0x3f,0x2c,0x7b,0x7e,0x2d,0x00,0x0d,0x86,0x45,0x0f,0xb1,0x80,0x7c,0xa4,0xca,0xbd,0xa4,0x65,0x82,0x5a,0x31,0xc7,0x89,0xa1,0xb7,0xa4,0x91,0xab,0x38,0x72,0x76,0x5d,0x32,0x0d,0x0b,0x71,0x92,0x0f,0xa2,0x13,0xc9,0x40,0x93,0x41,0x6b,0x83,0xb8,0x12,0x4e,0x69,0xf6,0x5e,0x62,0xcb,0x50,0x00,0xdc,0xc3,0x7a,0xa9,0xa0,0xff,0xf7,0x39,0x70,0xc4,0x77,0x2f,0x35,0x7d,0x24,0x18,0x9c,0xa6,0xf5,0x30,0x55,0x68,0xc0,0xe2,0x37,0x6a,0x37,0x62,0xa6,0x8c,0x60,0x5e,0x56,0x3c,0x5d,0x20,0x95,0x72,0xe0,0xfc,0x75,0x32,0xca,0x29,0x47,0x29,0x53,0x55,0x67,0xb5,0xfc,0x41,0x3c,0x5e,0x87,0x92,0xd2,0x46,0x45,0x36,0xcc,0x80,0x8f,0x98,0xad,0xd7,0x46,0x64,0xf1,0x41,0x56,0x6f,0x90,0x16,0xa9,0x0a,0x54,0x18,0x29,0xa9,0x8a,0x04,0x64,0xce,0x41,0xa8,0xbb,0x44,0xc2,0xd4,0xfa,0x3c,0x2c,0x20,0x94,0x60,0x72,0x8e,0xf1,0x4a,0x1a,0x7c,0x4c,0x9b,0x98,0xd1,0x22,0x03,0xb4,0xcc,0x35,0x29,0x16,0x0a,0x9a,0xb2,0xd7,0x83,0x8f,0x7f,0xf6,0xb5,0x3a,0xe0,0x5a,0xa3,0x1a,0x7d,0x64,0x6b,0x7a,0xfa,0x6c,0x45,0x93,0x25,0x26,0xa3,0xc3,0x75,0x56,0x19,0xbe,0x99,0x4c,0x21,0x1c,0x2a,0x31,0xc0,0x5b,0x34,0x47,0x83,0x6c,0xb2,0x15,0x0b,0xe1,0x82,0x9d,0xae,0x6b,0x04,0xc5,0x53,0x5c,0xff,0x54,0x6e,0x39,0x2b,0xa7,0x97,0x41,0x17,0x20,0xf9,0x24,0xf4,0x90,0xa5,0xac,0x54,0x95,0xf2,0x13,0x56,0xd5,0x50,0xb7,0x82,0xa6,0x4c,0x16,0x88,0xb6,0xb6,0x55,0xbc,0xc7,0x84,0x21,0x97,0xa4,0x34,0xc2,0xf6,0x56,0x3b,0x5b,0x7f,0x09,0xa7,0x8b,0xcc,0x48,0x82,0x32,0x78,0x35,0x61,0xd1,0x6f,0x4c,0xba,0xb6,0x75,0x54,0x00,0x05,0x07,0x81,0x57,0x0c,0x66,0x60,0x4b,0x81,0x7a,0xd1,0x25,0x22,0x94,0x73,0x6e,0x8b,0x01,0x86,0x1a,0x4b,0x5a,0x74,0x51,0x9b,0x8b,0x6f,0xe5,0x14,0x89,0xa5,0x07,0x23,0x92,0xe5,0x87,0x62,0x6c,0x71,0x37,0x76,0x57,0x5d,0x33,0x80,0x6a,0x1c,0x8e,0x27,0x32,0xaf,0x97,0xc2,0x68,0x0f,0x51,0x66,0x63,0x31,0xc4,0xeb,0x8b,0xbc,0x04,0x31,0xc4,0xf9,0x68,0x32,0xda,0xf1,0xb3,0xc4,0x55,0x28,0xfb,0xa1,0x53,0xf6,0xc7,0x8b,0x1c,0x19,0x87,0x02,0x94,0x7c,0xcd,0x33,0x77,0x27,0xa4,0x6f,0xb5,0x3b,0xa1,0x1d,0xe5,0xcb,0x41,0x91,0x34,0x68,0x59,0x51,0x6c,0xb6,0xad,0x72,0x40,0x0f,0x3c,0xf2,0x09,0xb2,0x36,0xae,0xf3,0x5a,0x58,0x0a,0xc8,0x7e,0xb3,0xe3,0x0f,0xaf,0xd6,0x69,0x73,0xca,0x8a,0x7d,0xd2,0x67,0x5a,0xf4,0x1f,0x7a,0x17,0xb6,0x14,0x33,0xcd,0x1a,0xf8,0x0f,0x77,0x08,0x86,0x9f,0x66,0x54,0x88,0x49,0x79,0x80,0xb1,0xac,0x10,0xa0,0xcd,0xcb,0x63,0x6a,0x00,0xed,0x86,0x81,0xb3,0x5e,0x42,0x91,0x24,0xca,0x80,0x35,0x07,0x25,0xb8,0x5f,0x83,0xa5,0xea,0xc3,0xa4,0xa3,0xcc,0x16,0x00,0x90,0x3e,0x65,0x29,0x35,0x60,0xb9,0xb3,0x36,0xe5,0xaf,0x0d,0x52,0x9d,0xac,0x1a,0x04,0x81,0x19,0x30,0x2c,0xb7,0xa9,0xbc,0xc1,0x10,0xb9,0x48,0x51,0xbf,0x02,0x11,0x7f,0x19,0x9d,0xc4,0x85,0xa8,0x52,0xb7,0x47,0x3f,0x09,0xb8,0x31,0xa6,0x83,0x1d,0x5b,0x54,0xc0,0xb7,0x90,0xd2,0x25,0xcf,0x6b,0xb9,0x2d,0x94,0x62,0xa2,0x6c,0xdb,0x33,0xdd,0xa5,0x12,0x3c,0x7a,0xaf,0x0e,0x26,0xa0,0xb8,0x36,0x55,0xee,0xa2,0x8b,0xf3,0xa8,0x07,0x47,0x25,0x01,0x8f,0xd6,0xba,0xe4,0xb6,0x01,0xcf,0x61,0xba,0xab,0x71,0xa7,0xa3,0xd3,0x51,0x97,0xa3,0x43,0xe7,0x4b,0x4a,0x27,0x2c,0x12,0x5d,0x54,0x08,0x96,0x42,0x6d,0x85,0xb7,0x95,0x8d,0x3b,0x38,0xa6,0xba,0x98,0x7e,0xc3,0x72,0x25,0xc7,0xb4,0x4c,0xdb,0x12,0xdd,0xe4,0x53,0x9b,0x4a,0xb0,0x82,0x36,0x36,0x83,0xf0,0x4b,0xf7,0xa0,0x9c,0xc5,0xc4,0x1d,0xfe,0x83,0x0a,0x1b,0x16,0x2e,0x0b,0x32,0x43,0x34,0x36,0x2f,0x08,0x4a,0x14,0x46,0x77,0x23,0x34,0x4b,0xad,0xd0,0x00,0xf8,0xd8,0xc5,0x37,0xc4,0x8f,0x99,0x8f,0x05,0x30,0x7c,0xeb,0xd1,0xed,0xe0,0xb8,0x1c,0x3b,0xc5,0x9a,0x06,0x5a,0x1b,0x6d,0x63,0xb2,0x6c]; + let pk_bytes: [u8; MLKEM512_PK_LEN] = [ + 0x39, 0x95, 0x81, 0x5E, 0x59, 0x7D, 0x10, 0x43, 0x55, 0xCF, 0x29, 0xAA, 0x53, 0x33, 0xC9, + 0x32, 0x51, 0x86, 0x9D, 0x5B, 0xCD, 0xBE, 0x48, 0x71, 0x24, 0xF6, 0x02, 0xB8, 0xB6, 0xA6, + 0x6C, 0x16, 0xC4, 0x76, 0x16, 0x48, 0xAD, 0x76, 0x5C, 0xF5, 0xD8, 0x00, 0x6B, 0x51, 0x5E, + 0x90, 0x5A, 0x7F, 0x0A, 0xC0, 0x76, 0xB0, 0xC6, 0x2E, 0xFA, 0x32, 0x81, 0x53, 0xE7, 0xCA, + 0x57, 0x01, 0x69, 0x9F, 0x13, 0x05, 0xF1, 0xE6, 0xBC, 0x6F, 0x90, 0xB0, 0xE4, 0x9B, 0x69, + 0x35, 0x12, 0xB6, 0xCE, 0x99, 0x2A, 0x8B, 0x80, 0x16, 0xDD, 0xFC, 0x1A, 0x66, 0x2C, 0x7E, + 0x3F, 0x96, 0x19, 0xCB, 0xD8, 0x69, 0xDD, 0x77, 0x1A, 0xF3, 0x08, 0x96, 0xCC, 0xD5, 0x91, + 0x8A, 0xC6, 0xCB, 0x77, 0x46, 0x6C, 0x5E, 0x77, 0x99, 0x96, 0xD6, 0x7F, 0xF9, 0xAA, 0xBC, + 0x97, 0x50, 0x3F, 0x2C, 0x7B, 0x7E, 0x2D, 0x00, 0x0D, 0x86, 0x45, 0x0F, 0xB1, 0x80, 0x7C, + 0xA4, 0xCA, 0xBD, 0xA4, 0x65, 0x82, 0x5A, 0x31, 0xC7, 0x89, 0xA1, 0xB7, 0xA4, 0x91, 0xAB, + 0x38, 0x72, 0x76, 0x5D, 0x32, 0x0D, 0x0B, 0x71, 0x92, 0x0F, 0xA2, 0x13, 0xC9, 0x40, 0x93, + 0x41, 0x6B, 0x83, 0xB8, 0x12, 0x4E, 0x69, 0xF6, 0x5E, 0x62, 0xCB, 0x50, 0x00, 0xDC, 0xC3, + 0x7A, 0xA9, 0xA0, 0xFF, 0xF7, 0x39, 0x70, 0xC4, 0x77, 0x2F, 0x35, 0x7D, 0x24, 0x18, 0x9C, + 0xA6, 0xF5, 0x30, 0x55, 0x68, 0xC0, 0xE2, 0x37, 0x6A, 0x37, 0x62, 0xA6, 0x8C, 0x60, 0x5E, + 0x56, 0x3C, 0x5D, 0x20, 0x95, 0x72, 0xE0, 0xFC, 0x75, 0x32, 0xCA, 0x29, 0x47, 0x29, 0x53, + 0x55, 0x67, 0xB5, 0xFC, 0x41, 0x3C, 0x5E, 0x87, 0x92, 0xD2, 0x46, 0x45, 0x36, 0xCC, 0x80, + 0x8F, 0x98, 0xAD, 0xD7, 0x46, 0x64, 0xF1, 0x41, 0x56, 0x6F, 0x90, 0x16, 0xA9, 0x0A, 0x54, + 0x18, 0x29, 0xA9, 0x8A, 0x04, 0x64, 0xCE, 0x41, 0xA8, 0xBB, 0x44, 0xC2, 0xD4, 0xFA, 0x3C, + 0x2C, 0x20, 0x94, 0x60, 0x72, 0x8E, 0xF1, 0x4A, 0x1A, 0x7C, 0x4C, 0x9B, 0x98, 0xD1, 0x22, + 0x03, 0xB4, 0xCC, 0x35, 0x29, 0x16, 0x0A, 0x9A, 0xB2, 0xD7, 0x83, 0x8F, 0x7F, 0xF6, 0xB5, + 0x3A, 0xE0, 0x5A, 0xA3, 0x1A, 0x7D, 0x64, 0x6B, 0x7A, 0xFA, 0x6C, 0x45, 0x93, 0x25, 0x26, + 0xA3, 0xC3, 0x75, 0x56, 0x19, 0xBE, 0x99, 0x4C, 0x21, 0x1C, 0x2A, 0x31, 0xC0, 0x5B, 0x34, + 0x47, 0x83, 0x6C, 0xB2, 0x15, 0x0B, 0xE1, 0x82, 0x9D, 0xAE, 0x6B, 0x04, 0xC5, 0x53, 0x5C, + 0xFF, 0x54, 0x6E, 0x39, 0x2B, 0xA7, 0x97, 0x41, 0x17, 0x20, 0xF9, 0x24, 0xF4, 0x90, 0xA5, + 0xAC, 0x54, 0x95, 0xF2, 0x13, 0x56, 0xD5, 0x50, 0xB7, 0x82, 0xA6, 0x4C, 0x16, 0x88, 0xB6, + 0xB6, 0x55, 0xBC, 0xC7, 0x84, 0x21, 0x97, 0xA4, 0x34, 0xC2, 0xF6, 0x56, 0x3B, 0x5B, 0x7F, + 0x09, 0xA7, 0x8B, 0xCC, 0x48, 0x82, 0x32, 0x78, 0x35, 0x61, 0xD1, 0x6F, 0x4C, 0xBA, 0xB6, + 0x75, 0x54, 0x00, 0x05, 0x07, 0x81, 0x57, 0x0C, 0x66, 0x60, 0x4B, 0x81, 0x7A, 0xD1, 0x25, + 0x22, 0x94, 0x73, 0x6E, 0x8B, 0x01, 0x86, 0x1A, 0x4B, 0x5A, 0x74, 0x51, 0x9B, 0x8B, 0x6F, + 0xE5, 0x14, 0x89, 0xA5, 0x07, 0x23, 0x92, 0xE5, 0x87, 0x62, 0x6C, 0x71, 0x37, 0x76, 0x57, + 0x5D, 0x33, 0x80, 0x6A, 0x1C, 0x8E, 0x27, 0x32, 0xAF, 0x97, 0xC2, 0x68, 0x0F, 0x51, 0x66, + 0x63, 0x31, 0xC4, 0xEB, 0x8B, 0xBC, 0x04, 0x31, 0xC4, 0xF9, 0x68, 0x32, 0xDA, 0xF1, 0xB3, + 0xC4, 0x55, 0x28, 0xFB, 0xA1, 0x53, 0xF6, 0xC7, 0x8B, 0x1C, 0x19, 0x87, 0x02, 0x94, 0x7C, + 0xCD, 0x33, 0x77, 0x27, 0xA4, 0x6F, 0xB5, 0x3B, 0xA1, 0x1D, 0xE5, 0xCB, 0x41, 0x91, 0x34, + 0x68, 0x59, 0x51, 0x6C, 0xB6, 0xAD, 0x72, 0x40, 0x0F, 0x3C, 0xF2, 0x09, 0xB2, 0x36, 0xAE, + 0xF3, 0x5A, 0x58, 0x0A, 0xC8, 0x7E, 0xB3, 0xE3, 0x0F, 0xAF, 0xD6, 0x69, 0x73, 0xCA, 0x8A, + 0x7D, 0xD2, 0x67, 0x5A, 0xF4, 0x1F, 0x7A, 0x17, 0xB6, 0x14, 0x33, 0xCD, 0x1A, 0xF8, 0x0F, + 0x77, 0x08, 0x86, 0x9F, 0x66, 0x54, 0x88, 0x49, 0x79, 0x80, 0xB1, 0xAC, 0x10, 0xA0, 0xCD, + 0xCB, 0x63, 0x6A, 0x00, 0xED, 0x86, 0x81, 0xB3, 0x5E, 0x42, 0x91, 0x24, 0xCA, 0x80, 0x35, + 0x07, 0x25, 0xB8, 0x5F, 0x83, 0xA5, 0xEA, 0xC3, 0xA4, 0xA3, 0xCC, 0x16, 0x00, 0x90, 0x3E, + 0x65, 0x29, 0x35, 0x60, 0xB9, 0xB3, 0x36, 0xE5, 0xAF, 0x0D, 0x52, 0x9D, 0xAC, 0x1A, 0x04, + 0x81, 0x19, 0x30, 0x2C, 0xB7, 0xA9, 0xBC, 0xC1, 0x10, 0xB9, 0x48, 0x51, 0xBF, 0x02, 0x11, + 0x7F, 0x19, 0x9D, 0xC4, 0x85, 0xA8, 0x52, 0xB7, 0x47, 0x3F, 0x09, 0xB8, 0x31, 0xA6, 0x83, + 0x1D, 0x5B, 0x54, 0xC0, 0xB7, 0x90, 0xD2, 0x25, 0xCF, 0x6B, 0xB9, 0x2D, 0x94, 0x62, 0xA2, + 0x6C, 0xDB, 0x33, 0xDD, 0xA5, 0x12, 0x3C, 0x7A, 0xAF, 0x0E, 0x26, 0xA0, 0xB8, 0x36, 0x55, + 0xEE, 0xA2, 0x8B, 0xF3, 0xA8, 0x07, 0x47, 0x25, 0x01, 0x8F, 0xD6, 0xBA, 0xE4, 0xB6, 0x01, + 0xCF, 0x61, 0xBA, 0xAB, 0x71, 0xA7, 0xA3, 0xD3, 0x51, 0x97, 0xA3, 0x43, 0xE7, 0x4B, 0x4A, + 0x27, 0x2C, 0x12, 0x5D, 0x54, 0x08, 0x96, 0x42, 0x6D, 0x85, 0xB7, 0x95, 0x8D, 0x3B, 0x38, + 0xA6, 0xBA, 0x98, 0x7E, 0xC3, 0x72, 0x25, 0xC7, 0xB4, 0x4C, 0xDB, 0x12, 0xDD, 0xE4, 0x53, + 0x9B, 0x4A, 0xB0, 0x82, 0x36, 0x36, 0x83, 0xF0, 0x4B, 0xF7, 0xA0, 0x9C, 0xC5, 0xC4, 0x1D, + 0xFE, 0x83, 0x0A, 0x1B, 0x16, 0x2E, 0x0B, 0x32, 0x43, 0x34, 0x36, 0x2F, 0x08, 0x4A, 0x14, + 0x46, 0x77, 0x23, 0x34, 0x4B, 0xAD, 0xD0, 0x00, 0xF8, 0xD8, 0xC5, 0x37, 0xC4, 0x8F, 0x99, + 0x8F, 0x05, 0x30, 0x7C, 0xEB, 0xD1, 0xED, 0xE0, 0xB8, 0x1C, 0x3B, 0xC5, 0x9A, 0x06, 0x5A, + 0x1B, 0x6D, 0x63, 0xB2, 0x6C, + ]; let pk = MLKEM512PublicKey::from_bytes(&pk_bytes).unwrap(); let (ss, ct) = MLKEM512::encaps(&pk).unwrap(); print!("{:x?}", ss); @@ -186,11 +318,10 @@ fn bench_mlkem512_encaps() { } fn bench_mlkem512_lowmemory_encaps() { - use bouncycastle::mlkem_lowmemory::{MLKEMTrait, MLKEM512, MLKEM512PublicKey}; + use bouncycastle::mlkem_lowmemory::{MLKEM512, MLKEM512PublicKey, MLKEMTrait}; eprintln!("MLKEM512_lowmemory/Encaps"); - /* One-time setup of the KAT -- commented out so that we're not capturing keygen in the bench */ // let seed = KeyMaterial512::from_bytes_as_type( // &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], @@ -201,7 +332,62 @@ fn bench_mlkem512_lowmemory_encaps() { // use bouncycastle_hex as hex; // eprintln!("pk:\n{}", &hex::encode(pk.encode())); - let pk_bytes: [u8; MLKEM512_PK_LEN] = [0x39,0x95,0x81,0x5e,0x59,0x7d,0x10,0x43,0x55,0xcf,0x29,0xaa,0x53,0x33,0xc9,0x32,0x51,0x86,0x9d,0x5b,0xcd,0xbe,0x48,0x71,0x24,0xf6,0x02,0xb8,0xb6,0xa6,0x6c,0x16,0xc4,0x76,0x16,0x48,0xad,0x76,0x5c,0xf5,0xd8,0x00,0x6b,0x51,0x5e,0x90,0x5a,0x7f,0x0a,0xc0,0x76,0xb0,0xc6,0x2e,0xfa,0x32,0x81,0x53,0xe7,0xca,0x57,0x01,0x69,0x9f,0x13,0x05,0xf1,0xe6,0xbc,0x6f,0x90,0xb0,0xe4,0x9b,0x69,0x35,0x12,0xb6,0xce,0x99,0x2a,0x8b,0x80,0x16,0xdd,0xfc,0x1a,0x66,0x2c,0x7e,0x3f,0x96,0x19,0xcb,0xd8,0x69,0xdd,0x77,0x1a,0xf3,0x08,0x96,0xcc,0xd5,0x91,0x8a,0xc6,0xcb,0x77,0x46,0x6c,0x5e,0x77,0x99,0x96,0xd6,0x7f,0xf9,0xaa,0xbc,0x97,0x50,0x3f,0x2c,0x7b,0x7e,0x2d,0x00,0x0d,0x86,0x45,0x0f,0xb1,0x80,0x7c,0xa4,0xca,0xbd,0xa4,0x65,0x82,0x5a,0x31,0xc7,0x89,0xa1,0xb7,0xa4,0x91,0xab,0x38,0x72,0x76,0x5d,0x32,0x0d,0x0b,0x71,0x92,0x0f,0xa2,0x13,0xc9,0x40,0x93,0x41,0x6b,0x83,0xb8,0x12,0x4e,0x69,0xf6,0x5e,0x62,0xcb,0x50,0x00,0xdc,0xc3,0x7a,0xa9,0xa0,0xff,0xf7,0x39,0x70,0xc4,0x77,0x2f,0x35,0x7d,0x24,0x18,0x9c,0xa6,0xf5,0x30,0x55,0x68,0xc0,0xe2,0x37,0x6a,0x37,0x62,0xa6,0x8c,0x60,0x5e,0x56,0x3c,0x5d,0x20,0x95,0x72,0xe0,0xfc,0x75,0x32,0xca,0x29,0x47,0x29,0x53,0x55,0x67,0xb5,0xfc,0x41,0x3c,0x5e,0x87,0x92,0xd2,0x46,0x45,0x36,0xcc,0x80,0x8f,0x98,0xad,0xd7,0x46,0x64,0xf1,0x41,0x56,0x6f,0x90,0x16,0xa9,0x0a,0x54,0x18,0x29,0xa9,0x8a,0x04,0x64,0xce,0x41,0xa8,0xbb,0x44,0xc2,0xd4,0xfa,0x3c,0x2c,0x20,0x94,0x60,0x72,0x8e,0xf1,0x4a,0x1a,0x7c,0x4c,0x9b,0x98,0xd1,0x22,0x03,0xb4,0xcc,0x35,0x29,0x16,0x0a,0x9a,0xb2,0xd7,0x83,0x8f,0x7f,0xf6,0xb5,0x3a,0xe0,0x5a,0xa3,0x1a,0x7d,0x64,0x6b,0x7a,0xfa,0x6c,0x45,0x93,0x25,0x26,0xa3,0xc3,0x75,0x56,0x19,0xbe,0x99,0x4c,0x21,0x1c,0x2a,0x31,0xc0,0x5b,0x34,0x47,0x83,0x6c,0xb2,0x15,0x0b,0xe1,0x82,0x9d,0xae,0x6b,0x04,0xc5,0x53,0x5c,0xff,0x54,0x6e,0x39,0x2b,0xa7,0x97,0x41,0x17,0x20,0xf9,0x24,0xf4,0x90,0xa5,0xac,0x54,0x95,0xf2,0x13,0x56,0xd5,0x50,0xb7,0x82,0xa6,0x4c,0x16,0x88,0xb6,0xb6,0x55,0xbc,0xc7,0x84,0x21,0x97,0xa4,0x34,0xc2,0xf6,0x56,0x3b,0x5b,0x7f,0x09,0xa7,0x8b,0xcc,0x48,0x82,0x32,0x78,0x35,0x61,0xd1,0x6f,0x4c,0xba,0xb6,0x75,0x54,0x00,0x05,0x07,0x81,0x57,0x0c,0x66,0x60,0x4b,0x81,0x7a,0xd1,0x25,0x22,0x94,0x73,0x6e,0x8b,0x01,0x86,0x1a,0x4b,0x5a,0x74,0x51,0x9b,0x8b,0x6f,0xe5,0x14,0x89,0xa5,0x07,0x23,0x92,0xe5,0x87,0x62,0x6c,0x71,0x37,0x76,0x57,0x5d,0x33,0x80,0x6a,0x1c,0x8e,0x27,0x32,0xaf,0x97,0xc2,0x68,0x0f,0x51,0x66,0x63,0x31,0xc4,0xeb,0x8b,0xbc,0x04,0x31,0xc4,0xf9,0x68,0x32,0xda,0xf1,0xb3,0xc4,0x55,0x28,0xfb,0xa1,0x53,0xf6,0xc7,0x8b,0x1c,0x19,0x87,0x02,0x94,0x7c,0xcd,0x33,0x77,0x27,0xa4,0x6f,0xb5,0x3b,0xa1,0x1d,0xe5,0xcb,0x41,0x91,0x34,0x68,0x59,0x51,0x6c,0xb6,0xad,0x72,0x40,0x0f,0x3c,0xf2,0x09,0xb2,0x36,0xae,0xf3,0x5a,0x58,0x0a,0xc8,0x7e,0xb3,0xe3,0x0f,0xaf,0xd6,0x69,0x73,0xca,0x8a,0x7d,0xd2,0x67,0x5a,0xf4,0x1f,0x7a,0x17,0xb6,0x14,0x33,0xcd,0x1a,0xf8,0x0f,0x77,0x08,0x86,0x9f,0x66,0x54,0x88,0x49,0x79,0x80,0xb1,0xac,0x10,0xa0,0xcd,0xcb,0x63,0x6a,0x00,0xed,0x86,0x81,0xb3,0x5e,0x42,0x91,0x24,0xca,0x80,0x35,0x07,0x25,0xb8,0x5f,0x83,0xa5,0xea,0xc3,0xa4,0xa3,0xcc,0x16,0x00,0x90,0x3e,0x65,0x29,0x35,0x60,0xb9,0xb3,0x36,0xe5,0xaf,0x0d,0x52,0x9d,0xac,0x1a,0x04,0x81,0x19,0x30,0x2c,0xb7,0xa9,0xbc,0xc1,0x10,0xb9,0x48,0x51,0xbf,0x02,0x11,0x7f,0x19,0x9d,0xc4,0x85,0xa8,0x52,0xb7,0x47,0x3f,0x09,0xb8,0x31,0xa6,0x83,0x1d,0x5b,0x54,0xc0,0xb7,0x90,0xd2,0x25,0xcf,0x6b,0xb9,0x2d,0x94,0x62,0xa2,0x6c,0xdb,0x33,0xdd,0xa5,0x12,0x3c,0x7a,0xaf,0x0e,0x26,0xa0,0xb8,0x36,0x55,0xee,0xa2,0x8b,0xf3,0xa8,0x07,0x47,0x25,0x01,0x8f,0xd6,0xba,0xe4,0xb6,0x01,0xcf,0x61,0xba,0xab,0x71,0xa7,0xa3,0xd3,0x51,0x97,0xa3,0x43,0xe7,0x4b,0x4a,0x27,0x2c,0x12,0x5d,0x54,0x08,0x96,0x42,0x6d,0x85,0xb7,0x95,0x8d,0x3b,0x38,0xa6,0xba,0x98,0x7e,0xc3,0x72,0x25,0xc7,0xb4,0x4c,0xdb,0x12,0xdd,0xe4,0x53,0x9b,0x4a,0xb0,0x82,0x36,0x36,0x83,0xf0,0x4b,0xf7,0xa0,0x9c,0xc5,0xc4,0x1d,0xfe,0x83,0x0a,0x1b,0x16,0x2e,0x0b,0x32,0x43,0x34,0x36,0x2f,0x08,0x4a,0x14,0x46,0x77,0x23,0x34,0x4b,0xad,0xd0,0x00,0xf8,0xd8,0xc5,0x37,0xc4,0x8f,0x99,0x8f,0x05,0x30,0x7c,0xeb,0xd1,0xed,0xe0,0xb8,0x1c,0x3b,0xc5,0x9a,0x06,0x5a,0x1b,0x6d,0x63,0xb2,0x6c]; + let pk_bytes: [u8; MLKEM512_PK_LEN] = [ + 0x39, 0x95, 0x81, 0x5E, 0x59, 0x7D, 0x10, 0x43, 0x55, 0xCF, 0x29, 0xAA, 0x53, 0x33, 0xC9, + 0x32, 0x51, 0x86, 0x9D, 0x5B, 0xCD, 0xBE, 0x48, 0x71, 0x24, 0xF6, 0x02, 0xB8, 0xB6, 0xA6, + 0x6C, 0x16, 0xC4, 0x76, 0x16, 0x48, 0xAD, 0x76, 0x5C, 0xF5, 0xD8, 0x00, 0x6B, 0x51, 0x5E, + 0x90, 0x5A, 0x7F, 0x0A, 0xC0, 0x76, 0xB0, 0xC6, 0x2E, 0xFA, 0x32, 0x81, 0x53, 0xE7, 0xCA, + 0x57, 0x01, 0x69, 0x9F, 0x13, 0x05, 0xF1, 0xE6, 0xBC, 0x6F, 0x90, 0xB0, 0xE4, 0x9B, 0x69, + 0x35, 0x12, 0xB6, 0xCE, 0x99, 0x2A, 0x8B, 0x80, 0x16, 0xDD, 0xFC, 0x1A, 0x66, 0x2C, 0x7E, + 0x3F, 0x96, 0x19, 0xCB, 0xD8, 0x69, 0xDD, 0x77, 0x1A, 0xF3, 0x08, 0x96, 0xCC, 0xD5, 0x91, + 0x8A, 0xC6, 0xCB, 0x77, 0x46, 0x6C, 0x5E, 0x77, 0x99, 0x96, 0xD6, 0x7F, 0xF9, 0xAA, 0xBC, + 0x97, 0x50, 0x3F, 0x2C, 0x7B, 0x7E, 0x2D, 0x00, 0x0D, 0x86, 0x45, 0x0F, 0xB1, 0x80, 0x7C, + 0xA4, 0xCA, 0xBD, 0xA4, 0x65, 0x82, 0x5A, 0x31, 0xC7, 0x89, 0xA1, 0xB7, 0xA4, 0x91, 0xAB, + 0x38, 0x72, 0x76, 0x5D, 0x32, 0x0D, 0x0B, 0x71, 0x92, 0x0F, 0xA2, 0x13, 0xC9, 0x40, 0x93, + 0x41, 0x6B, 0x83, 0xB8, 0x12, 0x4E, 0x69, 0xF6, 0x5E, 0x62, 0xCB, 0x50, 0x00, 0xDC, 0xC3, + 0x7A, 0xA9, 0xA0, 0xFF, 0xF7, 0x39, 0x70, 0xC4, 0x77, 0x2F, 0x35, 0x7D, 0x24, 0x18, 0x9C, + 0xA6, 0xF5, 0x30, 0x55, 0x68, 0xC0, 0xE2, 0x37, 0x6A, 0x37, 0x62, 0xA6, 0x8C, 0x60, 0x5E, + 0x56, 0x3C, 0x5D, 0x20, 0x95, 0x72, 0xE0, 0xFC, 0x75, 0x32, 0xCA, 0x29, 0x47, 0x29, 0x53, + 0x55, 0x67, 0xB5, 0xFC, 0x41, 0x3C, 0x5E, 0x87, 0x92, 0xD2, 0x46, 0x45, 0x36, 0xCC, 0x80, + 0x8F, 0x98, 0xAD, 0xD7, 0x46, 0x64, 0xF1, 0x41, 0x56, 0x6F, 0x90, 0x16, 0xA9, 0x0A, 0x54, + 0x18, 0x29, 0xA9, 0x8A, 0x04, 0x64, 0xCE, 0x41, 0xA8, 0xBB, 0x44, 0xC2, 0xD4, 0xFA, 0x3C, + 0x2C, 0x20, 0x94, 0x60, 0x72, 0x8E, 0xF1, 0x4A, 0x1A, 0x7C, 0x4C, 0x9B, 0x98, 0xD1, 0x22, + 0x03, 0xB4, 0xCC, 0x35, 0x29, 0x16, 0x0A, 0x9A, 0xB2, 0xD7, 0x83, 0x8F, 0x7F, 0xF6, 0xB5, + 0x3A, 0xE0, 0x5A, 0xA3, 0x1A, 0x7D, 0x64, 0x6B, 0x7A, 0xFA, 0x6C, 0x45, 0x93, 0x25, 0x26, + 0xA3, 0xC3, 0x75, 0x56, 0x19, 0xBE, 0x99, 0x4C, 0x21, 0x1C, 0x2A, 0x31, 0xC0, 0x5B, 0x34, + 0x47, 0x83, 0x6C, 0xB2, 0x15, 0x0B, 0xE1, 0x82, 0x9D, 0xAE, 0x6B, 0x04, 0xC5, 0x53, 0x5C, + 0xFF, 0x54, 0x6E, 0x39, 0x2B, 0xA7, 0x97, 0x41, 0x17, 0x20, 0xF9, 0x24, 0xF4, 0x90, 0xA5, + 0xAC, 0x54, 0x95, 0xF2, 0x13, 0x56, 0xD5, 0x50, 0xB7, 0x82, 0xA6, 0x4C, 0x16, 0x88, 0xB6, + 0xB6, 0x55, 0xBC, 0xC7, 0x84, 0x21, 0x97, 0xA4, 0x34, 0xC2, 0xF6, 0x56, 0x3B, 0x5B, 0x7F, + 0x09, 0xA7, 0x8B, 0xCC, 0x48, 0x82, 0x32, 0x78, 0x35, 0x61, 0xD1, 0x6F, 0x4C, 0xBA, 0xB6, + 0x75, 0x54, 0x00, 0x05, 0x07, 0x81, 0x57, 0x0C, 0x66, 0x60, 0x4B, 0x81, 0x7A, 0xD1, 0x25, + 0x22, 0x94, 0x73, 0x6E, 0x8B, 0x01, 0x86, 0x1A, 0x4B, 0x5A, 0x74, 0x51, 0x9B, 0x8B, 0x6F, + 0xE5, 0x14, 0x89, 0xA5, 0x07, 0x23, 0x92, 0xE5, 0x87, 0x62, 0x6C, 0x71, 0x37, 0x76, 0x57, + 0x5D, 0x33, 0x80, 0x6A, 0x1C, 0x8E, 0x27, 0x32, 0xAF, 0x97, 0xC2, 0x68, 0x0F, 0x51, 0x66, + 0x63, 0x31, 0xC4, 0xEB, 0x8B, 0xBC, 0x04, 0x31, 0xC4, 0xF9, 0x68, 0x32, 0xDA, 0xF1, 0xB3, + 0xC4, 0x55, 0x28, 0xFB, 0xA1, 0x53, 0xF6, 0xC7, 0x8B, 0x1C, 0x19, 0x87, 0x02, 0x94, 0x7C, + 0xCD, 0x33, 0x77, 0x27, 0xA4, 0x6F, 0xB5, 0x3B, 0xA1, 0x1D, 0xE5, 0xCB, 0x41, 0x91, 0x34, + 0x68, 0x59, 0x51, 0x6C, 0xB6, 0xAD, 0x72, 0x40, 0x0F, 0x3C, 0xF2, 0x09, 0xB2, 0x36, 0xAE, + 0xF3, 0x5A, 0x58, 0x0A, 0xC8, 0x7E, 0xB3, 0xE3, 0x0F, 0xAF, 0xD6, 0x69, 0x73, 0xCA, 0x8A, + 0x7D, 0xD2, 0x67, 0x5A, 0xF4, 0x1F, 0x7A, 0x17, 0xB6, 0x14, 0x33, 0xCD, 0x1A, 0xF8, 0x0F, + 0x77, 0x08, 0x86, 0x9F, 0x66, 0x54, 0x88, 0x49, 0x79, 0x80, 0xB1, 0xAC, 0x10, 0xA0, 0xCD, + 0xCB, 0x63, 0x6A, 0x00, 0xED, 0x86, 0x81, 0xB3, 0x5E, 0x42, 0x91, 0x24, 0xCA, 0x80, 0x35, + 0x07, 0x25, 0xB8, 0x5F, 0x83, 0xA5, 0xEA, 0xC3, 0xA4, 0xA3, 0xCC, 0x16, 0x00, 0x90, 0x3E, + 0x65, 0x29, 0x35, 0x60, 0xB9, 0xB3, 0x36, 0xE5, 0xAF, 0x0D, 0x52, 0x9D, 0xAC, 0x1A, 0x04, + 0x81, 0x19, 0x30, 0x2C, 0xB7, 0xA9, 0xBC, 0xC1, 0x10, 0xB9, 0x48, 0x51, 0xBF, 0x02, 0x11, + 0x7F, 0x19, 0x9D, 0xC4, 0x85, 0xA8, 0x52, 0xB7, 0x47, 0x3F, 0x09, 0xB8, 0x31, 0xA6, 0x83, + 0x1D, 0x5B, 0x54, 0xC0, 0xB7, 0x90, 0xD2, 0x25, 0xCF, 0x6B, 0xB9, 0x2D, 0x94, 0x62, 0xA2, + 0x6C, 0xDB, 0x33, 0xDD, 0xA5, 0x12, 0x3C, 0x7A, 0xAF, 0x0E, 0x26, 0xA0, 0xB8, 0x36, 0x55, + 0xEE, 0xA2, 0x8B, 0xF3, 0xA8, 0x07, 0x47, 0x25, 0x01, 0x8F, 0xD6, 0xBA, 0xE4, 0xB6, 0x01, + 0xCF, 0x61, 0xBA, 0xAB, 0x71, 0xA7, 0xA3, 0xD3, 0x51, 0x97, 0xA3, 0x43, 0xE7, 0x4B, 0x4A, + 0x27, 0x2C, 0x12, 0x5D, 0x54, 0x08, 0x96, 0x42, 0x6D, 0x85, 0xB7, 0x95, 0x8D, 0x3B, 0x38, + 0xA6, 0xBA, 0x98, 0x7E, 0xC3, 0x72, 0x25, 0xC7, 0xB4, 0x4C, 0xDB, 0x12, 0xDD, 0xE4, 0x53, + 0x9B, 0x4A, 0xB0, 0x82, 0x36, 0x36, 0x83, 0xF0, 0x4B, 0xF7, 0xA0, 0x9C, 0xC5, 0xC4, 0x1D, + 0xFE, 0x83, 0x0A, 0x1B, 0x16, 0x2E, 0x0B, 0x32, 0x43, 0x34, 0x36, 0x2F, 0x08, 0x4A, 0x14, + 0x46, 0x77, 0x23, 0x34, 0x4B, 0xAD, 0xD0, 0x00, 0xF8, 0xD8, 0xC5, 0x37, 0xC4, 0x8F, 0x99, + 0x8F, 0x05, 0x30, 0x7C, 0xEB, 0xD1, 0xED, 0xE0, 0xB8, 0x1C, 0x3B, 0xC5, 0x9A, 0x06, 0x5A, + 0x1B, 0x6D, 0x63, 0xB2, 0x6C, + ]; let pk = MLKEM512PublicKey::from_bytes(&pk_bytes).unwrap(); let (ss, ct) = MLKEM512::encaps(&pk).unwrap(); print!("{:x?}", ss); @@ -209,7 +395,7 @@ fn bench_mlkem512_lowmemory_encaps() { } fn bench_mlkem768_encaps() { - use bouncycastle::mlkem::{MLKEMTrait, MLKEM768, MLKEM768PublicKey}; + use bouncycastle::mlkem::{MLKEM768, MLKEM768PublicKey, MLKEMTrait}; eprintln!("MLKEM768/Encaps"); @@ -223,7 +409,87 @@ fn bench_mlkem768_encaps() { // use bouncycastle_hex as hex; // eprintln!("pk:\n{}", &hex::encode(pk.encode())); - let pk_bytes: [u8; MLKEM768_PK_LEN] = [0x29,0x8a,0xa1,0x0d,0x42,0x3c,0x8d,0xda,0x06,0x9d,0x02,0xbc,0x59,0xe6,0xcd,0xf0,0x3a,0x09,0x6b,0x8b,0x3d,0xa4,0xca,0xb9,0xb8,0x0c,0xa4,0xa1,0x49,0x07,0x67,0x2c,0xce,0xf1,0xec,0x4f,0xaf,0x23,0x4a,0x0b,0xc5,0xb7,0xe9,0xd4,0x73,0xf2,0xb3,0x13,0x3b,0x3b,0x26,0xa1,0xd1,0x75,0xcb,0x67,0xa7,0x80,0x59,0x19,0x69,0x9c,0x02,0xf7,0x65,0x31,0xb9,0x9c,0x5f,0x89,0x18,0x07,0x04,0xbb,0x4c,0xa4,0x53,0x5c,0x5b,0x89,0x72,0x67,0x9c,0x66,0x0a,0x07,0xc5,0xe5,0x14,0xb8,0x70,0x09,0xc8,0x62,0xeb,0x8f,0x51,0x57,0x69,0x5e,0xfb,0x3f,0xc4,0x0a,0x9d,0xef,0x6b,0x81,0xc1,0xcc,0x02,0xa2,0x49,0xae,0x4f,0x09,0x4a,0xd0,0xd9,0xbd,0x34,0x85,0xc1,0xc1,0xc6,0x80,0x80,0x52,0x0a,0x7c,0x8c,0x63,0x20,0x32,0xce,0xe7,0x38,0x15,0x4e,0x5c,0x51,0x76,0xc0,0x7d,0xa5,0x60,0x24,0x77,0x6a,0x43,0x0f,0xe7,0x6e,0xac,0xf6,0x65,0xa3,0xf7,0xb8,0x32,0x10,0x22,0x15,0xbc,0x82,0xf1,0x09,0x39,0xc8,0x35,0x57,0x04,0x33,0x6a,0x8f,0xac,0x1d,0x81,0xe4,0xbb,0x04,0x85,0xaa,0x5d,0x7c,0x74,0xd6,0xb5,0x9b,0xbe,0x5c,0x5e,0x97,0x2a,0x0d,0x8b,0xac,0x41,0x1b,0x55,0xb5,0xd5,0x55,0x7c,0xd6,0x80,0xa1,0xa8,0xf7,0x1b,0x4e,0xb8,0x6b,0xc4,0x8c,0x9a,0x05,0x09,0x73,0x1a,0x54,0xbd,0x9d,0x72,0x90,0xb2,0x79,0x63,0xe4,0x37,0x2d,0xc9,0xb1,0x99,0xcf,0xdc,0xac,0x0b,0x01,0xac,0xd2,0x8a,0x62,0x39,0x51,0x12,0xe4,0xc4,0x36,0x48,0xd6,0x22,0xc4,0x8c,0x82,0x34,0xd0,0x14,0x40,0xe8,0xcc,0x37,0x6c,0x92,0x7f,0x23,0xa5,0xaf,0xc9,0xac,0x04,0x74,0xc6,0x62,0x27,0x4e,0x42,0x45,0x25,0xc8,0x55,0x2e,0xce,0x3b,0x3f,0xe2,0x65,0x16,0xde,0x90,0x1b,0xc7,0xd5,0x15,0xbd,0xe8,0x95,0x58,0xe6,0x26,0xc9,0x5c,0x80,0xb9,0x33,0x42,0xf8,0x01,0x00,0x04,0xf3,0x9e,0x6c,0x6c,0x94,0x87,0x1c,0x5e,0x34,0x4c,0xab,0x39,0x66,0xc8,0x35,0xf9,0xa9,0x6a,0x59,0xaf,0xd3,0x1c,0x40,0x28,0x6b,0x38,0xb1,0xc1,0xa7,0x84,0x70,0xba,0xb9,0x47,0x51,0x89,0x34,0x45,0x3c,0xe8,0x67,0x36,0xa9,0x19,0xf1,0xf5,0xa6,0xd5,0x10,0xa8,0x6f,0x54,0x54,0xfc,0x39,0x80,0xcb,0x5c,0x76,0x5b,0xd2,0xbd,0x5f,0x7b,0x36,0xb1,0x41,0x0d,0x66,0x35,0xc8,0xce,0xb4,0x7c,0x4d,0xda,0x0d,0x76,0xa2,0x8e,0xac,0x93,0x9c,0x71,0xc3,0x02,0x48,0x04,0x86,0x6c,0x71,0x62,0x66,0x58,0x44,0x21,0x63,0xc2,0xc2,0x21,0x17,0xe5,0x0a,0xce,0xfc,0xe6,0x37,0x8a,0x98,0x56,0x52,0x30,0x2a,0x4e,0xf0,0xc2,0xce,0x0c,0xc7,0x16,0xb7,0x79,0x6e,0x2b,0x6b,0x2e,0x37,0x77,0xdf,0xa1,0xac,0x3d,0xa2,0x59,0xa3,0x1b,0x5a,0x9b,0x53,0x0f,0x8c,0xb6,0x38,0xa8,0x1a,0x62,0xac,0x30,0x18,0x49,0xab,0xaf,0x95,0xa7,0x30,0x1b,0xda,0x30,0x06,0x89,0x09,0xbf,0xdb,0x7e,0x67,0xdb,0xcc,0xbb,0x38,0xa5,0x55,0x1a,0x25,0xb1,0xa3,0xa0,0xf6,0x85,0x74,0x8a,0xd5,0x75,0x3d,0x88,0x80,0xf0,0x01,0x6c,0x62,0x74,0x86,0x16,0x63,0x84,0xc5,0x57,0x1f,0xe2,0x36,0x59,0x00,0x36,0x4d,0x03,0x83,0x11,0xe2,0xd8,0x75,0xdb,0x36,0x66,0x86,0x93,0x2b,0x5e,0xc6,0x02,0x43,0x0a,0x36,0x9e,0x87,0xa6,0xef,0x5c,0x33,0x87,0x86,0x65,0x78,0x25,0xbd,0x4c,0x05,0x7a,0xce,0xb9,0x23,0xeb,0x09,0x35,0xe6,0x90,0x5e,0x63,0xb4,0xce,0xd7,0xf8,0x08,0x57,0xa7,0x73,0xdd,0x64,0xb1,0x50,0xd2,0x66,0x12,0xea,0x9a,0xc1,0x20,0x52,0xdb,0x20,0x17,0xbf,0x18,0x43,0xcc,0xb4,0xb3,0x28,0x1b,0x69,0x0d,0xc7,0x28,0xad,0xfa,0x85,0xc0,0x02,0x81,0xb8,0xe3,0xc0,0x92,0x87,0x33,0x5f,0x85,0x6b,0x4f,0xc2,0x89,0x2f,0x69,0xa2,0xf5,0x79,0x21,0xad,0xa0,0x19,0x14,0xc4,0x09,0x88,0x66,0x2d,0x57,0x76,0x96,0x62,0xa7,0x86,0x35,0x1b,0x9b,0x66,0x49,0x3d,0xab,0x79,0x59,0x4d,0x98,0x6d,0xe2,0x10,0x0d,0x65,0xba,0x0f,0xf4,0xea,0x58,0xb8,0x15,0x38,0xd2,0x4a,0x44,0x35,0xa2,0x58,0xfa,0xc2,0x54,0x04,0xaa,0x7f,0x41,0xf6,0x58,0xb1,0x38,0x50,0x65,0xe1,0x58,0xdc,0xb6,0x01,0x15,0x73,0x27,0x20,0xf4,0x04,0x59,0xaa,0xac,0x15,0xe4,0x06,0x95,0x3a,0x90,0xac,0x52,0x99,0x7d,0x1c,0xcd,0x07,0x00,0x60,0xef,0xc6,0x5d,0xb9,0xe6,0x53,0x35,0x44,0x67,0xfa,0xd5,0x6e,0xc7,0x13,0xc8,0x6e,0x75,0x40,0xc4,0x23,0xac,0xf2,0x66,0x9f,0x52,0xfa,0x6f,0x4a,0xc6,0x88,0x8d,0x87,0x1e,0xf3,0xe8,0x47,0xc0,0x29,0xa8,0xaa,0xfb,0xb9,0x2e,0x17,0xb2,0x4a,0xa0,0x79,0xb1,0xf4,0x19,0xba,0x61,0x75,0xb4,0x42,0xaf,0xb1,0x19,0x09,0xd4,0xa5,0x6b,0x70,0xa0,0x33,0x5b,0x28,0x73,0x92,0x18,0xaa,0x7c,0x93,0x48,0xe2,0xc3,0xc2,0xf3,0xeb,0x3d,0x15,0xa4,0x1e,0x64,0x17,0xc0,0xdd,0x94,0xbf,0xeb,0x21,0x41,0x9b,0x31,0x1a,0x7b,0xb1,0x3a,0x18,0x0b,0xbe,0x83,0x32,0x18,0xa9,0xa6,0xb1,0x74,0x47,0xcc,0x85,0xf2,0x25,0x85,0x95,0x87,0xa7,0x30,0x77,0x04,0x9a,0xcb,0xcf,0xd4,0x4d,0x0f,0x02,0x54,0x38,0xe1,0x5d,0x15,0x38,0x27,0x0d,0x58,0x6e,0x1b,0xf8,0x31,0x92,0xa9,0x45,0x9c,0xf6,0x3c,0x0e,0x97,0x2f,0x85,0x29,0x76,0x79,0x83,0x1e,0xcf,0x12,0x15,0x09,0x85,0x1c,0xb8,0x34,0x0f,0x6f,0x10,0x7b,0x0f,0xa1,0xa0,0xef,0xd1,0xb3,0x6a,0x81,0x89,0xbc,0x08,0x5c,0x4f,0x5c,0xb7,0x84,0xe5,0x53,0xf4,0x1b,0x91,0x8f,0x80,0x39,0x7c,0xe1,0x95,0x6f,0x78,0x5b,0xee,0x37,0x7c,0xa9,0xaa,0x8b,0xe6,0x99,0x8a,0xda,0x30,0xc2,0x6b,0x7c,0x3d,0x8c,0x6b,0x55,0x25,0x4c,0xc9,0x62,0x03,0xb2,0x0c,0x42,0xae,0xe0,0xac,0x4e,0x1e,0xbb,0x40,0x8e,0x49,0xa9,0xe3,0xf8,0x79,0xd0,0xab,0x07,0x85,0xeb,0x70,0x25,0x42,0x5d,0x13,0x05,0xa2,0x29,0x9c,0x01,0x5e,0x12,0x0d,0x16,0x3b,0x0e,0x19,0x49,0x4c,0xe5,0x72,0x53,0xd0,0x24,0x6d,0x18,0x27,0x45,0xcb,0x81,0x97,0xab,0x74,0x38,0xb3,0xc1,0xbb,0x79,0x72,0xbe,0xc5,0xa3,0x06,0xeb,0xa3,0x56,0x78,0x55,0xc0,0x14,0x69,0x9f,0xef,0x65,0xae,0x54,0xc7,0x70,0xa0,0xd8,0x5c,0x18,0x40,0x0c,0xf6,0x42,0xae,0xdc,0x66,0x07,0x77,0xba,0x4b,0x13,0x85,0x02,0xbd,0x5a,0x78,0x12,0xf6,0x21,0xf8,0x4a,0x48,0x29,0x6b,0x98,0xdd,0x43,0x22,0xb6,0xf1,0x58,0x28,0xb8,0xa8,0xf0,0xe0,0x0a,0x8b,0xa4,0x4a,0x53,0xc3,0xa8,0xb1,0x43,0x57,0x1b,0x07,0x40,0xab,0xd5,0x67,0xda,0xf1,0xcd,0xe9,0xc7,0x9c,0x20,0x4b,0x6d,0x5e,0x25,0x9d,0x17,0x66,0xa3,0x1b,0xbb,0xcb,0x4e,0x6a,0x05,0xcf,0x45,0x02,0x17,0x6b,0x30,0x1c,0x1c,0x2f,0x41,0x24,0x77,0x50,0x15,0x7b,0xce,0xc8,0x5e,0x80,0x9b,0x30,0xa4,0xd6,0x0d,0x77,0x47,0xcd,0xd0,0xf5,0xb9,0x9a,0xa8,0xc8,0x26,0x98,0x75,0x17,0x79,0x3a,0xaa,0x80,0x80,0xa0,0xb1,0x24,0xa8,0x55,0x8d,0xf7,0x2b,0xbe,0x37,0xb7,0x5f,0x4e,0xdb,0xb6,0xbe,0x82,0x16,0xd6,0xc6,0x33,0xfb,0x2b,0x22,0x80,0xe2,0x51,0x13,0xd8,0x69,0x5e,0x43,0x48,0x1c,0x3e,0xeb,0x39,0x7e,0xb1,0x92,0x50,0x52,0x29,0xb6,0x7a,0x20,0x1e,0xa8,0x93,0xc3,0xe2,0xcb,0x32,0xda,0x8b,0xc3,0x42,0xfa,0x4d,0xea,0x05,0x78]; + let pk_bytes: [u8; MLKEM768_PK_LEN] = [ + 0x29, 0x8A, 0xA1, 0x0D, 0x42, 0x3C, 0x8D, 0xDA, 0x06, 0x9D, 0x02, 0xBC, 0x59, 0xE6, 0xCD, + 0xF0, 0x3A, 0x09, 0x6B, 0x8B, 0x3D, 0xA4, 0xCA, 0xB9, 0xB8, 0x0C, 0xA4, 0xA1, 0x49, 0x07, + 0x67, 0x2C, 0xCE, 0xF1, 0xEC, 0x4F, 0xAF, 0x23, 0x4A, 0x0B, 0xC5, 0xB7, 0xE9, 0xD4, 0x73, + 0xF2, 0xB3, 0x13, 0x3B, 0x3B, 0x26, 0xA1, 0xD1, 0x75, 0xCB, 0x67, 0xA7, 0x80, 0x59, 0x19, + 0x69, 0x9C, 0x02, 0xF7, 0x65, 0x31, 0xB9, 0x9C, 0x5F, 0x89, 0x18, 0x07, 0x04, 0xBB, 0x4C, + 0xA4, 0x53, 0x5C, 0x5B, 0x89, 0x72, 0x67, 0x9C, 0x66, 0x0A, 0x07, 0xC5, 0xE5, 0x14, 0xB8, + 0x70, 0x09, 0xC8, 0x62, 0xEB, 0x8F, 0x51, 0x57, 0x69, 0x5E, 0xFB, 0x3F, 0xC4, 0x0A, 0x9D, + 0xEF, 0x6B, 0x81, 0xC1, 0xCC, 0x02, 0xA2, 0x49, 0xAE, 0x4F, 0x09, 0x4A, 0xD0, 0xD9, 0xBD, + 0x34, 0x85, 0xC1, 0xC1, 0xC6, 0x80, 0x80, 0x52, 0x0A, 0x7C, 0x8C, 0x63, 0x20, 0x32, 0xCE, + 0xE7, 0x38, 0x15, 0x4E, 0x5C, 0x51, 0x76, 0xC0, 0x7D, 0xA5, 0x60, 0x24, 0x77, 0x6A, 0x43, + 0x0F, 0xE7, 0x6E, 0xAC, 0xF6, 0x65, 0xA3, 0xF7, 0xB8, 0x32, 0x10, 0x22, 0x15, 0xBC, 0x82, + 0xF1, 0x09, 0x39, 0xC8, 0x35, 0x57, 0x04, 0x33, 0x6A, 0x8F, 0xAC, 0x1D, 0x81, 0xE4, 0xBB, + 0x04, 0x85, 0xAA, 0x5D, 0x7C, 0x74, 0xD6, 0xB5, 0x9B, 0xBE, 0x5C, 0x5E, 0x97, 0x2A, 0x0D, + 0x8B, 0xAC, 0x41, 0x1B, 0x55, 0xB5, 0xD5, 0x55, 0x7C, 0xD6, 0x80, 0xA1, 0xA8, 0xF7, 0x1B, + 0x4E, 0xB8, 0x6B, 0xC4, 0x8C, 0x9A, 0x05, 0x09, 0x73, 0x1A, 0x54, 0xBD, 0x9D, 0x72, 0x90, + 0xB2, 0x79, 0x63, 0xE4, 0x37, 0x2D, 0xC9, 0xB1, 0x99, 0xCF, 0xDC, 0xAC, 0x0B, 0x01, 0xAC, + 0xD2, 0x8A, 0x62, 0x39, 0x51, 0x12, 0xE4, 0xC4, 0x36, 0x48, 0xD6, 0x22, 0xC4, 0x8C, 0x82, + 0x34, 0xD0, 0x14, 0x40, 0xE8, 0xCC, 0x37, 0x6C, 0x92, 0x7F, 0x23, 0xA5, 0xAF, 0xC9, 0xAC, + 0x04, 0x74, 0xC6, 0x62, 0x27, 0x4E, 0x42, 0x45, 0x25, 0xC8, 0x55, 0x2E, 0xCE, 0x3B, 0x3F, + 0xE2, 0x65, 0x16, 0xDE, 0x90, 0x1B, 0xC7, 0xD5, 0x15, 0xBD, 0xE8, 0x95, 0x58, 0xE6, 0x26, + 0xC9, 0x5C, 0x80, 0xB9, 0x33, 0x42, 0xF8, 0x01, 0x00, 0x04, 0xF3, 0x9E, 0x6C, 0x6C, 0x94, + 0x87, 0x1C, 0x5E, 0x34, 0x4C, 0xAB, 0x39, 0x66, 0xC8, 0x35, 0xF9, 0xA9, 0x6A, 0x59, 0xAF, + 0xD3, 0x1C, 0x40, 0x28, 0x6B, 0x38, 0xB1, 0xC1, 0xA7, 0x84, 0x70, 0xBA, 0xB9, 0x47, 0x51, + 0x89, 0x34, 0x45, 0x3C, 0xE8, 0x67, 0x36, 0xA9, 0x19, 0xF1, 0xF5, 0xA6, 0xD5, 0x10, 0xA8, + 0x6F, 0x54, 0x54, 0xFC, 0x39, 0x80, 0xCB, 0x5C, 0x76, 0x5B, 0xD2, 0xBD, 0x5F, 0x7B, 0x36, + 0xB1, 0x41, 0x0D, 0x66, 0x35, 0xC8, 0xCE, 0xB4, 0x7C, 0x4D, 0xDA, 0x0D, 0x76, 0xA2, 0x8E, + 0xAC, 0x93, 0x9C, 0x71, 0xC3, 0x02, 0x48, 0x04, 0x86, 0x6C, 0x71, 0x62, 0x66, 0x58, 0x44, + 0x21, 0x63, 0xC2, 0xC2, 0x21, 0x17, 0xE5, 0x0A, 0xCE, 0xFC, 0xE6, 0x37, 0x8A, 0x98, 0x56, + 0x52, 0x30, 0x2A, 0x4E, 0xF0, 0xC2, 0xCE, 0x0C, 0xC7, 0x16, 0xB7, 0x79, 0x6E, 0x2B, 0x6B, + 0x2E, 0x37, 0x77, 0xDF, 0xA1, 0xAC, 0x3D, 0xA2, 0x59, 0xA3, 0x1B, 0x5A, 0x9B, 0x53, 0x0F, + 0x8C, 0xB6, 0x38, 0xA8, 0x1A, 0x62, 0xAC, 0x30, 0x18, 0x49, 0xAB, 0xAF, 0x95, 0xA7, 0x30, + 0x1B, 0xDA, 0x30, 0x06, 0x89, 0x09, 0xBF, 0xDB, 0x7E, 0x67, 0xDB, 0xCC, 0xBB, 0x38, 0xA5, + 0x55, 0x1A, 0x25, 0xB1, 0xA3, 0xA0, 0xF6, 0x85, 0x74, 0x8A, 0xD5, 0x75, 0x3D, 0x88, 0x80, + 0xF0, 0x01, 0x6C, 0x62, 0x74, 0x86, 0x16, 0x63, 0x84, 0xC5, 0x57, 0x1F, 0xE2, 0x36, 0x59, + 0x00, 0x36, 0x4D, 0x03, 0x83, 0x11, 0xE2, 0xD8, 0x75, 0xDB, 0x36, 0x66, 0x86, 0x93, 0x2B, + 0x5E, 0xC6, 0x02, 0x43, 0x0A, 0x36, 0x9E, 0x87, 0xA6, 0xEF, 0x5C, 0x33, 0x87, 0x86, 0x65, + 0x78, 0x25, 0xBD, 0x4C, 0x05, 0x7A, 0xCE, 0xB9, 0x23, 0xEB, 0x09, 0x35, 0xE6, 0x90, 0x5E, + 0x63, 0xB4, 0xCE, 0xD7, 0xF8, 0x08, 0x57, 0xA7, 0x73, 0xDD, 0x64, 0xB1, 0x50, 0xD2, 0x66, + 0x12, 0xEA, 0x9A, 0xC1, 0x20, 0x52, 0xDB, 0x20, 0x17, 0xBF, 0x18, 0x43, 0xCC, 0xB4, 0xB3, + 0x28, 0x1B, 0x69, 0x0D, 0xC7, 0x28, 0xAD, 0xFA, 0x85, 0xC0, 0x02, 0x81, 0xB8, 0xE3, 0xC0, + 0x92, 0x87, 0x33, 0x5F, 0x85, 0x6B, 0x4F, 0xC2, 0x89, 0x2F, 0x69, 0xA2, 0xF5, 0x79, 0x21, + 0xAD, 0xA0, 0x19, 0x14, 0xC4, 0x09, 0x88, 0x66, 0x2D, 0x57, 0x76, 0x96, 0x62, 0xA7, 0x86, + 0x35, 0x1B, 0x9B, 0x66, 0x49, 0x3D, 0xAB, 0x79, 0x59, 0x4D, 0x98, 0x6D, 0xE2, 0x10, 0x0D, + 0x65, 0xBA, 0x0F, 0xF4, 0xEA, 0x58, 0xB8, 0x15, 0x38, 0xD2, 0x4A, 0x44, 0x35, 0xA2, 0x58, + 0xFA, 0xC2, 0x54, 0x04, 0xAA, 0x7F, 0x41, 0xF6, 0x58, 0xB1, 0x38, 0x50, 0x65, 0xE1, 0x58, + 0xDC, 0xB6, 0x01, 0x15, 0x73, 0x27, 0x20, 0xF4, 0x04, 0x59, 0xAA, 0xAC, 0x15, 0xE4, 0x06, + 0x95, 0x3A, 0x90, 0xAC, 0x52, 0x99, 0x7D, 0x1C, 0xCD, 0x07, 0x00, 0x60, 0xEF, 0xC6, 0x5D, + 0xB9, 0xE6, 0x53, 0x35, 0x44, 0x67, 0xFA, 0xD5, 0x6E, 0xC7, 0x13, 0xC8, 0x6E, 0x75, 0x40, + 0xC4, 0x23, 0xAC, 0xF2, 0x66, 0x9F, 0x52, 0xFA, 0x6F, 0x4A, 0xC6, 0x88, 0x8D, 0x87, 0x1E, + 0xF3, 0xE8, 0x47, 0xC0, 0x29, 0xA8, 0xAA, 0xFB, 0xB9, 0x2E, 0x17, 0xB2, 0x4A, 0xA0, 0x79, + 0xB1, 0xF4, 0x19, 0xBA, 0x61, 0x75, 0xB4, 0x42, 0xAF, 0xB1, 0x19, 0x09, 0xD4, 0xA5, 0x6B, + 0x70, 0xA0, 0x33, 0x5B, 0x28, 0x73, 0x92, 0x18, 0xAA, 0x7C, 0x93, 0x48, 0xE2, 0xC3, 0xC2, + 0xF3, 0xEB, 0x3D, 0x15, 0xA4, 0x1E, 0x64, 0x17, 0xC0, 0xDD, 0x94, 0xBF, 0xEB, 0x21, 0x41, + 0x9B, 0x31, 0x1A, 0x7B, 0xB1, 0x3A, 0x18, 0x0B, 0xBE, 0x83, 0x32, 0x18, 0xA9, 0xA6, 0xB1, + 0x74, 0x47, 0xCC, 0x85, 0xF2, 0x25, 0x85, 0x95, 0x87, 0xA7, 0x30, 0x77, 0x04, 0x9A, 0xCB, + 0xCF, 0xD4, 0x4D, 0x0F, 0x02, 0x54, 0x38, 0xE1, 0x5D, 0x15, 0x38, 0x27, 0x0D, 0x58, 0x6E, + 0x1B, 0xF8, 0x31, 0x92, 0xA9, 0x45, 0x9C, 0xF6, 0x3C, 0x0E, 0x97, 0x2F, 0x85, 0x29, 0x76, + 0x79, 0x83, 0x1E, 0xCF, 0x12, 0x15, 0x09, 0x85, 0x1C, 0xB8, 0x34, 0x0F, 0x6F, 0x10, 0x7B, + 0x0F, 0xA1, 0xA0, 0xEF, 0xD1, 0xB3, 0x6A, 0x81, 0x89, 0xBC, 0x08, 0x5C, 0x4F, 0x5C, 0xB7, + 0x84, 0xE5, 0x53, 0xF4, 0x1B, 0x91, 0x8F, 0x80, 0x39, 0x7C, 0xE1, 0x95, 0x6F, 0x78, 0x5B, + 0xEE, 0x37, 0x7C, 0xA9, 0xAA, 0x8B, 0xE6, 0x99, 0x8A, 0xDA, 0x30, 0xC2, 0x6B, 0x7C, 0x3D, + 0x8C, 0x6B, 0x55, 0x25, 0x4C, 0xC9, 0x62, 0x03, 0xB2, 0x0C, 0x42, 0xAE, 0xE0, 0xAC, 0x4E, + 0x1E, 0xBB, 0x40, 0x8E, 0x49, 0xA9, 0xE3, 0xF8, 0x79, 0xD0, 0xAB, 0x07, 0x85, 0xEB, 0x70, + 0x25, 0x42, 0x5D, 0x13, 0x05, 0xA2, 0x29, 0x9C, 0x01, 0x5E, 0x12, 0x0D, 0x16, 0x3B, 0x0E, + 0x19, 0x49, 0x4C, 0xE5, 0x72, 0x53, 0xD0, 0x24, 0x6D, 0x18, 0x27, 0x45, 0xCB, 0x81, 0x97, + 0xAB, 0x74, 0x38, 0xB3, 0xC1, 0xBB, 0x79, 0x72, 0xBE, 0xC5, 0xA3, 0x06, 0xEB, 0xA3, 0x56, + 0x78, 0x55, 0xC0, 0x14, 0x69, 0x9F, 0xEF, 0x65, 0xAE, 0x54, 0xC7, 0x70, 0xA0, 0xD8, 0x5C, + 0x18, 0x40, 0x0C, 0xF6, 0x42, 0xAE, 0xDC, 0x66, 0x07, 0x77, 0xBA, 0x4B, 0x13, 0x85, 0x02, + 0xBD, 0x5A, 0x78, 0x12, 0xF6, 0x21, 0xF8, 0x4A, 0x48, 0x29, 0x6B, 0x98, 0xDD, 0x43, 0x22, + 0xB6, 0xF1, 0x58, 0x28, 0xB8, 0xA8, 0xF0, 0xE0, 0x0A, 0x8B, 0xA4, 0x4A, 0x53, 0xC3, 0xA8, + 0xB1, 0x43, 0x57, 0x1B, 0x07, 0x40, 0xAB, 0xD5, 0x67, 0xDA, 0xF1, 0xCD, 0xE9, 0xC7, 0x9C, + 0x20, 0x4B, 0x6D, 0x5E, 0x25, 0x9D, 0x17, 0x66, 0xA3, 0x1B, 0xBB, 0xCB, 0x4E, 0x6A, 0x05, + 0xCF, 0x45, 0x02, 0x17, 0x6B, 0x30, 0x1C, 0x1C, 0x2F, 0x41, 0x24, 0x77, 0x50, 0x15, 0x7B, + 0xCE, 0xC8, 0x5E, 0x80, 0x9B, 0x30, 0xA4, 0xD6, 0x0D, 0x77, 0x47, 0xCD, 0xD0, 0xF5, 0xB9, + 0x9A, 0xA8, 0xC8, 0x26, 0x98, 0x75, 0x17, 0x79, 0x3A, 0xAA, 0x80, 0x80, 0xA0, 0xB1, 0x24, + 0xA8, 0x55, 0x8D, 0xF7, 0x2B, 0xBE, 0x37, 0xB7, 0x5F, 0x4E, 0xDB, 0xB6, 0xBE, 0x82, 0x16, + 0xD6, 0xC6, 0x33, 0xFB, 0x2B, 0x22, 0x80, 0xE2, 0x51, 0x13, 0xD8, 0x69, 0x5E, 0x43, 0x48, + 0x1C, 0x3E, 0xEB, 0x39, 0x7E, 0xB1, 0x92, 0x50, 0x52, 0x29, 0xB6, 0x7A, 0x20, 0x1E, 0xA8, + 0x93, 0xC3, 0xE2, 0xCB, 0x32, 0xDA, 0x8B, 0xC3, 0x42, 0xFA, 0x4D, 0xEA, 0x05, 0x78, + ]; let pk = MLKEM768PublicKey::from_bytes(&pk_bytes).unwrap(); let (ss, ct) = MLKEM768::encaps(&pk).unwrap(); print!("{:x?}", ss); @@ -231,7 +497,7 @@ fn bench_mlkem768_encaps() { } fn bench_mlkem768_lowmemory_encaps() { - use bouncycastle::mlkem_lowmemory::{MLKEMTrait, MLKEM768, MLKEM768PublicKey}; + use bouncycastle::mlkem_lowmemory::{MLKEM768, MLKEM768PublicKey, MLKEMTrait}; eprintln!("MLKEM768_lowmemory/Encaps"); @@ -245,7 +511,87 @@ fn bench_mlkem768_lowmemory_encaps() { // use bouncycastle_hex as hex; // eprintln!("pk:\n{}", &hex::encode(pk.encode())); - let pk_bytes: [u8; MLKEM768_PK_LEN] = [0x29,0x8a,0xa1,0x0d,0x42,0x3c,0x8d,0xda,0x06,0x9d,0x02,0xbc,0x59,0xe6,0xcd,0xf0,0x3a,0x09,0x6b,0x8b,0x3d,0xa4,0xca,0xb9,0xb8,0x0c,0xa4,0xa1,0x49,0x07,0x67,0x2c,0xce,0xf1,0xec,0x4f,0xaf,0x23,0x4a,0x0b,0xc5,0xb7,0xe9,0xd4,0x73,0xf2,0xb3,0x13,0x3b,0x3b,0x26,0xa1,0xd1,0x75,0xcb,0x67,0xa7,0x80,0x59,0x19,0x69,0x9c,0x02,0xf7,0x65,0x31,0xb9,0x9c,0x5f,0x89,0x18,0x07,0x04,0xbb,0x4c,0xa4,0x53,0x5c,0x5b,0x89,0x72,0x67,0x9c,0x66,0x0a,0x07,0xc5,0xe5,0x14,0xb8,0x70,0x09,0xc8,0x62,0xeb,0x8f,0x51,0x57,0x69,0x5e,0xfb,0x3f,0xc4,0x0a,0x9d,0xef,0x6b,0x81,0xc1,0xcc,0x02,0xa2,0x49,0xae,0x4f,0x09,0x4a,0xd0,0xd9,0xbd,0x34,0x85,0xc1,0xc1,0xc6,0x80,0x80,0x52,0x0a,0x7c,0x8c,0x63,0x20,0x32,0xce,0xe7,0x38,0x15,0x4e,0x5c,0x51,0x76,0xc0,0x7d,0xa5,0x60,0x24,0x77,0x6a,0x43,0x0f,0xe7,0x6e,0xac,0xf6,0x65,0xa3,0xf7,0xb8,0x32,0x10,0x22,0x15,0xbc,0x82,0xf1,0x09,0x39,0xc8,0x35,0x57,0x04,0x33,0x6a,0x8f,0xac,0x1d,0x81,0xe4,0xbb,0x04,0x85,0xaa,0x5d,0x7c,0x74,0xd6,0xb5,0x9b,0xbe,0x5c,0x5e,0x97,0x2a,0x0d,0x8b,0xac,0x41,0x1b,0x55,0xb5,0xd5,0x55,0x7c,0xd6,0x80,0xa1,0xa8,0xf7,0x1b,0x4e,0xb8,0x6b,0xc4,0x8c,0x9a,0x05,0x09,0x73,0x1a,0x54,0xbd,0x9d,0x72,0x90,0xb2,0x79,0x63,0xe4,0x37,0x2d,0xc9,0xb1,0x99,0xcf,0xdc,0xac,0x0b,0x01,0xac,0xd2,0x8a,0x62,0x39,0x51,0x12,0xe4,0xc4,0x36,0x48,0xd6,0x22,0xc4,0x8c,0x82,0x34,0xd0,0x14,0x40,0xe8,0xcc,0x37,0x6c,0x92,0x7f,0x23,0xa5,0xaf,0xc9,0xac,0x04,0x74,0xc6,0x62,0x27,0x4e,0x42,0x45,0x25,0xc8,0x55,0x2e,0xce,0x3b,0x3f,0xe2,0x65,0x16,0xde,0x90,0x1b,0xc7,0xd5,0x15,0xbd,0xe8,0x95,0x58,0xe6,0x26,0xc9,0x5c,0x80,0xb9,0x33,0x42,0xf8,0x01,0x00,0x04,0xf3,0x9e,0x6c,0x6c,0x94,0x87,0x1c,0x5e,0x34,0x4c,0xab,0x39,0x66,0xc8,0x35,0xf9,0xa9,0x6a,0x59,0xaf,0xd3,0x1c,0x40,0x28,0x6b,0x38,0xb1,0xc1,0xa7,0x84,0x70,0xba,0xb9,0x47,0x51,0x89,0x34,0x45,0x3c,0xe8,0x67,0x36,0xa9,0x19,0xf1,0xf5,0xa6,0xd5,0x10,0xa8,0x6f,0x54,0x54,0xfc,0x39,0x80,0xcb,0x5c,0x76,0x5b,0xd2,0xbd,0x5f,0x7b,0x36,0xb1,0x41,0x0d,0x66,0x35,0xc8,0xce,0xb4,0x7c,0x4d,0xda,0x0d,0x76,0xa2,0x8e,0xac,0x93,0x9c,0x71,0xc3,0x02,0x48,0x04,0x86,0x6c,0x71,0x62,0x66,0x58,0x44,0x21,0x63,0xc2,0xc2,0x21,0x17,0xe5,0x0a,0xce,0xfc,0xe6,0x37,0x8a,0x98,0x56,0x52,0x30,0x2a,0x4e,0xf0,0xc2,0xce,0x0c,0xc7,0x16,0xb7,0x79,0x6e,0x2b,0x6b,0x2e,0x37,0x77,0xdf,0xa1,0xac,0x3d,0xa2,0x59,0xa3,0x1b,0x5a,0x9b,0x53,0x0f,0x8c,0xb6,0x38,0xa8,0x1a,0x62,0xac,0x30,0x18,0x49,0xab,0xaf,0x95,0xa7,0x30,0x1b,0xda,0x30,0x06,0x89,0x09,0xbf,0xdb,0x7e,0x67,0xdb,0xcc,0xbb,0x38,0xa5,0x55,0x1a,0x25,0xb1,0xa3,0xa0,0xf6,0x85,0x74,0x8a,0xd5,0x75,0x3d,0x88,0x80,0xf0,0x01,0x6c,0x62,0x74,0x86,0x16,0x63,0x84,0xc5,0x57,0x1f,0xe2,0x36,0x59,0x00,0x36,0x4d,0x03,0x83,0x11,0xe2,0xd8,0x75,0xdb,0x36,0x66,0x86,0x93,0x2b,0x5e,0xc6,0x02,0x43,0x0a,0x36,0x9e,0x87,0xa6,0xef,0x5c,0x33,0x87,0x86,0x65,0x78,0x25,0xbd,0x4c,0x05,0x7a,0xce,0xb9,0x23,0xeb,0x09,0x35,0xe6,0x90,0x5e,0x63,0xb4,0xce,0xd7,0xf8,0x08,0x57,0xa7,0x73,0xdd,0x64,0xb1,0x50,0xd2,0x66,0x12,0xea,0x9a,0xc1,0x20,0x52,0xdb,0x20,0x17,0xbf,0x18,0x43,0xcc,0xb4,0xb3,0x28,0x1b,0x69,0x0d,0xc7,0x28,0xad,0xfa,0x85,0xc0,0x02,0x81,0xb8,0xe3,0xc0,0x92,0x87,0x33,0x5f,0x85,0x6b,0x4f,0xc2,0x89,0x2f,0x69,0xa2,0xf5,0x79,0x21,0xad,0xa0,0x19,0x14,0xc4,0x09,0x88,0x66,0x2d,0x57,0x76,0x96,0x62,0xa7,0x86,0x35,0x1b,0x9b,0x66,0x49,0x3d,0xab,0x79,0x59,0x4d,0x98,0x6d,0xe2,0x10,0x0d,0x65,0xba,0x0f,0xf4,0xea,0x58,0xb8,0x15,0x38,0xd2,0x4a,0x44,0x35,0xa2,0x58,0xfa,0xc2,0x54,0x04,0xaa,0x7f,0x41,0xf6,0x58,0xb1,0x38,0x50,0x65,0xe1,0x58,0xdc,0xb6,0x01,0x15,0x73,0x27,0x20,0xf4,0x04,0x59,0xaa,0xac,0x15,0xe4,0x06,0x95,0x3a,0x90,0xac,0x52,0x99,0x7d,0x1c,0xcd,0x07,0x00,0x60,0xef,0xc6,0x5d,0xb9,0xe6,0x53,0x35,0x44,0x67,0xfa,0xd5,0x6e,0xc7,0x13,0xc8,0x6e,0x75,0x40,0xc4,0x23,0xac,0xf2,0x66,0x9f,0x52,0xfa,0x6f,0x4a,0xc6,0x88,0x8d,0x87,0x1e,0xf3,0xe8,0x47,0xc0,0x29,0xa8,0xaa,0xfb,0xb9,0x2e,0x17,0xb2,0x4a,0xa0,0x79,0xb1,0xf4,0x19,0xba,0x61,0x75,0xb4,0x42,0xaf,0xb1,0x19,0x09,0xd4,0xa5,0x6b,0x70,0xa0,0x33,0x5b,0x28,0x73,0x92,0x18,0xaa,0x7c,0x93,0x48,0xe2,0xc3,0xc2,0xf3,0xeb,0x3d,0x15,0xa4,0x1e,0x64,0x17,0xc0,0xdd,0x94,0xbf,0xeb,0x21,0x41,0x9b,0x31,0x1a,0x7b,0xb1,0x3a,0x18,0x0b,0xbe,0x83,0x32,0x18,0xa9,0xa6,0xb1,0x74,0x47,0xcc,0x85,0xf2,0x25,0x85,0x95,0x87,0xa7,0x30,0x77,0x04,0x9a,0xcb,0xcf,0xd4,0x4d,0x0f,0x02,0x54,0x38,0xe1,0x5d,0x15,0x38,0x27,0x0d,0x58,0x6e,0x1b,0xf8,0x31,0x92,0xa9,0x45,0x9c,0xf6,0x3c,0x0e,0x97,0x2f,0x85,0x29,0x76,0x79,0x83,0x1e,0xcf,0x12,0x15,0x09,0x85,0x1c,0xb8,0x34,0x0f,0x6f,0x10,0x7b,0x0f,0xa1,0xa0,0xef,0xd1,0xb3,0x6a,0x81,0x89,0xbc,0x08,0x5c,0x4f,0x5c,0xb7,0x84,0xe5,0x53,0xf4,0x1b,0x91,0x8f,0x80,0x39,0x7c,0xe1,0x95,0x6f,0x78,0x5b,0xee,0x37,0x7c,0xa9,0xaa,0x8b,0xe6,0x99,0x8a,0xda,0x30,0xc2,0x6b,0x7c,0x3d,0x8c,0x6b,0x55,0x25,0x4c,0xc9,0x62,0x03,0xb2,0x0c,0x42,0xae,0xe0,0xac,0x4e,0x1e,0xbb,0x40,0x8e,0x49,0xa9,0xe3,0xf8,0x79,0xd0,0xab,0x07,0x85,0xeb,0x70,0x25,0x42,0x5d,0x13,0x05,0xa2,0x29,0x9c,0x01,0x5e,0x12,0x0d,0x16,0x3b,0x0e,0x19,0x49,0x4c,0xe5,0x72,0x53,0xd0,0x24,0x6d,0x18,0x27,0x45,0xcb,0x81,0x97,0xab,0x74,0x38,0xb3,0xc1,0xbb,0x79,0x72,0xbe,0xc5,0xa3,0x06,0xeb,0xa3,0x56,0x78,0x55,0xc0,0x14,0x69,0x9f,0xef,0x65,0xae,0x54,0xc7,0x70,0xa0,0xd8,0x5c,0x18,0x40,0x0c,0xf6,0x42,0xae,0xdc,0x66,0x07,0x77,0xba,0x4b,0x13,0x85,0x02,0xbd,0x5a,0x78,0x12,0xf6,0x21,0xf8,0x4a,0x48,0x29,0x6b,0x98,0xdd,0x43,0x22,0xb6,0xf1,0x58,0x28,0xb8,0xa8,0xf0,0xe0,0x0a,0x8b,0xa4,0x4a,0x53,0xc3,0xa8,0xb1,0x43,0x57,0x1b,0x07,0x40,0xab,0xd5,0x67,0xda,0xf1,0xcd,0xe9,0xc7,0x9c,0x20,0x4b,0x6d,0x5e,0x25,0x9d,0x17,0x66,0xa3,0x1b,0xbb,0xcb,0x4e,0x6a,0x05,0xcf,0x45,0x02,0x17,0x6b,0x30,0x1c,0x1c,0x2f,0x41,0x24,0x77,0x50,0x15,0x7b,0xce,0xc8,0x5e,0x80,0x9b,0x30,0xa4,0xd6,0x0d,0x77,0x47,0xcd,0xd0,0xf5,0xb9,0x9a,0xa8,0xc8,0x26,0x98,0x75,0x17,0x79,0x3a,0xaa,0x80,0x80,0xa0,0xb1,0x24,0xa8,0x55,0x8d,0xf7,0x2b,0xbe,0x37,0xb7,0x5f,0x4e,0xdb,0xb6,0xbe,0x82,0x16,0xd6,0xc6,0x33,0xfb,0x2b,0x22,0x80,0xe2,0x51,0x13,0xd8,0x69,0x5e,0x43,0x48,0x1c,0x3e,0xeb,0x39,0x7e,0xb1,0x92,0x50,0x52,0x29,0xb6,0x7a,0x20,0x1e,0xa8,0x93,0xc3,0xe2,0xcb,0x32,0xda,0x8b,0xc3,0x42,0xfa,0x4d,0xea,0x05,0x78]; + let pk_bytes: [u8; MLKEM768_PK_LEN] = [ + 0x29, 0x8A, 0xA1, 0x0D, 0x42, 0x3C, 0x8D, 0xDA, 0x06, 0x9D, 0x02, 0xBC, 0x59, 0xE6, 0xCD, + 0xF0, 0x3A, 0x09, 0x6B, 0x8B, 0x3D, 0xA4, 0xCA, 0xB9, 0xB8, 0x0C, 0xA4, 0xA1, 0x49, 0x07, + 0x67, 0x2C, 0xCE, 0xF1, 0xEC, 0x4F, 0xAF, 0x23, 0x4A, 0x0B, 0xC5, 0xB7, 0xE9, 0xD4, 0x73, + 0xF2, 0xB3, 0x13, 0x3B, 0x3B, 0x26, 0xA1, 0xD1, 0x75, 0xCB, 0x67, 0xA7, 0x80, 0x59, 0x19, + 0x69, 0x9C, 0x02, 0xF7, 0x65, 0x31, 0xB9, 0x9C, 0x5F, 0x89, 0x18, 0x07, 0x04, 0xBB, 0x4C, + 0xA4, 0x53, 0x5C, 0x5B, 0x89, 0x72, 0x67, 0x9C, 0x66, 0x0A, 0x07, 0xC5, 0xE5, 0x14, 0xB8, + 0x70, 0x09, 0xC8, 0x62, 0xEB, 0x8F, 0x51, 0x57, 0x69, 0x5E, 0xFB, 0x3F, 0xC4, 0x0A, 0x9D, + 0xEF, 0x6B, 0x81, 0xC1, 0xCC, 0x02, 0xA2, 0x49, 0xAE, 0x4F, 0x09, 0x4A, 0xD0, 0xD9, 0xBD, + 0x34, 0x85, 0xC1, 0xC1, 0xC6, 0x80, 0x80, 0x52, 0x0A, 0x7C, 0x8C, 0x63, 0x20, 0x32, 0xCE, + 0xE7, 0x38, 0x15, 0x4E, 0x5C, 0x51, 0x76, 0xC0, 0x7D, 0xA5, 0x60, 0x24, 0x77, 0x6A, 0x43, + 0x0F, 0xE7, 0x6E, 0xAC, 0xF6, 0x65, 0xA3, 0xF7, 0xB8, 0x32, 0x10, 0x22, 0x15, 0xBC, 0x82, + 0xF1, 0x09, 0x39, 0xC8, 0x35, 0x57, 0x04, 0x33, 0x6A, 0x8F, 0xAC, 0x1D, 0x81, 0xE4, 0xBB, + 0x04, 0x85, 0xAA, 0x5D, 0x7C, 0x74, 0xD6, 0xB5, 0x9B, 0xBE, 0x5C, 0x5E, 0x97, 0x2A, 0x0D, + 0x8B, 0xAC, 0x41, 0x1B, 0x55, 0xB5, 0xD5, 0x55, 0x7C, 0xD6, 0x80, 0xA1, 0xA8, 0xF7, 0x1B, + 0x4E, 0xB8, 0x6B, 0xC4, 0x8C, 0x9A, 0x05, 0x09, 0x73, 0x1A, 0x54, 0xBD, 0x9D, 0x72, 0x90, + 0xB2, 0x79, 0x63, 0xE4, 0x37, 0x2D, 0xC9, 0xB1, 0x99, 0xCF, 0xDC, 0xAC, 0x0B, 0x01, 0xAC, + 0xD2, 0x8A, 0x62, 0x39, 0x51, 0x12, 0xE4, 0xC4, 0x36, 0x48, 0xD6, 0x22, 0xC4, 0x8C, 0x82, + 0x34, 0xD0, 0x14, 0x40, 0xE8, 0xCC, 0x37, 0x6C, 0x92, 0x7F, 0x23, 0xA5, 0xAF, 0xC9, 0xAC, + 0x04, 0x74, 0xC6, 0x62, 0x27, 0x4E, 0x42, 0x45, 0x25, 0xC8, 0x55, 0x2E, 0xCE, 0x3B, 0x3F, + 0xE2, 0x65, 0x16, 0xDE, 0x90, 0x1B, 0xC7, 0xD5, 0x15, 0xBD, 0xE8, 0x95, 0x58, 0xE6, 0x26, + 0xC9, 0x5C, 0x80, 0xB9, 0x33, 0x42, 0xF8, 0x01, 0x00, 0x04, 0xF3, 0x9E, 0x6C, 0x6C, 0x94, + 0x87, 0x1C, 0x5E, 0x34, 0x4C, 0xAB, 0x39, 0x66, 0xC8, 0x35, 0xF9, 0xA9, 0x6A, 0x59, 0xAF, + 0xD3, 0x1C, 0x40, 0x28, 0x6B, 0x38, 0xB1, 0xC1, 0xA7, 0x84, 0x70, 0xBA, 0xB9, 0x47, 0x51, + 0x89, 0x34, 0x45, 0x3C, 0xE8, 0x67, 0x36, 0xA9, 0x19, 0xF1, 0xF5, 0xA6, 0xD5, 0x10, 0xA8, + 0x6F, 0x54, 0x54, 0xFC, 0x39, 0x80, 0xCB, 0x5C, 0x76, 0x5B, 0xD2, 0xBD, 0x5F, 0x7B, 0x36, + 0xB1, 0x41, 0x0D, 0x66, 0x35, 0xC8, 0xCE, 0xB4, 0x7C, 0x4D, 0xDA, 0x0D, 0x76, 0xA2, 0x8E, + 0xAC, 0x93, 0x9C, 0x71, 0xC3, 0x02, 0x48, 0x04, 0x86, 0x6C, 0x71, 0x62, 0x66, 0x58, 0x44, + 0x21, 0x63, 0xC2, 0xC2, 0x21, 0x17, 0xE5, 0x0A, 0xCE, 0xFC, 0xE6, 0x37, 0x8A, 0x98, 0x56, + 0x52, 0x30, 0x2A, 0x4E, 0xF0, 0xC2, 0xCE, 0x0C, 0xC7, 0x16, 0xB7, 0x79, 0x6E, 0x2B, 0x6B, + 0x2E, 0x37, 0x77, 0xDF, 0xA1, 0xAC, 0x3D, 0xA2, 0x59, 0xA3, 0x1B, 0x5A, 0x9B, 0x53, 0x0F, + 0x8C, 0xB6, 0x38, 0xA8, 0x1A, 0x62, 0xAC, 0x30, 0x18, 0x49, 0xAB, 0xAF, 0x95, 0xA7, 0x30, + 0x1B, 0xDA, 0x30, 0x06, 0x89, 0x09, 0xBF, 0xDB, 0x7E, 0x67, 0xDB, 0xCC, 0xBB, 0x38, 0xA5, + 0x55, 0x1A, 0x25, 0xB1, 0xA3, 0xA0, 0xF6, 0x85, 0x74, 0x8A, 0xD5, 0x75, 0x3D, 0x88, 0x80, + 0xF0, 0x01, 0x6C, 0x62, 0x74, 0x86, 0x16, 0x63, 0x84, 0xC5, 0x57, 0x1F, 0xE2, 0x36, 0x59, + 0x00, 0x36, 0x4D, 0x03, 0x83, 0x11, 0xE2, 0xD8, 0x75, 0xDB, 0x36, 0x66, 0x86, 0x93, 0x2B, + 0x5E, 0xC6, 0x02, 0x43, 0x0A, 0x36, 0x9E, 0x87, 0xA6, 0xEF, 0x5C, 0x33, 0x87, 0x86, 0x65, + 0x78, 0x25, 0xBD, 0x4C, 0x05, 0x7A, 0xCE, 0xB9, 0x23, 0xEB, 0x09, 0x35, 0xE6, 0x90, 0x5E, + 0x63, 0xB4, 0xCE, 0xD7, 0xF8, 0x08, 0x57, 0xA7, 0x73, 0xDD, 0x64, 0xB1, 0x50, 0xD2, 0x66, + 0x12, 0xEA, 0x9A, 0xC1, 0x20, 0x52, 0xDB, 0x20, 0x17, 0xBF, 0x18, 0x43, 0xCC, 0xB4, 0xB3, + 0x28, 0x1B, 0x69, 0x0D, 0xC7, 0x28, 0xAD, 0xFA, 0x85, 0xC0, 0x02, 0x81, 0xB8, 0xE3, 0xC0, + 0x92, 0x87, 0x33, 0x5F, 0x85, 0x6B, 0x4F, 0xC2, 0x89, 0x2F, 0x69, 0xA2, 0xF5, 0x79, 0x21, + 0xAD, 0xA0, 0x19, 0x14, 0xC4, 0x09, 0x88, 0x66, 0x2D, 0x57, 0x76, 0x96, 0x62, 0xA7, 0x86, + 0x35, 0x1B, 0x9B, 0x66, 0x49, 0x3D, 0xAB, 0x79, 0x59, 0x4D, 0x98, 0x6D, 0xE2, 0x10, 0x0D, + 0x65, 0xBA, 0x0F, 0xF4, 0xEA, 0x58, 0xB8, 0x15, 0x38, 0xD2, 0x4A, 0x44, 0x35, 0xA2, 0x58, + 0xFA, 0xC2, 0x54, 0x04, 0xAA, 0x7F, 0x41, 0xF6, 0x58, 0xB1, 0x38, 0x50, 0x65, 0xE1, 0x58, + 0xDC, 0xB6, 0x01, 0x15, 0x73, 0x27, 0x20, 0xF4, 0x04, 0x59, 0xAA, 0xAC, 0x15, 0xE4, 0x06, + 0x95, 0x3A, 0x90, 0xAC, 0x52, 0x99, 0x7D, 0x1C, 0xCD, 0x07, 0x00, 0x60, 0xEF, 0xC6, 0x5D, + 0xB9, 0xE6, 0x53, 0x35, 0x44, 0x67, 0xFA, 0xD5, 0x6E, 0xC7, 0x13, 0xC8, 0x6E, 0x75, 0x40, + 0xC4, 0x23, 0xAC, 0xF2, 0x66, 0x9F, 0x52, 0xFA, 0x6F, 0x4A, 0xC6, 0x88, 0x8D, 0x87, 0x1E, + 0xF3, 0xE8, 0x47, 0xC0, 0x29, 0xA8, 0xAA, 0xFB, 0xB9, 0x2E, 0x17, 0xB2, 0x4A, 0xA0, 0x79, + 0xB1, 0xF4, 0x19, 0xBA, 0x61, 0x75, 0xB4, 0x42, 0xAF, 0xB1, 0x19, 0x09, 0xD4, 0xA5, 0x6B, + 0x70, 0xA0, 0x33, 0x5B, 0x28, 0x73, 0x92, 0x18, 0xAA, 0x7C, 0x93, 0x48, 0xE2, 0xC3, 0xC2, + 0xF3, 0xEB, 0x3D, 0x15, 0xA4, 0x1E, 0x64, 0x17, 0xC0, 0xDD, 0x94, 0xBF, 0xEB, 0x21, 0x41, + 0x9B, 0x31, 0x1A, 0x7B, 0xB1, 0x3A, 0x18, 0x0B, 0xBE, 0x83, 0x32, 0x18, 0xA9, 0xA6, 0xB1, + 0x74, 0x47, 0xCC, 0x85, 0xF2, 0x25, 0x85, 0x95, 0x87, 0xA7, 0x30, 0x77, 0x04, 0x9A, 0xCB, + 0xCF, 0xD4, 0x4D, 0x0F, 0x02, 0x54, 0x38, 0xE1, 0x5D, 0x15, 0x38, 0x27, 0x0D, 0x58, 0x6E, + 0x1B, 0xF8, 0x31, 0x92, 0xA9, 0x45, 0x9C, 0xF6, 0x3C, 0x0E, 0x97, 0x2F, 0x85, 0x29, 0x76, + 0x79, 0x83, 0x1E, 0xCF, 0x12, 0x15, 0x09, 0x85, 0x1C, 0xB8, 0x34, 0x0F, 0x6F, 0x10, 0x7B, + 0x0F, 0xA1, 0xA0, 0xEF, 0xD1, 0xB3, 0x6A, 0x81, 0x89, 0xBC, 0x08, 0x5C, 0x4F, 0x5C, 0xB7, + 0x84, 0xE5, 0x53, 0xF4, 0x1B, 0x91, 0x8F, 0x80, 0x39, 0x7C, 0xE1, 0x95, 0x6F, 0x78, 0x5B, + 0xEE, 0x37, 0x7C, 0xA9, 0xAA, 0x8B, 0xE6, 0x99, 0x8A, 0xDA, 0x30, 0xC2, 0x6B, 0x7C, 0x3D, + 0x8C, 0x6B, 0x55, 0x25, 0x4C, 0xC9, 0x62, 0x03, 0xB2, 0x0C, 0x42, 0xAE, 0xE0, 0xAC, 0x4E, + 0x1E, 0xBB, 0x40, 0x8E, 0x49, 0xA9, 0xE3, 0xF8, 0x79, 0xD0, 0xAB, 0x07, 0x85, 0xEB, 0x70, + 0x25, 0x42, 0x5D, 0x13, 0x05, 0xA2, 0x29, 0x9C, 0x01, 0x5E, 0x12, 0x0D, 0x16, 0x3B, 0x0E, + 0x19, 0x49, 0x4C, 0xE5, 0x72, 0x53, 0xD0, 0x24, 0x6D, 0x18, 0x27, 0x45, 0xCB, 0x81, 0x97, + 0xAB, 0x74, 0x38, 0xB3, 0xC1, 0xBB, 0x79, 0x72, 0xBE, 0xC5, 0xA3, 0x06, 0xEB, 0xA3, 0x56, + 0x78, 0x55, 0xC0, 0x14, 0x69, 0x9F, 0xEF, 0x65, 0xAE, 0x54, 0xC7, 0x70, 0xA0, 0xD8, 0x5C, + 0x18, 0x40, 0x0C, 0xF6, 0x42, 0xAE, 0xDC, 0x66, 0x07, 0x77, 0xBA, 0x4B, 0x13, 0x85, 0x02, + 0xBD, 0x5A, 0x78, 0x12, 0xF6, 0x21, 0xF8, 0x4A, 0x48, 0x29, 0x6B, 0x98, 0xDD, 0x43, 0x22, + 0xB6, 0xF1, 0x58, 0x28, 0xB8, 0xA8, 0xF0, 0xE0, 0x0A, 0x8B, 0xA4, 0x4A, 0x53, 0xC3, 0xA8, + 0xB1, 0x43, 0x57, 0x1B, 0x07, 0x40, 0xAB, 0xD5, 0x67, 0xDA, 0xF1, 0xCD, 0xE9, 0xC7, 0x9C, + 0x20, 0x4B, 0x6D, 0x5E, 0x25, 0x9D, 0x17, 0x66, 0xA3, 0x1B, 0xBB, 0xCB, 0x4E, 0x6A, 0x05, + 0xCF, 0x45, 0x02, 0x17, 0x6B, 0x30, 0x1C, 0x1C, 0x2F, 0x41, 0x24, 0x77, 0x50, 0x15, 0x7B, + 0xCE, 0xC8, 0x5E, 0x80, 0x9B, 0x30, 0xA4, 0xD6, 0x0D, 0x77, 0x47, 0xCD, 0xD0, 0xF5, 0xB9, + 0x9A, 0xA8, 0xC8, 0x26, 0x98, 0x75, 0x17, 0x79, 0x3A, 0xAA, 0x80, 0x80, 0xA0, 0xB1, 0x24, + 0xA8, 0x55, 0x8D, 0xF7, 0x2B, 0xBE, 0x37, 0xB7, 0x5F, 0x4E, 0xDB, 0xB6, 0xBE, 0x82, 0x16, + 0xD6, 0xC6, 0x33, 0xFB, 0x2B, 0x22, 0x80, 0xE2, 0x51, 0x13, 0xD8, 0x69, 0x5E, 0x43, 0x48, + 0x1C, 0x3E, 0xEB, 0x39, 0x7E, 0xB1, 0x92, 0x50, 0x52, 0x29, 0xB6, 0x7A, 0x20, 0x1E, 0xA8, + 0x93, 0xC3, 0xE2, 0xCB, 0x32, 0xDA, 0x8B, 0xC3, 0x42, 0xFA, 0x4D, 0xEA, 0x05, 0x78, + ]; let pk = MLKEM768PublicKey::from_bytes(&pk_bytes).unwrap(); let (ss, ct) = MLKEM768::encaps(&pk).unwrap(); print!("{:x?}", ss); @@ -253,7 +599,7 @@ fn bench_mlkem768_lowmemory_encaps() { } fn bench_mlkem1024_encaps() { - use bouncycastle::mlkem::{MLKEMTrait, MLKEM1024, MLKEM1024PublicKey}; + use bouncycastle::mlkem::{MLKEM1024, MLKEM1024PublicKey, MLKEMTrait}; eprintln!("MLKEM1024/Encaps"); @@ -267,7 +613,113 @@ fn bench_mlkem1024_encaps() { // use bouncycastle_hex as hex; // eprintln!("pk:\n{}", &hex::encode(pk.encode())); - let pk_bytes: [u8; MLKEM1024_PK_LEN] = [0x4b,0x94,0xc2,0x94,0x50,0x11,0x11,0x91,0x82,0x3b,0x35,0x14,0xc9,0xac,0x1e,0xa3,0xd9,0x82,0x5c,0xcb,0x86,0x39,0x3a,0x2d,0xfb,0x04,0x65,0x4f,0xa2,0x19,0x2d,0x37,0xbf,0xad,0x1c,0x49,0x7c,0x65,0x02,0xee,0xe5,0xca,0x80,0xa7,0x3b,0xfc,0xe0,0xba,0xf5,0xa5,0x4a,0x88,0x58,0x5a,0x40,0x13,0x97,0xa3,0xd2,0x32,0xf4,0x26,0xa7,0xaf,0xb0,0x82,0xbc,0x21,0xa4,0x43,0x17,0x09,0x0e,0xaa,0xc7,0x59,0x2c,0x2e,0xa8,0x8a,0x65,0x3c,0x44,0x91,0xea,0x19,0x39,0x31,0x33,0x5f,0x52,0xe9,0x89,0xa3,0xc4,0xcc,0x56,0xd9,0xc5,0x53,0x73,0x2d,0x57,0xc4,0x70,0xfb,0x41,0xab,0x75,0x9b,0x65,0xd2,0xd0,0x44,0x45,0x38,0x2f,0xcd,0x9c,0x4e,0x34,0x4a,0x11,0x28,0xfa,0x9e,0x11,0xe0,0x43,0x58,0xe1,0x92,0xed,0x01,0x4b,0x23,0x23,0x2a,0x7e,0xe2,0xb2,0x2e,0x23,0x71,0x7f,0x44,0x11,0x1e,0xe3,0x35,0x75,0x39,0x9c,0x37,0x64,0x6d,0xa9,0x81,0x3e,0xc9,0xb2,0x12,0xaf,0xe9,0x4e,0x5d,0xc5,0xc2,0x33,0x0a,0x72,0x94,0xcc,0x1f,0x42,0x34,0xa6,0xd3,0xfb,0xb4,0xf1,0x68,0x5a,0xb8,0x89,0x2c,0x04,0xac,0xb1,0x7c,0xd1,0xc1,0x70,0xd7,0xb0,0x61,0x1b,0x6a,0x71,0x76,0xc7,0x94,0xcc,0x8c,0x67,0xf5,0x5f,0xc9,0x23,0xc2,0xad,0x20,0x31,0x00,0xf3,0x65,0x99,0x18,0x82,0xc3,0x02,0x43,0xd7,0x78,0x13,0x84,0x3b,0x5e,0xc7,0xc9,0x64,0x03,0x22,0x63,0x70,0x60,0x92,0xec,0xf0,0x0c,0x75,0x16,0xbe,0x64,0xe4,0x59,0x8c,0xa4,0x22,0x6c,0x06,0x9b,0xb5,0xe6,0x7e,0x41,0x75,0xcf,0x22,0x86,0xc8,0xdd,0x5c,0x48,0x8a,0x6c,0x58,0x61,0xf3,0x1b,0xaa,0x0b,0xd0,0x26,0x94,0x70,0xe8,0xb5,0x51,0xdd,0x3b,0xcd,0x38,0xc8,0x6c,0x12,0xf9,0xcd,0xb1,0x76,0xc7,0x7d,0xc8,0xb6,0xc0,0x2a,0x70,0x1f,0x47,0x89,0x02,0xc8,0x55,0x3f,0x69,0x4c,0x0d,0x82,0x72,0x7b,0x4c,0x4a,0x5c,0x2c,0x10,0x41,0x21,0x2a,0xa1,0x27,0x48,0x08,0xb8,0x21,0x11,0xb3,0x77,0xec,0x75,0x21,0x4e,0x9b,0x19,0x78,0xf7,0x60,0x04,0xd4,0x13,0x9d,0x98,0x61,0x3f,0x4b,0x8e,0x98,0xd2,0x0a,0xf7,0xb5,0x34,0x07,0x3a,0x50,0x9a,0x95,0x9b,0x7a,0x75,0x64,0xf9,0xb4,0x0c,0xa2,0x18,0xbf,0x61,0x82,0x93,0x20,0xa8,0x50,0x20,0x17,0x95,0x4d,0x32,0x8d,0x7a,0xc6,0xc7,0x69,0xec,0x29,0x70,0x07,0x56,0xe7,0xb0,0x68,0x5b,0x34,0x0d,0x5e,0x11,0x80,0x59,0x50,0x4a,0x49,0xa9,0xa5,0x0a,0x10,0x19,0x8e,0xb1,0x0a,0x57,0x84,0x67,0x8e,0xb4,0x27,0xd7,0xb4,0xba,0xbb,0x95,0x52,0x93,0x3b,0x06,0x28,0x97,0x97,0x3e,0x13,0x18,0xea,0xf0,0xa0,0xea,0xc3,0x75,0x84,0xa6,0x54,0x01,0xb1,0x70,0x3e,0x04,0x2a,0xcc,0xd8,0x37,0x53,0x14,0x83,0xf2,0x41,0xca,0xdc,0xd1,0xc1,0xd3,0x78,0x11,0x9e,0x69,0x44,0x29,0xdb,0x19,0x9a,0xc8,0x91,0xe4,0xc5,0x34,0x37,0x57,0x08,0x5b,0xb3,0xae,0x78,0x36,0x67,0x35,0x0c,0x44,0x58,0xd9,0x76,0x72,0xe8,0x61,0xe8,0x0b,0x1d,0x26,0x79,0x51,0x0e,0xa3,0xa6,0xf2,0x36,0x0c,0x77,0xa4,0x69,0x42,0xc7,0xa0,0x6a,0x55,0x4d,0x22,0x80,0x80,0xc8,0x4b,0x47,0xae,0xf1,0x4d,0xb1,0x76,0x20,0xcb,0x16,0xc0,0x6a,0xb3,0x0a,0x1b,0xe4,0xcd,0xa7,0x08,0x2b,0xe9,0xf8,0x7e,0x9c,0x21,0x1c,0x46,0x91,0x63,0x49,0xa5,0xba,0x8e,0xaa,0x52,0x01,0xc7,0x29,0x4a,0x3c,0x08,0x85,0xb5,0x3b,0x65,0x74,0x52,0x10,0x88,0x25,0xec,0x64,0x6c,0x90,0xa0,0x46,0x12,0x32,0x4e,0xe7,0xd0,0x31,0xaf,0xe5,0x34,0x31,0x32,0xcb,0xef,0x67,0xb6,0xef,0xb1,0xa5,0xec,0x28,0x09,0xb7,0x73,0x53,0x8c,0xe7,0x7b,0x3d,0x8b,0x04,0xeb,0x0b,0x3c,0x22,0x56,0x01,0x1e,0x4c,0x71,0x6c,0x19,0xa8,0xba,0x07,0x52,0xbf,0x71,0x49,0x21,0x17,0x64,0x9f,0x06,0x15,0xc3,0x29,0x0f,0xc2,0x9a,0x46,0xfd,0xe4,0xbd,0x52,0xdb,0x92,0x86,0xd6,0x03,0x38,0x82,0x44,0x25,0x9c,0x15,0xa7,0xac,0x2b,0x64,0x0a,0x60,0xcc,0x03,0x37,0x6a,0x58,0x41,0xa3,0xfb,0x8a,0x47,0x35,0x68,0xfa,0x9b,0x1a,0x26,0x72,0x15,0xf3,0x4c,0x01,0x69,0x7b,0x0f,0x0e,0x62,0x71,0x75,0xd7,0x21,0x05,0xb7,0x70,0x7c,0x29,0xb9,0xe6,0x14,0xbd,0xc3,0x3a,0x6f,0x6c,0x81,0x8a,0x95,0x37,0x0b,0x42,0x78,0x82,0xd7,0xb4,0x76,0x79,0x6a,0x9e,0xc6,0xeb,0x99,0x32,0x74,0xcd,0x9b,0x23,0x91,0xa8,0x2b,0xa4,0x5e,0x33,0x93,0xd2,0xe9,0xae,0x97,0x21,0xca,0x9d,0x6c,0x1b,0x98,0x8b,0x58,0x27,0x71,0x3f,0x90,0xa6,0x58,0x5d,0xe9,0x43,0x35,0x28,0xc0,0x2b,0x03,0xce,0x10,0xbb,0x5f,0x72,0x01,0x38,0xd0,0xfb,0xb4,0xc3,0x0c,0x12,0x66,0xb9,0x18,0xe5,0x29,0x25,0xdf,0xe1,0x7b,0x37,0xf9,0x5d,0x22,0xbc,0xa5,0x4f,0x47,0x59,0x19,0xac,0x85,0x90,0x98,0xc0,0xf0,0xd0,0x8a,0xc5,0x87,0x5e,0xf2,0x9b,0x56,0xfd,0x14,0x1e,0x6e,0xf1,0x5f,0x70,0x0a,0x0b,0x66,0xf3,0x95,0x95,0xc5,0x88,0x17,0x73,0x73,0xc4,0x66,0x9b,0x21,0xbc,0x07,0x1e,0x4c,0x3a,0xa5,0xf0,0xb4,0xa3,0x1b,0x62,0x58,0xf3,0x5d,0xa2,0x4a,0xc3,0xcd,0x29,0xc7,0xf2,0x09,0x24,0x10,0xc5,0x07,0x83,0x55,0xb1,0x38,0xfb,0x53,0xa6,0xb9,0xae,0x6e,0x0b,0x9c,0x08,0x24,0x3e,0x7b,0xaa,0x45,0xc4,0x73,0x76,0xeb,0x8c,0x7f,0x13,0xd4,0xcf,0x51,0xaa,0x73,0x6f,0xa3,0x15,0x40,0xc9,0x24,0x1f,0x37,0x0d,0xa5,0x44,0xbf,0x9f,0x9c,0x28,0xd9,0xa5,0x7e,0x2f,0x2a,0x7c,0xa9,0x5a,0x4e,0x4b,0x46,0x6e,0x64,0x1a,0xb3,0xbc,0xc7,0x6a,0xdf,0x11,0x39,0xd5,0x67,0xa6,0xf1,0x2b,0x52,0xf3,0xa6,0x5e,0x7e,0xc0,0xaa,0xe2,0x6b,0xca,0xa8,0xc5,0x58,0x33,0xb0,0x4e,0x59,0x99,0x8e,0xbc,0x9a,0x19,0x30,0xfb,0xb6,0xd2,0x23,0x3c,0x53,0xd2,0xc1,0xf8,0xb9,0x51,0x8e,0x3c,0x2d,0xe7,0x3a,0x19,0xde,0xe6,0xb3,0x80,0xa5,0xb3,0x29,0x71,0xcf,0x64,0xe1,0x29,0xfd,0x6c,0x1f,0xa6,0xe7,0x5d,0x4a,0x23,0x45,0x01,0xe9,0x66,0xdd,0x3a,0x54,0x0a,0xf5,0xc8,0xf4,0xf3,0x4a,0x6b,0x4a,0x25,0x3e,0xe2,0x84,0x92,0x56,0x6d,0x5e,0x67,0xc6,0xf5,0x58,0x55,0xfc,0xb0,0x50,0x6f,0xb0,0x6c,0x15,0x67,0x44,0xd9,0xa0,0x3a,0x31,0xa2,0x6f,0xa9,0x4c,0xad,0x14,0xf1,0x57,0xb7,0xf3,0x03,0xd0,0x7a,0x69,0xc7,0x73,0x76,0x8f,0xcb,0x4d,0x07,0x9c,0x09,0x05,0x97,0x03,0xa0,0xc3,0xa9,0x4d,0xe4,0xb9,0x9e,0xa3,0xa2,0xf1,0x65,0x83,0xd0,0xf9,0x17,0x0a,0x39,0x50,0xdb,0x07,0xb4,0xf0,0xbc,0x30,0x80,0x29,0x27,0xf9,0xf7,0x96,0x1b,0x62,0x59,0x89,0x26,0x36,0xa9,0x50,0x2a,0x27,0x05,0x30,0x36,0x37,0x79,0x9d,0xd3,0x44,0xda,0x45,0x1c,0x1c,0xf7,0xbf,0x67,0x84,0x0c,0xeb,0x30,0x79,0xab,0x8c,0x6b,0x8c,0x19,0x27,0xf6,0x40,0x53,0xc6,0x12,0x45,0x0c,0x45,0xc9,0xe6,0x03,0xbc,0x16,0x66,0x6e,0x59,0x6b,0x34,0x71,0xe1,0x03,0xb6,0xf1,0x54,0x47,0x42,0x4d,0x17,0x02,0x20,0x48,0x11,0x1f,0xfb,0xd3,0x7e,0x1c,0x67,0x0f,0x64,0xf1,0x4b,0x8a,0x7b,0x32,0xb9,0x4c,0x1a,0x49,0xb4,0x5d,0xd2,0xfc,0x38,0xcd,0x52,0x89,0xd9,0x10,0xad,0x63,0x60,0x2c,0xf5,0xe1,0x30,0x42,0xc6,0x4a,0xc6,0x79,0x7b,0x89,0xfb,0x55,0x1a,0xd0,0x8e,0x05,0xa9,0x2d,0x20,0x0c,0xcc,0xb7,0xe7,0x12,0xef,0x23,0xc9,0x31,0x2c,0xb3,0x50,0xf0,0x29,0xab,0x53,0x7e,0x28,0x73,0x47,0xfd,0x30,0x75,0xac,0x10,0x90,0x6a,0x78,0x3f,0x1c,0x6c,0x07,0xcc,0xb8,0x8f,0x41,0x22,0x8c,0x4b,0xe1,0xc6,0x40,0xf7,0x90,0xb5,0xc3,0xa5,0xd5,0xd3,0xca,0x79,0x24,0x95,0xd7,0x4b,0xc4,0x61,0x56,0x26,0x58,0xc0,0x7a,0xc6,0x00,0x27,0x6b,0x92,0x4a,0xb5,0xbc,0x9b,0xe1,0xf0,0x49,0x4c,0xb7,0x6f,0x82,0xf4,0x60,0xa7,0x48,0x09,0x72,0x66,0x33,0x81,0xe1,0x69,0x99,0x60,0x61,0xd7,0x99,0x85,0x9e,0xc5,0x4d,0x4f,0x5c,0xa5,0xc4,0x11,0xc0,0x1d,0xb1,0x59,0x7b,0x16,0x59,0x77,0x66,0x9d,0xe1,0x3a,0x92,0x8a,0x34,0xaf,0xba,0xc2,0x58,0xfe,0xa8,0xc4,0x76,0x42,0x39,0xc9,0x42,0x1d,0xc3,0x11,0x9b,0xf5,0xb4,0x76,0x99,0x20,0x69,0x78,0x32,0x7b,0x1c,0x53,0x45,0xef,0x74,0x6a,0x79,0x83,0x84,0x1f,0x05,0x6e,0x25,0x34,0x10,0x0a,0xb2,0x4d,0x4e,0x9a,0xbb,0xd0,0xb1,0x7c,0x6a,0x95,0xbd,0x4c,0x3c,0x0e,0x40,0xf6,0x9e,0x16,0x12,0xac,0xee,0xb2,0x8b,0x99,0x08,0x6c,0x95,0x11,0x6e,0x72,0x04,0x27,0x38,0x93,0x39,0x0b,0xf4,0x6b,0x89,0x9b,0x36,0x28,0x6b,0x0e,0xbf,0x19,0x47,0xbb,0x98,0x84,0xf7,0x32,0xca,0x27,0xda,0x82,0xb1,0x9b,0x5d,0xc0,0xcc,0x7f,0x88,0x85,0x71,0x49,0x10,0x88,0x8b,0x23,0x10,0xc4,0xf9,0x31,0x9d,0x41,0x0b,0x34,0xe6,0x43,0x3b,0x90,0x03,0xe2,0x17,0x6b,0xb9,0x95,0x25,0x74,0x56,0x10,0x6e,0x89,0x52,0x16,0x3b,0x8b,0xa5,0x92,0x53,0x0c,0xc5,0xaa,0x0a,0xeb,0x43,0xad,0x39,0x8f,0xe9,0xe9,0x7b,0xaa,0x52,0x3d,0x7a,0x44,0x31,0x67,0x7c,0x3d,0x3a,0xf0,0x71,0x9e,0x47,0x5d,0xb8,0x5c,0xa9,0x5a,0xf5,0x08,0x9b,0xea,0xbe,0xb0,0x5b,0x2f,0xaa,0xb4,0x89,0x6b,0xa6,0x0f,0x81,0xc8,0x84,0x72,0xa5,0x7b,0x46,0xa8,0x28,0x82,0x6a,0x0c,0xdf,0xb4,0x46,0xf8,0x18,0x91,0x82,0xd2,0xbf,0x5e,0xac,0x4e,0xc1,0xcc,0x5d,0xea,0xf5,0x99,0xc8,0xa1,0x3e,0x48,0x23,0x54,0x06,0xd1,0x7f,0xfd,0xdc,0x83,0x44,0xb6,0xc6,0x69,0x84,0xa8,0x68,0xaa,0x92,0xfa,0x02,0x22,0x7a,0x08,0x69,0x50,0xeb,0x0c,0x87,0x01,0xed,0x58,0xdc,0x62,0x87,0x76,0xb9,0x83,0x88,0x2e,0x11,0x75]; + let pk_bytes: [u8; MLKEM1024_PK_LEN] = [ + 0x4B, 0x94, 0xC2, 0x94, 0x50, 0x11, 0x11, 0x91, 0x82, 0x3B, 0x35, 0x14, 0xC9, 0xAC, 0x1E, + 0xA3, 0xD9, 0x82, 0x5C, 0xCB, 0x86, 0x39, 0x3A, 0x2D, 0xFB, 0x04, 0x65, 0x4F, 0xA2, 0x19, + 0x2D, 0x37, 0xBF, 0xAD, 0x1C, 0x49, 0x7C, 0x65, 0x02, 0xEE, 0xE5, 0xCA, 0x80, 0xA7, 0x3B, + 0xFC, 0xE0, 0xBA, 0xF5, 0xA5, 0x4A, 0x88, 0x58, 0x5A, 0x40, 0x13, 0x97, 0xA3, 0xD2, 0x32, + 0xF4, 0x26, 0xA7, 0xAF, 0xB0, 0x82, 0xBC, 0x21, 0xA4, 0x43, 0x17, 0x09, 0x0E, 0xAA, 0xC7, + 0x59, 0x2C, 0x2E, 0xA8, 0x8A, 0x65, 0x3C, 0x44, 0x91, 0xEA, 0x19, 0x39, 0x31, 0x33, 0x5F, + 0x52, 0xE9, 0x89, 0xA3, 0xC4, 0xCC, 0x56, 0xD9, 0xC5, 0x53, 0x73, 0x2D, 0x57, 0xC4, 0x70, + 0xFB, 0x41, 0xAB, 0x75, 0x9B, 0x65, 0xD2, 0xD0, 0x44, 0x45, 0x38, 0x2F, 0xCD, 0x9C, 0x4E, + 0x34, 0x4A, 0x11, 0x28, 0xFA, 0x9E, 0x11, 0xE0, 0x43, 0x58, 0xE1, 0x92, 0xED, 0x01, 0x4B, + 0x23, 0x23, 0x2A, 0x7E, 0xE2, 0xB2, 0x2E, 0x23, 0x71, 0x7F, 0x44, 0x11, 0x1E, 0xE3, 0x35, + 0x75, 0x39, 0x9C, 0x37, 0x64, 0x6D, 0xA9, 0x81, 0x3E, 0xC9, 0xB2, 0x12, 0xAF, 0xE9, 0x4E, + 0x5D, 0xC5, 0xC2, 0x33, 0x0A, 0x72, 0x94, 0xCC, 0x1F, 0x42, 0x34, 0xA6, 0xD3, 0xFB, 0xB4, + 0xF1, 0x68, 0x5A, 0xB8, 0x89, 0x2C, 0x04, 0xAC, 0xB1, 0x7C, 0xD1, 0xC1, 0x70, 0xD7, 0xB0, + 0x61, 0x1B, 0x6A, 0x71, 0x76, 0xC7, 0x94, 0xCC, 0x8C, 0x67, 0xF5, 0x5F, 0xC9, 0x23, 0xC2, + 0xAD, 0x20, 0x31, 0x00, 0xF3, 0x65, 0x99, 0x18, 0x82, 0xC3, 0x02, 0x43, 0xD7, 0x78, 0x13, + 0x84, 0x3B, 0x5E, 0xC7, 0xC9, 0x64, 0x03, 0x22, 0x63, 0x70, 0x60, 0x92, 0xEC, 0xF0, 0x0C, + 0x75, 0x16, 0xBE, 0x64, 0xE4, 0x59, 0x8C, 0xA4, 0x22, 0x6C, 0x06, 0x9B, 0xB5, 0xE6, 0x7E, + 0x41, 0x75, 0xCF, 0x22, 0x86, 0xC8, 0xDD, 0x5C, 0x48, 0x8A, 0x6C, 0x58, 0x61, 0xF3, 0x1B, + 0xAA, 0x0B, 0xD0, 0x26, 0x94, 0x70, 0xE8, 0xB5, 0x51, 0xDD, 0x3B, 0xCD, 0x38, 0xC8, 0x6C, + 0x12, 0xF9, 0xCD, 0xB1, 0x76, 0xC7, 0x7D, 0xC8, 0xB6, 0xC0, 0x2A, 0x70, 0x1F, 0x47, 0x89, + 0x02, 0xC8, 0x55, 0x3F, 0x69, 0x4C, 0x0D, 0x82, 0x72, 0x7B, 0x4C, 0x4A, 0x5C, 0x2C, 0x10, + 0x41, 0x21, 0x2A, 0xA1, 0x27, 0x48, 0x08, 0xB8, 0x21, 0x11, 0xB3, 0x77, 0xEC, 0x75, 0x21, + 0x4E, 0x9B, 0x19, 0x78, 0xF7, 0x60, 0x04, 0xD4, 0x13, 0x9D, 0x98, 0x61, 0x3F, 0x4B, 0x8E, + 0x98, 0xD2, 0x0A, 0xF7, 0xB5, 0x34, 0x07, 0x3A, 0x50, 0x9A, 0x95, 0x9B, 0x7A, 0x75, 0x64, + 0xF9, 0xB4, 0x0C, 0xA2, 0x18, 0xBF, 0x61, 0x82, 0x93, 0x20, 0xA8, 0x50, 0x20, 0x17, 0x95, + 0x4D, 0x32, 0x8D, 0x7A, 0xC6, 0xC7, 0x69, 0xEC, 0x29, 0x70, 0x07, 0x56, 0xE7, 0xB0, 0x68, + 0x5B, 0x34, 0x0D, 0x5E, 0x11, 0x80, 0x59, 0x50, 0x4A, 0x49, 0xA9, 0xA5, 0x0A, 0x10, 0x19, + 0x8E, 0xB1, 0x0A, 0x57, 0x84, 0x67, 0x8E, 0xB4, 0x27, 0xD7, 0xB4, 0xBA, 0xBB, 0x95, 0x52, + 0x93, 0x3B, 0x06, 0x28, 0x97, 0x97, 0x3E, 0x13, 0x18, 0xEA, 0xF0, 0xA0, 0xEA, 0xC3, 0x75, + 0x84, 0xA6, 0x54, 0x01, 0xB1, 0x70, 0x3E, 0x04, 0x2A, 0xCC, 0xD8, 0x37, 0x53, 0x14, 0x83, + 0xF2, 0x41, 0xCA, 0xDC, 0xD1, 0xC1, 0xD3, 0x78, 0x11, 0x9E, 0x69, 0x44, 0x29, 0xDB, 0x19, + 0x9A, 0xC8, 0x91, 0xE4, 0xC5, 0x34, 0x37, 0x57, 0x08, 0x5B, 0xB3, 0xAE, 0x78, 0x36, 0x67, + 0x35, 0x0C, 0x44, 0x58, 0xD9, 0x76, 0x72, 0xE8, 0x61, 0xE8, 0x0B, 0x1D, 0x26, 0x79, 0x51, + 0x0E, 0xA3, 0xA6, 0xF2, 0x36, 0x0C, 0x77, 0xA4, 0x69, 0x42, 0xC7, 0xA0, 0x6A, 0x55, 0x4D, + 0x22, 0x80, 0x80, 0xC8, 0x4B, 0x47, 0xAE, 0xF1, 0x4D, 0xB1, 0x76, 0x20, 0xCB, 0x16, 0xC0, + 0x6A, 0xB3, 0x0A, 0x1B, 0xE4, 0xCD, 0xA7, 0x08, 0x2B, 0xE9, 0xF8, 0x7E, 0x9C, 0x21, 0x1C, + 0x46, 0x91, 0x63, 0x49, 0xA5, 0xBA, 0x8E, 0xAA, 0x52, 0x01, 0xC7, 0x29, 0x4A, 0x3C, 0x08, + 0x85, 0xB5, 0x3B, 0x65, 0x74, 0x52, 0x10, 0x88, 0x25, 0xEC, 0x64, 0x6C, 0x90, 0xA0, 0x46, + 0x12, 0x32, 0x4E, 0xE7, 0xD0, 0x31, 0xAF, 0xE5, 0x34, 0x31, 0x32, 0xCB, 0xEF, 0x67, 0xB6, + 0xEF, 0xB1, 0xA5, 0xEC, 0x28, 0x09, 0xB7, 0x73, 0x53, 0x8C, 0xE7, 0x7B, 0x3D, 0x8B, 0x04, + 0xEB, 0x0B, 0x3C, 0x22, 0x56, 0x01, 0x1E, 0x4C, 0x71, 0x6C, 0x19, 0xA8, 0xBA, 0x07, 0x52, + 0xBF, 0x71, 0x49, 0x21, 0x17, 0x64, 0x9F, 0x06, 0x15, 0xC3, 0x29, 0x0F, 0xC2, 0x9A, 0x46, + 0xFD, 0xE4, 0xBD, 0x52, 0xDB, 0x92, 0x86, 0xD6, 0x03, 0x38, 0x82, 0x44, 0x25, 0x9C, 0x15, + 0xA7, 0xAC, 0x2B, 0x64, 0x0A, 0x60, 0xCC, 0x03, 0x37, 0x6A, 0x58, 0x41, 0xA3, 0xFB, 0x8A, + 0x47, 0x35, 0x68, 0xFA, 0x9B, 0x1A, 0x26, 0x72, 0x15, 0xF3, 0x4C, 0x01, 0x69, 0x7B, 0x0F, + 0x0E, 0x62, 0x71, 0x75, 0xD7, 0x21, 0x05, 0xB7, 0x70, 0x7C, 0x29, 0xB9, 0xE6, 0x14, 0xBD, + 0xC3, 0x3A, 0x6F, 0x6C, 0x81, 0x8A, 0x95, 0x37, 0x0B, 0x42, 0x78, 0x82, 0xD7, 0xB4, 0x76, + 0x79, 0x6A, 0x9E, 0xC6, 0xEB, 0x99, 0x32, 0x74, 0xCD, 0x9B, 0x23, 0x91, 0xA8, 0x2B, 0xA4, + 0x5E, 0x33, 0x93, 0xD2, 0xE9, 0xAE, 0x97, 0x21, 0xCA, 0x9D, 0x6C, 0x1B, 0x98, 0x8B, 0x58, + 0x27, 0x71, 0x3F, 0x90, 0xA6, 0x58, 0x5D, 0xE9, 0x43, 0x35, 0x28, 0xC0, 0x2B, 0x03, 0xCE, + 0x10, 0xBB, 0x5F, 0x72, 0x01, 0x38, 0xD0, 0xFB, 0xB4, 0xC3, 0x0C, 0x12, 0x66, 0xB9, 0x18, + 0xE5, 0x29, 0x25, 0xDF, 0xE1, 0x7B, 0x37, 0xF9, 0x5D, 0x22, 0xBC, 0xA5, 0x4F, 0x47, 0x59, + 0x19, 0xAC, 0x85, 0x90, 0x98, 0xC0, 0xF0, 0xD0, 0x8A, 0xC5, 0x87, 0x5E, 0xF2, 0x9B, 0x56, + 0xFD, 0x14, 0x1E, 0x6E, 0xF1, 0x5F, 0x70, 0x0A, 0x0B, 0x66, 0xF3, 0x95, 0x95, 0xC5, 0x88, + 0x17, 0x73, 0x73, 0xC4, 0x66, 0x9B, 0x21, 0xBC, 0x07, 0x1E, 0x4C, 0x3A, 0xA5, 0xF0, 0xB4, + 0xA3, 0x1B, 0x62, 0x58, 0xF3, 0x5D, 0xA2, 0x4A, 0xC3, 0xCD, 0x29, 0xC7, 0xF2, 0x09, 0x24, + 0x10, 0xC5, 0x07, 0x83, 0x55, 0xB1, 0x38, 0xFB, 0x53, 0xA6, 0xB9, 0xAE, 0x6E, 0x0B, 0x9C, + 0x08, 0x24, 0x3E, 0x7B, 0xAA, 0x45, 0xC4, 0x73, 0x76, 0xEB, 0x8C, 0x7F, 0x13, 0xD4, 0xCF, + 0x51, 0xAA, 0x73, 0x6F, 0xA3, 0x15, 0x40, 0xC9, 0x24, 0x1F, 0x37, 0x0D, 0xA5, 0x44, 0xBF, + 0x9F, 0x9C, 0x28, 0xD9, 0xA5, 0x7E, 0x2F, 0x2A, 0x7C, 0xA9, 0x5A, 0x4E, 0x4B, 0x46, 0x6E, + 0x64, 0x1A, 0xB3, 0xBC, 0xC7, 0x6A, 0xDF, 0x11, 0x39, 0xD5, 0x67, 0xA6, 0xF1, 0x2B, 0x52, + 0xF3, 0xA6, 0x5E, 0x7E, 0xC0, 0xAA, 0xE2, 0x6B, 0xCA, 0xA8, 0xC5, 0x58, 0x33, 0xB0, 0x4E, + 0x59, 0x99, 0x8E, 0xBC, 0x9A, 0x19, 0x30, 0xFB, 0xB6, 0xD2, 0x23, 0x3C, 0x53, 0xD2, 0xC1, + 0xF8, 0xB9, 0x51, 0x8E, 0x3C, 0x2D, 0xE7, 0x3A, 0x19, 0xDE, 0xE6, 0xB3, 0x80, 0xA5, 0xB3, + 0x29, 0x71, 0xCF, 0x64, 0xE1, 0x29, 0xFD, 0x6C, 0x1F, 0xA6, 0xE7, 0x5D, 0x4A, 0x23, 0x45, + 0x01, 0xE9, 0x66, 0xDD, 0x3A, 0x54, 0x0A, 0xF5, 0xC8, 0xF4, 0xF3, 0x4A, 0x6B, 0x4A, 0x25, + 0x3E, 0xE2, 0x84, 0x92, 0x56, 0x6D, 0x5E, 0x67, 0xC6, 0xF5, 0x58, 0x55, 0xFC, 0xB0, 0x50, + 0x6F, 0xB0, 0x6C, 0x15, 0x67, 0x44, 0xD9, 0xA0, 0x3A, 0x31, 0xA2, 0x6F, 0xA9, 0x4C, 0xAD, + 0x14, 0xF1, 0x57, 0xB7, 0xF3, 0x03, 0xD0, 0x7A, 0x69, 0xC7, 0x73, 0x76, 0x8F, 0xCB, 0x4D, + 0x07, 0x9C, 0x09, 0x05, 0x97, 0x03, 0xA0, 0xC3, 0xA9, 0x4D, 0xE4, 0xB9, 0x9E, 0xA3, 0xA2, + 0xF1, 0x65, 0x83, 0xD0, 0xF9, 0x17, 0x0A, 0x39, 0x50, 0xDB, 0x07, 0xB4, 0xF0, 0xBC, 0x30, + 0x80, 0x29, 0x27, 0xF9, 0xF7, 0x96, 0x1B, 0x62, 0x59, 0x89, 0x26, 0x36, 0xA9, 0x50, 0x2A, + 0x27, 0x05, 0x30, 0x36, 0x37, 0x79, 0x9D, 0xD3, 0x44, 0xDA, 0x45, 0x1C, 0x1C, 0xF7, 0xBF, + 0x67, 0x84, 0x0C, 0xEB, 0x30, 0x79, 0xAB, 0x8C, 0x6B, 0x8C, 0x19, 0x27, 0xF6, 0x40, 0x53, + 0xC6, 0x12, 0x45, 0x0C, 0x45, 0xC9, 0xE6, 0x03, 0xBC, 0x16, 0x66, 0x6E, 0x59, 0x6B, 0x34, + 0x71, 0xE1, 0x03, 0xB6, 0xF1, 0x54, 0x47, 0x42, 0x4D, 0x17, 0x02, 0x20, 0x48, 0x11, 0x1F, + 0xFB, 0xD3, 0x7E, 0x1C, 0x67, 0x0F, 0x64, 0xF1, 0x4B, 0x8A, 0x7B, 0x32, 0xB9, 0x4C, 0x1A, + 0x49, 0xB4, 0x5D, 0xD2, 0xFC, 0x38, 0xCD, 0x52, 0x89, 0xD9, 0x10, 0xAD, 0x63, 0x60, 0x2C, + 0xF5, 0xE1, 0x30, 0x42, 0xC6, 0x4A, 0xC6, 0x79, 0x7B, 0x89, 0xFB, 0x55, 0x1A, 0xD0, 0x8E, + 0x05, 0xA9, 0x2D, 0x20, 0x0C, 0xCC, 0xB7, 0xE7, 0x12, 0xEF, 0x23, 0xC9, 0x31, 0x2C, 0xB3, + 0x50, 0xF0, 0x29, 0xAB, 0x53, 0x7E, 0x28, 0x73, 0x47, 0xFD, 0x30, 0x75, 0xAC, 0x10, 0x90, + 0x6A, 0x78, 0x3F, 0x1C, 0x6C, 0x07, 0xCC, 0xB8, 0x8F, 0x41, 0x22, 0x8C, 0x4B, 0xE1, 0xC6, + 0x40, 0xF7, 0x90, 0xB5, 0xC3, 0xA5, 0xD5, 0xD3, 0xCA, 0x79, 0x24, 0x95, 0xD7, 0x4B, 0xC4, + 0x61, 0x56, 0x26, 0x58, 0xC0, 0x7A, 0xC6, 0x00, 0x27, 0x6B, 0x92, 0x4A, 0xB5, 0xBC, 0x9B, + 0xE1, 0xF0, 0x49, 0x4C, 0xB7, 0x6F, 0x82, 0xF4, 0x60, 0xA7, 0x48, 0x09, 0x72, 0x66, 0x33, + 0x81, 0xE1, 0x69, 0x99, 0x60, 0x61, 0xD7, 0x99, 0x85, 0x9E, 0xC5, 0x4D, 0x4F, 0x5C, 0xA5, + 0xC4, 0x11, 0xC0, 0x1D, 0xB1, 0x59, 0x7B, 0x16, 0x59, 0x77, 0x66, 0x9D, 0xE1, 0x3A, 0x92, + 0x8A, 0x34, 0xAF, 0xBA, 0xC2, 0x58, 0xFE, 0xA8, 0xC4, 0x76, 0x42, 0x39, 0xC9, 0x42, 0x1D, + 0xC3, 0x11, 0x9B, 0xF5, 0xB4, 0x76, 0x99, 0x20, 0x69, 0x78, 0x32, 0x7B, 0x1C, 0x53, 0x45, + 0xEF, 0x74, 0x6A, 0x79, 0x83, 0x84, 0x1F, 0x05, 0x6E, 0x25, 0x34, 0x10, 0x0A, 0xB2, 0x4D, + 0x4E, 0x9A, 0xBB, 0xD0, 0xB1, 0x7C, 0x6A, 0x95, 0xBD, 0x4C, 0x3C, 0x0E, 0x40, 0xF6, 0x9E, + 0x16, 0x12, 0xAC, 0xEE, 0xB2, 0x8B, 0x99, 0x08, 0x6C, 0x95, 0x11, 0x6E, 0x72, 0x04, 0x27, + 0x38, 0x93, 0x39, 0x0B, 0xF4, 0x6B, 0x89, 0x9B, 0x36, 0x28, 0x6B, 0x0E, 0xBF, 0x19, 0x47, + 0xBB, 0x98, 0x84, 0xF7, 0x32, 0xCA, 0x27, 0xDA, 0x82, 0xB1, 0x9B, 0x5D, 0xC0, 0xCC, 0x7F, + 0x88, 0x85, 0x71, 0x49, 0x10, 0x88, 0x8B, 0x23, 0x10, 0xC4, 0xF9, 0x31, 0x9D, 0x41, 0x0B, + 0x34, 0xE6, 0x43, 0x3B, 0x90, 0x03, 0xE2, 0x17, 0x6B, 0xB9, 0x95, 0x25, 0x74, 0x56, 0x10, + 0x6E, 0x89, 0x52, 0x16, 0x3B, 0x8B, 0xA5, 0x92, 0x53, 0x0C, 0xC5, 0xAA, 0x0A, 0xEB, 0x43, + 0xAD, 0x39, 0x8F, 0xE9, 0xE9, 0x7B, 0xAA, 0x52, 0x3D, 0x7A, 0x44, 0x31, 0x67, 0x7C, 0x3D, + 0x3A, 0xF0, 0x71, 0x9E, 0x47, 0x5D, 0xB8, 0x5C, 0xA9, 0x5A, 0xF5, 0x08, 0x9B, 0xEA, 0xBE, + 0xB0, 0x5B, 0x2F, 0xAA, 0xB4, 0x89, 0x6B, 0xA6, 0x0F, 0x81, 0xC8, 0x84, 0x72, 0xA5, 0x7B, + 0x46, 0xA8, 0x28, 0x82, 0x6A, 0x0C, 0xDF, 0xB4, 0x46, 0xF8, 0x18, 0x91, 0x82, 0xD2, 0xBF, + 0x5E, 0xAC, 0x4E, 0xC1, 0xCC, 0x5D, 0xEA, 0xF5, 0x99, 0xC8, 0xA1, 0x3E, 0x48, 0x23, 0x54, + 0x06, 0xD1, 0x7F, 0xFD, 0xDC, 0x83, 0x44, 0xB6, 0xC6, 0x69, 0x84, 0xA8, 0x68, 0xAA, 0x92, + 0xFA, 0x02, 0x22, 0x7A, 0x08, 0x69, 0x50, 0xEB, 0x0C, 0x87, 0x01, 0xED, 0x58, 0xDC, 0x62, + 0x87, 0x76, 0xB9, 0x83, 0x88, 0x2E, 0x11, 0x75, + ]; let pk = MLKEM1024PublicKey::from_bytes(&pk_bytes).unwrap(); let (ss, ct) = MLKEM1024::encaps(&pk).unwrap(); print!("{:x?}", ss); @@ -275,7 +727,7 @@ fn bench_mlkem1024_encaps() { } fn bench_mlkem1024_lowmemory_encaps() { - use bouncycastle::mlkem_lowmemory::{MLKEMTrait, MLKEM1024, MLKEM1024PublicKey}; + use bouncycastle::mlkem_lowmemory::{MLKEM1024, MLKEM1024PublicKey, MLKEMTrait}; eprintln!("MLKEM1024_lowmemory/Encaps"); @@ -289,7 +741,113 @@ fn bench_mlkem1024_lowmemory_encaps() { // use bouncycastle_hex as hex; // eprintln!("pk:\n{}", &hex::encode(pk.encode())); - let pk_bytes: [u8; MLKEM1024_PK_LEN] = [0x4b,0x94,0xc2,0x94,0x50,0x11,0x11,0x91,0x82,0x3b,0x35,0x14,0xc9,0xac,0x1e,0xa3,0xd9,0x82,0x5c,0xcb,0x86,0x39,0x3a,0x2d,0xfb,0x04,0x65,0x4f,0xa2,0x19,0x2d,0x37,0xbf,0xad,0x1c,0x49,0x7c,0x65,0x02,0xee,0xe5,0xca,0x80,0xa7,0x3b,0xfc,0xe0,0xba,0xf5,0xa5,0x4a,0x88,0x58,0x5a,0x40,0x13,0x97,0xa3,0xd2,0x32,0xf4,0x26,0xa7,0xaf,0xb0,0x82,0xbc,0x21,0xa4,0x43,0x17,0x09,0x0e,0xaa,0xc7,0x59,0x2c,0x2e,0xa8,0x8a,0x65,0x3c,0x44,0x91,0xea,0x19,0x39,0x31,0x33,0x5f,0x52,0xe9,0x89,0xa3,0xc4,0xcc,0x56,0xd9,0xc5,0x53,0x73,0x2d,0x57,0xc4,0x70,0xfb,0x41,0xab,0x75,0x9b,0x65,0xd2,0xd0,0x44,0x45,0x38,0x2f,0xcd,0x9c,0x4e,0x34,0x4a,0x11,0x28,0xfa,0x9e,0x11,0xe0,0x43,0x58,0xe1,0x92,0xed,0x01,0x4b,0x23,0x23,0x2a,0x7e,0xe2,0xb2,0x2e,0x23,0x71,0x7f,0x44,0x11,0x1e,0xe3,0x35,0x75,0x39,0x9c,0x37,0x64,0x6d,0xa9,0x81,0x3e,0xc9,0xb2,0x12,0xaf,0xe9,0x4e,0x5d,0xc5,0xc2,0x33,0x0a,0x72,0x94,0xcc,0x1f,0x42,0x34,0xa6,0xd3,0xfb,0xb4,0xf1,0x68,0x5a,0xb8,0x89,0x2c,0x04,0xac,0xb1,0x7c,0xd1,0xc1,0x70,0xd7,0xb0,0x61,0x1b,0x6a,0x71,0x76,0xc7,0x94,0xcc,0x8c,0x67,0xf5,0x5f,0xc9,0x23,0xc2,0xad,0x20,0x31,0x00,0xf3,0x65,0x99,0x18,0x82,0xc3,0x02,0x43,0xd7,0x78,0x13,0x84,0x3b,0x5e,0xc7,0xc9,0x64,0x03,0x22,0x63,0x70,0x60,0x92,0xec,0xf0,0x0c,0x75,0x16,0xbe,0x64,0xe4,0x59,0x8c,0xa4,0x22,0x6c,0x06,0x9b,0xb5,0xe6,0x7e,0x41,0x75,0xcf,0x22,0x86,0xc8,0xdd,0x5c,0x48,0x8a,0x6c,0x58,0x61,0xf3,0x1b,0xaa,0x0b,0xd0,0x26,0x94,0x70,0xe8,0xb5,0x51,0xdd,0x3b,0xcd,0x38,0xc8,0x6c,0x12,0xf9,0xcd,0xb1,0x76,0xc7,0x7d,0xc8,0xb6,0xc0,0x2a,0x70,0x1f,0x47,0x89,0x02,0xc8,0x55,0x3f,0x69,0x4c,0x0d,0x82,0x72,0x7b,0x4c,0x4a,0x5c,0x2c,0x10,0x41,0x21,0x2a,0xa1,0x27,0x48,0x08,0xb8,0x21,0x11,0xb3,0x77,0xec,0x75,0x21,0x4e,0x9b,0x19,0x78,0xf7,0x60,0x04,0xd4,0x13,0x9d,0x98,0x61,0x3f,0x4b,0x8e,0x98,0xd2,0x0a,0xf7,0xb5,0x34,0x07,0x3a,0x50,0x9a,0x95,0x9b,0x7a,0x75,0x64,0xf9,0xb4,0x0c,0xa2,0x18,0xbf,0x61,0x82,0x93,0x20,0xa8,0x50,0x20,0x17,0x95,0x4d,0x32,0x8d,0x7a,0xc6,0xc7,0x69,0xec,0x29,0x70,0x07,0x56,0xe7,0xb0,0x68,0x5b,0x34,0x0d,0x5e,0x11,0x80,0x59,0x50,0x4a,0x49,0xa9,0xa5,0x0a,0x10,0x19,0x8e,0xb1,0x0a,0x57,0x84,0x67,0x8e,0xb4,0x27,0xd7,0xb4,0xba,0xbb,0x95,0x52,0x93,0x3b,0x06,0x28,0x97,0x97,0x3e,0x13,0x18,0xea,0xf0,0xa0,0xea,0xc3,0x75,0x84,0xa6,0x54,0x01,0xb1,0x70,0x3e,0x04,0x2a,0xcc,0xd8,0x37,0x53,0x14,0x83,0xf2,0x41,0xca,0xdc,0xd1,0xc1,0xd3,0x78,0x11,0x9e,0x69,0x44,0x29,0xdb,0x19,0x9a,0xc8,0x91,0xe4,0xc5,0x34,0x37,0x57,0x08,0x5b,0xb3,0xae,0x78,0x36,0x67,0x35,0x0c,0x44,0x58,0xd9,0x76,0x72,0xe8,0x61,0xe8,0x0b,0x1d,0x26,0x79,0x51,0x0e,0xa3,0xa6,0xf2,0x36,0x0c,0x77,0xa4,0x69,0x42,0xc7,0xa0,0x6a,0x55,0x4d,0x22,0x80,0x80,0xc8,0x4b,0x47,0xae,0xf1,0x4d,0xb1,0x76,0x20,0xcb,0x16,0xc0,0x6a,0xb3,0x0a,0x1b,0xe4,0xcd,0xa7,0x08,0x2b,0xe9,0xf8,0x7e,0x9c,0x21,0x1c,0x46,0x91,0x63,0x49,0xa5,0xba,0x8e,0xaa,0x52,0x01,0xc7,0x29,0x4a,0x3c,0x08,0x85,0xb5,0x3b,0x65,0x74,0x52,0x10,0x88,0x25,0xec,0x64,0x6c,0x90,0xa0,0x46,0x12,0x32,0x4e,0xe7,0xd0,0x31,0xaf,0xe5,0x34,0x31,0x32,0xcb,0xef,0x67,0xb6,0xef,0xb1,0xa5,0xec,0x28,0x09,0xb7,0x73,0x53,0x8c,0xe7,0x7b,0x3d,0x8b,0x04,0xeb,0x0b,0x3c,0x22,0x56,0x01,0x1e,0x4c,0x71,0x6c,0x19,0xa8,0xba,0x07,0x52,0xbf,0x71,0x49,0x21,0x17,0x64,0x9f,0x06,0x15,0xc3,0x29,0x0f,0xc2,0x9a,0x46,0xfd,0xe4,0xbd,0x52,0xdb,0x92,0x86,0xd6,0x03,0x38,0x82,0x44,0x25,0x9c,0x15,0xa7,0xac,0x2b,0x64,0x0a,0x60,0xcc,0x03,0x37,0x6a,0x58,0x41,0xa3,0xfb,0x8a,0x47,0x35,0x68,0xfa,0x9b,0x1a,0x26,0x72,0x15,0xf3,0x4c,0x01,0x69,0x7b,0x0f,0x0e,0x62,0x71,0x75,0xd7,0x21,0x05,0xb7,0x70,0x7c,0x29,0xb9,0xe6,0x14,0xbd,0xc3,0x3a,0x6f,0x6c,0x81,0x8a,0x95,0x37,0x0b,0x42,0x78,0x82,0xd7,0xb4,0x76,0x79,0x6a,0x9e,0xc6,0xeb,0x99,0x32,0x74,0xcd,0x9b,0x23,0x91,0xa8,0x2b,0xa4,0x5e,0x33,0x93,0xd2,0xe9,0xae,0x97,0x21,0xca,0x9d,0x6c,0x1b,0x98,0x8b,0x58,0x27,0x71,0x3f,0x90,0xa6,0x58,0x5d,0xe9,0x43,0x35,0x28,0xc0,0x2b,0x03,0xce,0x10,0xbb,0x5f,0x72,0x01,0x38,0xd0,0xfb,0xb4,0xc3,0x0c,0x12,0x66,0xb9,0x18,0xe5,0x29,0x25,0xdf,0xe1,0x7b,0x37,0xf9,0x5d,0x22,0xbc,0xa5,0x4f,0x47,0x59,0x19,0xac,0x85,0x90,0x98,0xc0,0xf0,0xd0,0x8a,0xc5,0x87,0x5e,0xf2,0x9b,0x56,0xfd,0x14,0x1e,0x6e,0xf1,0x5f,0x70,0x0a,0x0b,0x66,0xf3,0x95,0x95,0xc5,0x88,0x17,0x73,0x73,0xc4,0x66,0x9b,0x21,0xbc,0x07,0x1e,0x4c,0x3a,0xa5,0xf0,0xb4,0xa3,0x1b,0x62,0x58,0xf3,0x5d,0xa2,0x4a,0xc3,0xcd,0x29,0xc7,0xf2,0x09,0x24,0x10,0xc5,0x07,0x83,0x55,0xb1,0x38,0xfb,0x53,0xa6,0xb9,0xae,0x6e,0x0b,0x9c,0x08,0x24,0x3e,0x7b,0xaa,0x45,0xc4,0x73,0x76,0xeb,0x8c,0x7f,0x13,0xd4,0xcf,0x51,0xaa,0x73,0x6f,0xa3,0x15,0x40,0xc9,0x24,0x1f,0x37,0x0d,0xa5,0x44,0xbf,0x9f,0x9c,0x28,0xd9,0xa5,0x7e,0x2f,0x2a,0x7c,0xa9,0x5a,0x4e,0x4b,0x46,0x6e,0x64,0x1a,0xb3,0xbc,0xc7,0x6a,0xdf,0x11,0x39,0xd5,0x67,0xa6,0xf1,0x2b,0x52,0xf3,0xa6,0x5e,0x7e,0xc0,0xaa,0xe2,0x6b,0xca,0xa8,0xc5,0x58,0x33,0xb0,0x4e,0x59,0x99,0x8e,0xbc,0x9a,0x19,0x30,0xfb,0xb6,0xd2,0x23,0x3c,0x53,0xd2,0xc1,0xf8,0xb9,0x51,0x8e,0x3c,0x2d,0xe7,0x3a,0x19,0xde,0xe6,0xb3,0x80,0xa5,0xb3,0x29,0x71,0xcf,0x64,0xe1,0x29,0xfd,0x6c,0x1f,0xa6,0xe7,0x5d,0x4a,0x23,0x45,0x01,0xe9,0x66,0xdd,0x3a,0x54,0x0a,0xf5,0xc8,0xf4,0xf3,0x4a,0x6b,0x4a,0x25,0x3e,0xe2,0x84,0x92,0x56,0x6d,0x5e,0x67,0xc6,0xf5,0x58,0x55,0xfc,0xb0,0x50,0x6f,0xb0,0x6c,0x15,0x67,0x44,0xd9,0xa0,0x3a,0x31,0xa2,0x6f,0xa9,0x4c,0xad,0x14,0xf1,0x57,0xb7,0xf3,0x03,0xd0,0x7a,0x69,0xc7,0x73,0x76,0x8f,0xcb,0x4d,0x07,0x9c,0x09,0x05,0x97,0x03,0xa0,0xc3,0xa9,0x4d,0xe4,0xb9,0x9e,0xa3,0xa2,0xf1,0x65,0x83,0xd0,0xf9,0x17,0x0a,0x39,0x50,0xdb,0x07,0xb4,0xf0,0xbc,0x30,0x80,0x29,0x27,0xf9,0xf7,0x96,0x1b,0x62,0x59,0x89,0x26,0x36,0xa9,0x50,0x2a,0x27,0x05,0x30,0x36,0x37,0x79,0x9d,0xd3,0x44,0xda,0x45,0x1c,0x1c,0xf7,0xbf,0x67,0x84,0x0c,0xeb,0x30,0x79,0xab,0x8c,0x6b,0x8c,0x19,0x27,0xf6,0x40,0x53,0xc6,0x12,0x45,0x0c,0x45,0xc9,0xe6,0x03,0xbc,0x16,0x66,0x6e,0x59,0x6b,0x34,0x71,0xe1,0x03,0xb6,0xf1,0x54,0x47,0x42,0x4d,0x17,0x02,0x20,0x48,0x11,0x1f,0xfb,0xd3,0x7e,0x1c,0x67,0x0f,0x64,0xf1,0x4b,0x8a,0x7b,0x32,0xb9,0x4c,0x1a,0x49,0xb4,0x5d,0xd2,0xfc,0x38,0xcd,0x52,0x89,0xd9,0x10,0xad,0x63,0x60,0x2c,0xf5,0xe1,0x30,0x42,0xc6,0x4a,0xc6,0x79,0x7b,0x89,0xfb,0x55,0x1a,0xd0,0x8e,0x05,0xa9,0x2d,0x20,0x0c,0xcc,0xb7,0xe7,0x12,0xef,0x23,0xc9,0x31,0x2c,0xb3,0x50,0xf0,0x29,0xab,0x53,0x7e,0x28,0x73,0x47,0xfd,0x30,0x75,0xac,0x10,0x90,0x6a,0x78,0x3f,0x1c,0x6c,0x07,0xcc,0xb8,0x8f,0x41,0x22,0x8c,0x4b,0xe1,0xc6,0x40,0xf7,0x90,0xb5,0xc3,0xa5,0xd5,0xd3,0xca,0x79,0x24,0x95,0xd7,0x4b,0xc4,0x61,0x56,0x26,0x58,0xc0,0x7a,0xc6,0x00,0x27,0x6b,0x92,0x4a,0xb5,0xbc,0x9b,0xe1,0xf0,0x49,0x4c,0xb7,0x6f,0x82,0xf4,0x60,0xa7,0x48,0x09,0x72,0x66,0x33,0x81,0xe1,0x69,0x99,0x60,0x61,0xd7,0x99,0x85,0x9e,0xc5,0x4d,0x4f,0x5c,0xa5,0xc4,0x11,0xc0,0x1d,0xb1,0x59,0x7b,0x16,0x59,0x77,0x66,0x9d,0xe1,0x3a,0x92,0x8a,0x34,0xaf,0xba,0xc2,0x58,0xfe,0xa8,0xc4,0x76,0x42,0x39,0xc9,0x42,0x1d,0xc3,0x11,0x9b,0xf5,0xb4,0x76,0x99,0x20,0x69,0x78,0x32,0x7b,0x1c,0x53,0x45,0xef,0x74,0x6a,0x79,0x83,0x84,0x1f,0x05,0x6e,0x25,0x34,0x10,0x0a,0xb2,0x4d,0x4e,0x9a,0xbb,0xd0,0xb1,0x7c,0x6a,0x95,0xbd,0x4c,0x3c,0x0e,0x40,0xf6,0x9e,0x16,0x12,0xac,0xee,0xb2,0x8b,0x99,0x08,0x6c,0x95,0x11,0x6e,0x72,0x04,0x27,0x38,0x93,0x39,0x0b,0xf4,0x6b,0x89,0x9b,0x36,0x28,0x6b,0x0e,0xbf,0x19,0x47,0xbb,0x98,0x84,0xf7,0x32,0xca,0x27,0xda,0x82,0xb1,0x9b,0x5d,0xc0,0xcc,0x7f,0x88,0x85,0x71,0x49,0x10,0x88,0x8b,0x23,0x10,0xc4,0xf9,0x31,0x9d,0x41,0x0b,0x34,0xe6,0x43,0x3b,0x90,0x03,0xe2,0x17,0x6b,0xb9,0x95,0x25,0x74,0x56,0x10,0x6e,0x89,0x52,0x16,0x3b,0x8b,0xa5,0x92,0x53,0x0c,0xc5,0xaa,0x0a,0xeb,0x43,0xad,0x39,0x8f,0xe9,0xe9,0x7b,0xaa,0x52,0x3d,0x7a,0x44,0x31,0x67,0x7c,0x3d,0x3a,0xf0,0x71,0x9e,0x47,0x5d,0xb8,0x5c,0xa9,0x5a,0xf5,0x08,0x9b,0xea,0xbe,0xb0,0x5b,0x2f,0xaa,0xb4,0x89,0x6b,0xa6,0x0f,0x81,0xc8,0x84,0x72,0xa5,0x7b,0x46,0xa8,0x28,0x82,0x6a,0x0c,0xdf,0xb4,0x46,0xf8,0x18,0x91,0x82,0xd2,0xbf,0x5e,0xac,0x4e,0xc1,0xcc,0x5d,0xea,0xf5,0x99,0xc8,0xa1,0x3e,0x48,0x23,0x54,0x06,0xd1,0x7f,0xfd,0xdc,0x83,0x44,0xb6,0xc6,0x69,0x84,0xa8,0x68,0xaa,0x92,0xfa,0x02,0x22,0x7a,0x08,0x69,0x50,0xeb,0x0c,0x87,0x01,0xed,0x58,0xdc,0x62,0x87,0x76,0xb9,0x83,0x88,0x2e,0x11,0x75]; + let pk_bytes: [u8; MLKEM1024_PK_LEN] = [ + 0x4B, 0x94, 0xC2, 0x94, 0x50, 0x11, 0x11, 0x91, 0x82, 0x3B, 0x35, 0x14, 0xC9, 0xAC, 0x1E, + 0xA3, 0xD9, 0x82, 0x5C, 0xCB, 0x86, 0x39, 0x3A, 0x2D, 0xFB, 0x04, 0x65, 0x4F, 0xA2, 0x19, + 0x2D, 0x37, 0xBF, 0xAD, 0x1C, 0x49, 0x7C, 0x65, 0x02, 0xEE, 0xE5, 0xCA, 0x80, 0xA7, 0x3B, + 0xFC, 0xE0, 0xBA, 0xF5, 0xA5, 0x4A, 0x88, 0x58, 0x5A, 0x40, 0x13, 0x97, 0xA3, 0xD2, 0x32, + 0xF4, 0x26, 0xA7, 0xAF, 0xB0, 0x82, 0xBC, 0x21, 0xA4, 0x43, 0x17, 0x09, 0x0E, 0xAA, 0xC7, + 0x59, 0x2C, 0x2E, 0xA8, 0x8A, 0x65, 0x3C, 0x44, 0x91, 0xEA, 0x19, 0x39, 0x31, 0x33, 0x5F, + 0x52, 0xE9, 0x89, 0xA3, 0xC4, 0xCC, 0x56, 0xD9, 0xC5, 0x53, 0x73, 0x2D, 0x57, 0xC4, 0x70, + 0xFB, 0x41, 0xAB, 0x75, 0x9B, 0x65, 0xD2, 0xD0, 0x44, 0x45, 0x38, 0x2F, 0xCD, 0x9C, 0x4E, + 0x34, 0x4A, 0x11, 0x28, 0xFA, 0x9E, 0x11, 0xE0, 0x43, 0x58, 0xE1, 0x92, 0xED, 0x01, 0x4B, + 0x23, 0x23, 0x2A, 0x7E, 0xE2, 0xB2, 0x2E, 0x23, 0x71, 0x7F, 0x44, 0x11, 0x1E, 0xE3, 0x35, + 0x75, 0x39, 0x9C, 0x37, 0x64, 0x6D, 0xA9, 0x81, 0x3E, 0xC9, 0xB2, 0x12, 0xAF, 0xE9, 0x4E, + 0x5D, 0xC5, 0xC2, 0x33, 0x0A, 0x72, 0x94, 0xCC, 0x1F, 0x42, 0x34, 0xA6, 0xD3, 0xFB, 0xB4, + 0xF1, 0x68, 0x5A, 0xB8, 0x89, 0x2C, 0x04, 0xAC, 0xB1, 0x7C, 0xD1, 0xC1, 0x70, 0xD7, 0xB0, + 0x61, 0x1B, 0x6A, 0x71, 0x76, 0xC7, 0x94, 0xCC, 0x8C, 0x67, 0xF5, 0x5F, 0xC9, 0x23, 0xC2, + 0xAD, 0x20, 0x31, 0x00, 0xF3, 0x65, 0x99, 0x18, 0x82, 0xC3, 0x02, 0x43, 0xD7, 0x78, 0x13, + 0x84, 0x3B, 0x5E, 0xC7, 0xC9, 0x64, 0x03, 0x22, 0x63, 0x70, 0x60, 0x92, 0xEC, 0xF0, 0x0C, + 0x75, 0x16, 0xBE, 0x64, 0xE4, 0x59, 0x8C, 0xA4, 0x22, 0x6C, 0x06, 0x9B, 0xB5, 0xE6, 0x7E, + 0x41, 0x75, 0xCF, 0x22, 0x86, 0xC8, 0xDD, 0x5C, 0x48, 0x8A, 0x6C, 0x58, 0x61, 0xF3, 0x1B, + 0xAA, 0x0B, 0xD0, 0x26, 0x94, 0x70, 0xE8, 0xB5, 0x51, 0xDD, 0x3B, 0xCD, 0x38, 0xC8, 0x6C, + 0x12, 0xF9, 0xCD, 0xB1, 0x76, 0xC7, 0x7D, 0xC8, 0xB6, 0xC0, 0x2A, 0x70, 0x1F, 0x47, 0x89, + 0x02, 0xC8, 0x55, 0x3F, 0x69, 0x4C, 0x0D, 0x82, 0x72, 0x7B, 0x4C, 0x4A, 0x5C, 0x2C, 0x10, + 0x41, 0x21, 0x2A, 0xA1, 0x27, 0x48, 0x08, 0xB8, 0x21, 0x11, 0xB3, 0x77, 0xEC, 0x75, 0x21, + 0x4E, 0x9B, 0x19, 0x78, 0xF7, 0x60, 0x04, 0xD4, 0x13, 0x9D, 0x98, 0x61, 0x3F, 0x4B, 0x8E, + 0x98, 0xD2, 0x0A, 0xF7, 0xB5, 0x34, 0x07, 0x3A, 0x50, 0x9A, 0x95, 0x9B, 0x7A, 0x75, 0x64, + 0xF9, 0xB4, 0x0C, 0xA2, 0x18, 0xBF, 0x61, 0x82, 0x93, 0x20, 0xA8, 0x50, 0x20, 0x17, 0x95, + 0x4D, 0x32, 0x8D, 0x7A, 0xC6, 0xC7, 0x69, 0xEC, 0x29, 0x70, 0x07, 0x56, 0xE7, 0xB0, 0x68, + 0x5B, 0x34, 0x0D, 0x5E, 0x11, 0x80, 0x59, 0x50, 0x4A, 0x49, 0xA9, 0xA5, 0x0A, 0x10, 0x19, + 0x8E, 0xB1, 0x0A, 0x57, 0x84, 0x67, 0x8E, 0xB4, 0x27, 0xD7, 0xB4, 0xBA, 0xBB, 0x95, 0x52, + 0x93, 0x3B, 0x06, 0x28, 0x97, 0x97, 0x3E, 0x13, 0x18, 0xEA, 0xF0, 0xA0, 0xEA, 0xC3, 0x75, + 0x84, 0xA6, 0x54, 0x01, 0xB1, 0x70, 0x3E, 0x04, 0x2A, 0xCC, 0xD8, 0x37, 0x53, 0x14, 0x83, + 0xF2, 0x41, 0xCA, 0xDC, 0xD1, 0xC1, 0xD3, 0x78, 0x11, 0x9E, 0x69, 0x44, 0x29, 0xDB, 0x19, + 0x9A, 0xC8, 0x91, 0xE4, 0xC5, 0x34, 0x37, 0x57, 0x08, 0x5B, 0xB3, 0xAE, 0x78, 0x36, 0x67, + 0x35, 0x0C, 0x44, 0x58, 0xD9, 0x76, 0x72, 0xE8, 0x61, 0xE8, 0x0B, 0x1D, 0x26, 0x79, 0x51, + 0x0E, 0xA3, 0xA6, 0xF2, 0x36, 0x0C, 0x77, 0xA4, 0x69, 0x42, 0xC7, 0xA0, 0x6A, 0x55, 0x4D, + 0x22, 0x80, 0x80, 0xC8, 0x4B, 0x47, 0xAE, 0xF1, 0x4D, 0xB1, 0x76, 0x20, 0xCB, 0x16, 0xC0, + 0x6A, 0xB3, 0x0A, 0x1B, 0xE4, 0xCD, 0xA7, 0x08, 0x2B, 0xE9, 0xF8, 0x7E, 0x9C, 0x21, 0x1C, + 0x46, 0x91, 0x63, 0x49, 0xA5, 0xBA, 0x8E, 0xAA, 0x52, 0x01, 0xC7, 0x29, 0x4A, 0x3C, 0x08, + 0x85, 0xB5, 0x3B, 0x65, 0x74, 0x52, 0x10, 0x88, 0x25, 0xEC, 0x64, 0x6C, 0x90, 0xA0, 0x46, + 0x12, 0x32, 0x4E, 0xE7, 0xD0, 0x31, 0xAF, 0xE5, 0x34, 0x31, 0x32, 0xCB, 0xEF, 0x67, 0xB6, + 0xEF, 0xB1, 0xA5, 0xEC, 0x28, 0x09, 0xB7, 0x73, 0x53, 0x8C, 0xE7, 0x7B, 0x3D, 0x8B, 0x04, + 0xEB, 0x0B, 0x3C, 0x22, 0x56, 0x01, 0x1E, 0x4C, 0x71, 0x6C, 0x19, 0xA8, 0xBA, 0x07, 0x52, + 0xBF, 0x71, 0x49, 0x21, 0x17, 0x64, 0x9F, 0x06, 0x15, 0xC3, 0x29, 0x0F, 0xC2, 0x9A, 0x46, + 0xFD, 0xE4, 0xBD, 0x52, 0xDB, 0x92, 0x86, 0xD6, 0x03, 0x38, 0x82, 0x44, 0x25, 0x9C, 0x15, + 0xA7, 0xAC, 0x2B, 0x64, 0x0A, 0x60, 0xCC, 0x03, 0x37, 0x6A, 0x58, 0x41, 0xA3, 0xFB, 0x8A, + 0x47, 0x35, 0x68, 0xFA, 0x9B, 0x1A, 0x26, 0x72, 0x15, 0xF3, 0x4C, 0x01, 0x69, 0x7B, 0x0F, + 0x0E, 0x62, 0x71, 0x75, 0xD7, 0x21, 0x05, 0xB7, 0x70, 0x7C, 0x29, 0xB9, 0xE6, 0x14, 0xBD, + 0xC3, 0x3A, 0x6F, 0x6C, 0x81, 0x8A, 0x95, 0x37, 0x0B, 0x42, 0x78, 0x82, 0xD7, 0xB4, 0x76, + 0x79, 0x6A, 0x9E, 0xC6, 0xEB, 0x99, 0x32, 0x74, 0xCD, 0x9B, 0x23, 0x91, 0xA8, 0x2B, 0xA4, + 0x5E, 0x33, 0x93, 0xD2, 0xE9, 0xAE, 0x97, 0x21, 0xCA, 0x9D, 0x6C, 0x1B, 0x98, 0x8B, 0x58, + 0x27, 0x71, 0x3F, 0x90, 0xA6, 0x58, 0x5D, 0xE9, 0x43, 0x35, 0x28, 0xC0, 0x2B, 0x03, 0xCE, + 0x10, 0xBB, 0x5F, 0x72, 0x01, 0x38, 0xD0, 0xFB, 0xB4, 0xC3, 0x0C, 0x12, 0x66, 0xB9, 0x18, + 0xE5, 0x29, 0x25, 0xDF, 0xE1, 0x7B, 0x37, 0xF9, 0x5D, 0x22, 0xBC, 0xA5, 0x4F, 0x47, 0x59, + 0x19, 0xAC, 0x85, 0x90, 0x98, 0xC0, 0xF0, 0xD0, 0x8A, 0xC5, 0x87, 0x5E, 0xF2, 0x9B, 0x56, + 0xFD, 0x14, 0x1E, 0x6E, 0xF1, 0x5F, 0x70, 0x0A, 0x0B, 0x66, 0xF3, 0x95, 0x95, 0xC5, 0x88, + 0x17, 0x73, 0x73, 0xC4, 0x66, 0x9B, 0x21, 0xBC, 0x07, 0x1E, 0x4C, 0x3A, 0xA5, 0xF0, 0xB4, + 0xA3, 0x1B, 0x62, 0x58, 0xF3, 0x5D, 0xA2, 0x4A, 0xC3, 0xCD, 0x29, 0xC7, 0xF2, 0x09, 0x24, + 0x10, 0xC5, 0x07, 0x83, 0x55, 0xB1, 0x38, 0xFB, 0x53, 0xA6, 0xB9, 0xAE, 0x6E, 0x0B, 0x9C, + 0x08, 0x24, 0x3E, 0x7B, 0xAA, 0x45, 0xC4, 0x73, 0x76, 0xEB, 0x8C, 0x7F, 0x13, 0xD4, 0xCF, + 0x51, 0xAA, 0x73, 0x6F, 0xA3, 0x15, 0x40, 0xC9, 0x24, 0x1F, 0x37, 0x0D, 0xA5, 0x44, 0xBF, + 0x9F, 0x9C, 0x28, 0xD9, 0xA5, 0x7E, 0x2F, 0x2A, 0x7C, 0xA9, 0x5A, 0x4E, 0x4B, 0x46, 0x6E, + 0x64, 0x1A, 0xB3, 0xBC, 0xC7, 0x6A, 0xDF, 0x11, 0x39, 0xD5, 0x67, 0xA6, 0xF1, 0x2B, 0x52, + 0xF3, 0xA6, 0x5E, 0x7E, 0xC0, 0xAA, 0xE2, 0x6B, 0xCA, 0xA8, 0xC5, 0x58, 0x33, 0xB0, 0x4E, + 0x59, 0x99, 0x8E, 0xBC, 0x9A, 0x19, 0x30, 0xFB, 0xB6, 0xD2, 0x23, 0x3C, 0x53, 0xD2, 0xC1, + 0xF8, 0xB9, 0x51, 0x8E, 0x3C, 0x2D, 0xE7, 0x3A, 0x19, 0xDE, 0xE6, 0xB3, 0x80, 0xA5, 0xB3, + 0x29, 0x71, 0xCF, 0x64, 0xE1, 0x29, 0xFD, 0x6C, 0x1F, 0xA6, 0xE7, 0x5D, 0x4A, 0x23, 0x45, + 0x01, 0xE9, 0x66, 0xDD, 0x3A, 0x54, 0x0A, 0xF5, 0xC8, 0xF4, 0xF3, 0x4A, 0x6B, 0x4A, 0x25, + 0x3E, 0xE2, 0x84, 0x92, 0x56, 0x6D, 0x5E, 0x67, 0xC6, 0xF5, 0x58, 0x55, 0xFC, 0xB0, 0x50, + 0x6F, 0xB0, 0x6C, 0x15, 0x67, 0x44, 0xD9, 0xA0, 0x3A, 0x31, 0xA2, 0x6F, 0xA9, 0x4C, 0xAD, + 0x14, 0xF1, 0x57, 0xB7, 0xF3, 0x03, 0xD0, 0x7A, 0x69, 0xC7, 0x73, 0x76, 0x8F, 0xCB, 0x4D, + 0x07, 0x9C, 0x09, 0x05, 0x97, 0x03, 0xA0, 0xC3, 0xA9, 0x4D, 0xE4, 0xB9, 0x9E, 0xA3, 0xA2, + 0xF1, 0x65, 0x83, 0xD0, 0xF9, 0x17, 0x0A, 0x39, 0x50, 0xDB, 0x07, 0xB4, 0xF0, 0xBC, 0x30, + 0x80, 0x29, 0x27, 0xF9, 0xF7, 0x96, 0x1B, 0x62, 0x59, 0x89, 0x26, 0x36, 0xA9, 0x50, 0x2A, + 0x27, 0x05, 0x30, 0x36, 0x37, 0x79, 0x9D, 0xD3, 0x44, 0xDA, 0x45, 0x1C, 0x1C, 0xF7, 0xBF, + 0x67, 0x84, 0x0C, 0xEB, 0x30, 0x79, 0xAB, 0x8C, 0x6B, 0x8C, 0x19, 0x27, 0xF6, 0x40, 0x53, + 0xC6, 0x12, 0x45, 0x0C, 0x45, 0xC9, 0xE6, 0x03, 0xBC, 0x16, 0x66, 0x6E, 0x59, 0x6B, 0x34, + 0x71, 0xE1, 0x03, 0xB6, 0xF1, 0x54, 0x47, 0x42, 0x4D, 0x17, 0x02, 0x20, 0x48, 0x11, 0x1F, + 0xFB, 0xD3, 0x7E, 0x1C, 0x67, 0x0F, 0x64, 0xF1, 0x4B, 0x8A, 0x7B, 0x32, 0xB9, 0x4C, 0x1A, + 0x49, 0xB4, 0x5D, 0xD2, 0xFC, 0x38, 0xCD, 0x52, 0x89, 0xD9, 0x10, 0xAD, 0x63, 0x60, 0x2C, + 0xF5, 0xE1, 0x30, 0x42, 0xC6, 0x4A, 0xC6, 0x79, 0x7B, 0x89, 0xFB, 0x55, 0x1A, 0xD0, 0x8E, + 0x05, 0xA9, 0x2D, 0x20, 0x0C, 0xCC, 0xB7, 0xE7, 0x12, 0xEF, 0x23, 0xC9, 0x31, 0x2C, 0xB3, + 0x50, 0xF0, 0x29, 0xAB, 0x53, 0x7E, 0x28, 0x73, 0x47, 0xFD, 0x30, 0x75, 0xAC, 0x10, 0x90, + 0x6A, 0x78, 0x3F, 0x1C, 0x6C, 0x07, 0xCC, 0xB8, 0x8F, 0x41, 0x22, 0x8C, 0x4B, 0xE1, 0xC6, + 0x40, 0xF7, 0x90, 0xB5, 0xC3, 0xA5, 0xD5, 0xD3, 0xCA, 0x79, 0x24, 0x95, 0xD7, 0x4B, 0xC4, + 0x61, 0x56, 0x26, 0x58, 0xC0, 0x7A, 0xC6, 0x00, 0x27, 0x6B, 0x92, 0x4A, 0xB5, 0xBC, 0x9B, + 0xE1, 0xF0, 0x49, 0x4C, 0xB7, 0x6F, 0x82, 0xF4, 0x60, 0xA7, 0x48, 0x09, 0x72, 0x66, 0x33, + 0x81, 0xE1, 0x69, 0x99, 0x60, 0x61, 0xD7, 0x99, 0x85, 0x9E, 0xC5, 0x4D, 0x4F, 0x5C, 0xA5, + 0xC4, 0x11, 0xC0, 0x1D, 0xB1, 0x59, 0x7B, 0x16, 0x59, 0x77, 0x66, 0x9D, 0xE1, 0x3A, 0x92, + 0x8A, 0x34, 0xAF, 0xBA, 0xC2, 0x58, 0xFE, 0xA8, 0xC4, 0x76, 0x42, 0x39, 0xC9, 0x42, 0x1D, + 0xC3, 0x11, 0x9B, 0xF5, 0xB4, 0x76, 0x99, 0x20, 0x69, 0x78, 0x32, 0x7B, 0x1C, 0x53, 0x45, + 0xEF, 0x74, 0x6A, 0x79, 0x83, 0x84, 0x1F, 0x05, 0x6E, 0x25, 0x34, 0x10, 0x0A, 0xB2, 0x4D, + 0x4E, 0x9A, 0xBB, 0xD0, 0xB1, 0x7C, 0x6A, 0x95, 0xBD, 0x4C, 0x3C, 0x0E, 0x40, 0xF6, 0x9E, + 0x16, 0x12, 0xAC, 0xEE, 0xB2, 0x8B, 0x99, 0x08, 0x6C, 0x95, 0x11, 0x6E, 0x72, 0x04, 0x27, + 0x38, 0x93, 0x39, 0x0B, 0xF4, 0x6B, 0x89, 0x9B, 0x36, 0x28, 0x6B, 0x0E, 0xBF, 0x19, 0x47, + 0xBB, 0x98, 0x84, 0xF7, 0x32, 0xCA, 0x27, 0xDA, 0x82, 0xB1, 0x9B, 0x5D, 0xC0, 0xCC, 0x7F, + 0x88, 0x85, 0x71, 0x49, 0x10, 0x88, 0x8B, 0x23, 0x10, 0xC4, 0xF9, 0x31, 0x9D, 0x41, 0x0B, + 0x34, 0xE6, 0x43, 0x3B, 0x90, 0x03, 0xE2, 0x17, 0x6B, 0xB9, 0x95, 0x25, 0x74, 0x56, 0x10, + 0x6E, 0x89, 0x52, 0x16, 0x3B, 0x8B, 0xA5, 0x92, 0x53, 0x0C, 0xC5, 0xAA, 0x0A, 0xEB, 0x43, + 0xAD, 0x39, 0x8F, 0xE9, 0xE9, 0x7B, 0xAA, 0x52, 0x3D, 0x7A, 0x44, 0x31, 0x67, 0x7C, 0x3D, + 0x3A, 0xF0, 0x71, 0x9E, 0x47, 0x5D, 0xB8, 0x5C, 0xA9, 0x5A, 0xF5, 0x08, 0x9B, 0xEA, 0xBE, + 0xB0, 0x5B, 0x2F, 0xAA, 0xB4, 0x89, 0x6B, 0xA6, 0x0F, 0x81, 0xC8, 0x84, 0x72, 0xA5, 0x7B, + 0x46, 0xA8, 0x28, 0x82, 0x6A, 0x0C, 0xDF, 0xB4, 0x46, 0xF8, 0x18, 0x91, 0x82, 0xD2, 0xBF, + 0x5E, 0xAC, 0x4E, 0xC1, 0xCC, 0x5D, 0xEA, 0xF5, 0x99, 0xC8, 0xA1, 0x3E, 0x48, 0x23, 0x54, + 0x06, 0xD1, 0x7F, 0xFD, 0xDC, 0x83, 0x44, 0xB6, 0xC6, 0x69, 0x84, 0xA8, 0x68, 0xAA, 0x92, + 0xFA, 0x02, 0x22, 0x7A, 0x08, 0x69, 0x50, 0xEB, 0x0C, 0x87, 0x01, 0xED, 0x58, 0xDC, 0x62, + 0x87, 0x76, 0xB9, 0x83, 0x88, 0x2E, 0x11, 0x75, + ]; let pk = MLKEM1024PublicKey::from_bytes(&pk_bytes).unwrap(); let (ss, ct) = MLKEM1024::encaps(&pk).unwrap(); print!("{:x?}", ss); @@ -297,14 +855,21 @@ fn bench_mlkem1024_lowmemory_encaps() { } fn bench_mlkem512_decaps() { - use bouncycastle::mlkem::{MLKEMTrait, MLKEM512}; + use bouncycastle::mlkem::{MLKEM512, MLKEMTrait}; eprintln!("MLKEM512/Decaps"); let seed = KeyMaterial512::from_bytes_as_type( - &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ], KeyType::Seed, - ).unwrap(); + ) + .unwrap(); /* One-time setup of the KAT -- commented out so that we're not capturing keygen in the bench */ // let (pk, _sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); @@ -312,7 +877,60 @@ fn bench_mlkem512_decaps() { // use bouncycastle_hex as hex; // eprintln!("ct:\n{}", &hex::encode(ct)); - let ct: [u8; MLKEM512_CT_LEN] = [0x5a,0x68,0x40,0x8e,0xeb,0x0e,0xe7,0xd1,0xf5,0x11,0x4f,0x4b,0xed,0xae,0xb6,0x00,0x48,0xf5,0x39,0x7e,0xea,0x20,0xca,0x22,0x89,0xe5,0xb2,0xb1,0xc7,0x01,0x65,0x49,0xac,0x72,0x8d,0xb0,0x97,0x74,0xe1,0xc6,0x79,0x8c,0xd7,0xd1,0x93,0xbd,0x74,0x94,0x16,0xf3,0x75,0x2e,0x9d,0x75,0xbb,0x16,0x09,0x01,0xc6,0x39,0xab,0x39,0x41,0xb4,0xe2,0xb2,0xe5,0xa0,0x68,0x3d,0x49,0xcb,0xa9,0xbc,0xe2,0x07,0xf8,0x45,0x8f,0x9e,0xf9,0x54,0xce,0xbb,0xbf,0x15,0xb1,0x8a,0x14,0x8e,0x37,0x05,0xc6,0xb1,0x9b,0xba,0x2e,0x52,0x54,0x69,0x80,0x3d,0x1b,0x86,0x11,0xe7,0x43,0xc8,0x56,0x8b,0x9f,0x07,0x77,0x84,0x71,0xdd,0x0e,0x6c,0x3a,0x00,0x76,0x6c,0xfa,0xdf,0xf1,0x6d,0xf4,0xdb,0x94,0x9b,0x34,0xf0,0x86,0x07,0x06,0x30,0x3a,0x32,0xb6,0x2a,0x9b,0x9d,0x23,0x44,0x69,0x27,0x63,0x4d,0x02,0x45,0x9f,0x3b,0x69,0xbc,0x3b,0xd2,0xf1,0x2f,0x9f,0x66,0x00,0x92,0x10,0xcb,0xe9,0xdf,0xf1,0x1c,0xde,0x5e,0x63,0x3f,0x37,0xb4,0xdc,0xda,0xbe,0x97,0x93,0x0b,0x1b,0xce,0xe5,0x71,0xe9,0x55,0x49,0xe6,0xfd,0x25,0x54,0x98,0xcf,0x0d,0x75,0x4d,0xd2,0x5c,0x1d,0xda,0xe9,0x4f,0xa0,0x7c,0xed,0xc1,0x64,0x17,0xf5,0x51,0x3a,0xd3,0x5e,0x54,0xae,0x67,0xc6,0x4d,0x70,0x76,0x00,0x6d,0x8b,0x41,0x5b,0x8e,0xe8,0x2e,0x40,0xe0,0x4a,0xfb,0xea,0x24,0x37,0xe6,0x71,0xba,0xee,0x25,0x5c,0x9a,0x6c,0x86,0x60,0x8b,0xb7,0xa2,0x3f,0xc9,0xe7,0x11,0xeb,0x32,0x82,0x90,0x41,0x38,0xb3,0xf9,0x23,0x5d,0xd1,0x02,0x8b,0xe6,0xa5,0x6c,0xfc,0xa3,0x64,0xa6,0x57,0x0f,0xf8,0xde,0x67,0x19,0x2e,0x33,0x3e,0x34,0x56,0xf0,0xc9,0xc6,0x5f,0x77,0x1e,0x25,0x6a,0x59,0x09,0x88,0xdb,0x8b,0x56,0x09,0xf3,0x6c,0x14,0x0f,0x16,0x18,0x64,0x01,0x40,0x94,0xab,0x30,0x44,0xb0,0xa8,0x0b,0x37,0x3f,0x33,0x65,0x3b,0x0c,0x29,0xd5,0xb3,0x80,0xd9,0x72,0x7c,0xf2,0x32,0xc5,0x16,0x79,0x86,0x57,0x98,0x51,0xbb,0xcc,0xc8,0x22,0x88,0x28,0xd5,0xb2,0x58,0xb4,0xb0,0x26,0x7e,0xe6,0x65,0x86,0x07,0x5a,0x30,0x36,0xcc,0xcf,0x79,0xb5,0xbc,0xfa,0xb4,0x50,0x28,0x6a,0x6e,0x3d,0xee,0x31,0xae,0x7a,0x15,0x01,0xb1,0x94,0xe8,0xea,0x35,0x2a,0x6c,0x11,0x00,0x3e,0x87,0xdb,0xc6,0x94,0x1a,0x72,0x96,0x6f,0xd3,0x03,0x83,0x7c,0x42,0x16,0xcb,0x0d,0x36,0xa9,0xd6,0x95,0x9c,0xb1,0xe6,0x99,0xa7,0xe3,0x33,0xc4,0xe8,0xc6,0x9e,0xdd,0x77,0x15,0x8f,0x30,0xcc,0x67,0xf1,0x14,0x9f,0x29,0x33,0xa4,0x1f,0xd4,0xd3,0x75,0x85,0xff,0x62,0x59,0xa0,0x1d,0x96,0x60,0x01,0x05,0xf0,0x79,0xba,0x18,0x16,0x80,0x2c,0xc6,0xf0,0x25,0xfb,0xc2,0x08,0x86,0x69,0x3a,0x0a,0xb5,0x97,0x5b,0xa7,0x1c,0xe2,0xc5,0x38,0xf8,0xd2,0x0e,0x1b,0xa1,0x48,0x29,0x89,0x42,0x2e,0x5f,0xa1,0x11,0xf0,0x8b,0x2f,0x95,0xf1,0x33,0xe1,0xe1,0x72,0x46,0xc2,0x68,0xf8,0x3c,0x3e,0x90,0xfd,0xa6,0x9c,0x71,0x51,0xf1,0x60,0xa6,0xec,0xde,0x7a,0x96,0xea,0xd4,0x33,0xe4,0x05,0x1d,0xc1,0x1c,0x34,0x6f,0x35,0x76,0xef,0x10,0xae,0x7a,0xf4,0x83,0xd8,0xff,0xba,0xa8,0x5e,0x28,0x55,0x8b,0x09,0x3a,0x97,0xc9,0x65,0x2e,0x65,0x51,0xb8,0x13,0x9b,0xa1,0xbf,0x79,0xb7,0x4e,0x17,0x37,0x20,0xde,0x55,0xbb,0x44,0xd2,0x72,0xeb,0xff,0x67,0x79,0xcc,0x73,0xcb,0x4f,0xfd,0x5a,0x9c,0x02,0xed,0xcb,0xe2,0xb7,0x7e,0xe9,0xb7,0x3e,0x61,0xc6,0x9e,0x8b,0x97,0xf5,0xab,0xe9,0x39,0x60,0xd8,0x5b,0xab,0x28,0xf5,0x92,0x47,0x06,0xd0,0x6e,0xfc,0x98,0x12,0xfb,0x1c,0xdd,0xe3,0x17,0xa2,0x8e,0x0e,0x9a,0xae,0x83,0xf2,0x27,0xc3,0xab,0x15,0x11,0xca,0x14,0x15,0x12,0xec,0x37,0x42,0x58,0x59,0x9e,0x32,0xfc,0xf7,0xd3,0x35,0x7c,0x3d,0x40,0xe5,0x8f,0x92,0x6f,0xbf,0x80,0xe8,0x5c,0x62,0x63,0xf1,0x80,0xec,0x48,0x30,0xe7,0xc3,0x5f,0x8c,0xea,0x11,0xb4,0x23,0xa7,0x35,0xdb,0x47,0x1a,0x4b,0x69,0x98,0x2e,0x64,0x79,0x99,0x9c,0x3b,0x06,0x58,0x97,0x2d,0xb3,0x2a,0xff,0xdb,0x56,0xae,0x9d,0x49,0x83,0x43,0xe6,0x99,0xe9,0xea,0x22,0xa1,0xde,0x54,0x17,0xe5,0xaa,0xb4,0xbc,0x0a,0x99,0x9b,0xa8,0x6c,0x19,0xaa,0x8b,0x99,0x3a,0xa1,0x1d,0xdd,0x7e,0x7f,0xfb,0xed,0x4f,0xb7,0xa9,0x22,0x1f,0x0f,0xf9,0xa5,0x14,0x96,0x19,0x61,0xc5,0x48,0x38,0x9f,0x01,0x5d,0x30,0x77,0xc1,0x33,0x11,0x4e,0xee,0x5d,0x91,0x7b,0x51,0x5b,0x75,0x99,0x6d,0x52,0xdb,0x1c,0x03,0x74,0x41,0x77,0x13,0x39,0x86,0xe7,0xee,0x6c,0x77,0x1b,0xad,0x25]; + let ct: [u8; MLKEM512_CT_LEN] = [ + 0x5A, 0x68, 0x40, 0x8E, 0xEB, 0x0E, 0xE7, 0xD1, 0xF5, 0x11, 0x4F, 0x4B, 0xED, 0xAE, 0xB6, + 0x00, 0x48, 0xF5, 0x39, 0x7E, 0xEA, 0x20, 0xCA, 0x22, 0x89, 0xE5, 0xB2, 0xB1, 0xC7, 0x01, + 0x65, 0x49, 0xAC, 0x72, 0x8D, 0xB0, 0x97, 0x74, 0xE1, 0xC6, 0x79, 0x8C, 0xD7, 0xD1, 0x93, + 0xBD, 0x74, 0x94, 0x16, 0xF3, 0x75, 0x2E, 0x9D, 0x75, 0xBB, 0x16, 0x09, 0x01, 0xC6, 0x39, + 0xAB, 0x39, 0x41, 0xB4, 0xE2, 0xB2, 0xE5, 0xA0, 0x68, 0x3D, 0x49, 0xCB, 0xA9, 0xBC, 0xE2, + 0x07, 0xF8, 0x45, 0x8F, 0x9E, 0xF9, 0x54, 0xCE, 0xBB, 0xBF, 0x15, 0xB1, 0x8A, 0x14, 0x8E, + 0x37, 0x05, 0xC6, 0xB1, 0x9B, 0xBA, 0x2E, 0x52, 0x54, 0x69, 0x80, 0x3D, 0x1B, 0x86, 0x11, + 0xE7, 0x43, 0xC8, 0x56, 0x8B, 0x9F, 0x07, 0x77, 0x84, 0x71, 0xDD, 0x0E, 0x6C, 0x3A, 0x00, + 0x76, 0x6C, 0xFA, 0xDF, 0xF1, 0x6D, 0xF4, 0xDB, 0x94, 0x9B, 0x34, 0xF0, 0x86, 0x07, 0x06, + 0x30, 0x3A, 0x32, 0xB6, 0x2A, 0x9B, 0x9D, 0x23, 0x44, 0x69, 0x27, 0x63, 0x4D, 0x02, 0x45, + 0x9F, 0x3B, 0x69, 0xBC, 0x3B, 0xD2, 0xF1, 0x2F, 0x9F, 0x66, 0x00, 0x92, 0x10, 0xCB, 0xE9, + 0xDF, 0xF1, 0x1C, 0xDE, 0x5E, 0x63, 0x3F, 0x37, 0xB4, 0xDC, 0xDA, 0xBE, 0x97, 0x93, 0x0B, + 0x1B, 0xCE, 0xE5, 0x71, 0xE9, 0x55, 0x49, 0xE6, 0xFD, 0x25, 0x54, 0x98, 0xCF, 0x0D, 0x75, + 0x4D, 0xD2, 0x5C, 0x1D, 0xDA, 0xE9, 0x4F, 0xA0, 0x7C, 0xED, 0xC1, 0x64, 0x17, 0xF5, 0x51, + 0x3A, 0xD3, 0x5E, 0x54, 0xAE, 0x67, 0xC6, 0x4D, 0x70, 0x76, 0x00, 0x6D, 0x8B, 0x41, 0x5B, + 0x8E, 0xE8, 0x2E, 0x40, 0xE0, 0x4A, 0xFB, 0xEA, 0x24, 0x37, 0xE6, 0x71, 0xBA, 0xEE, 0x25, + 0x5C, 0x9A, 0x6C, 0x86, 0x60, 0x8B, 0xB7, 0xA2, 0x3F, 0xC9, 0xE7, 0x11, 0xEB, 0x32, 0x82, + 0x90, 0x41, 0x38, 0xB3, 0xF9, 0x23, 0x5D, 0xD1, 0x02, 0x8B, 0xE6, 0xA5, 0x6C, 0xFC, 0xA3, + 0x64, 0xA6, 0x57, 0x0F, 0xF8, 0xDE, 0x67, 0x19, 0x2E, 0x33, 0x3E, 0x34, 0x56, 0xF0, 0xC9, + 0xC6, 0x5F, 0x77, 0x1E, 0x25, 0x6A, 0x59, 0x09, 0x88, 0xDB, 0x8B, 0x56, 0x09, 0xF3, 0x6C, + 0x14, 0x0F, 0x16, 0x18, 0x64, 0x01, 0x40, 0x94, 0xAB, 0x30, 0x44, 0xB0, 0xA8, 0x0B, 0x37, + 0x3F, 0x33, 0x65, 0x3B, 0x0C, 0x29, 0xD5, 0xB3, 0x80, 0xD9, 0x72, 0x7C, 0xF2, 0x32, 0xC5, + 0x16, 0x79, 0x86, 0x57, 0x98, 0x51, 0xBB, 0xCC, 0xC8, 0x22, 0x88, 0x28, 0xD5, 0xB2, 0x58, + 0xB4, 0xB0, 0x26, 0x7E, 0xE6, 0x65, 0x86, 0x07, 0x5A, 0x30, 0x36, 0xCC, 0xCF, 0x79, 0xB5, + 0xBC, 0xFA, 0xB4, 0x50, 0x28, 0x6A, 0x6E, 0x3D, 0xEE, 0x31, 0xAE, 0x7A, 0x15, 0x01, 0xB1, + 0x94, 0xE8, 0xEA, 0x35, 0x2A, 0x6C, 0x11, 0x00, 0x3E, 0x87, 0xDB, 0xC6, 0x94, 0x1A, 0x72, + 0x96, 0x6F, 0xD3, 0x03, 0x83, 0x7C, 0x42, 0x16, 0xCB, 0x0D, 0x36, 0xA9, 0xD6, 0x95, 0x9C, + 0xB1, 0xE6, 0x99, 0xA7, 0xE3, 0x33, 0xC4, 0xE8, 0xC6, 0x9E, 0xDD, 0x77, 0x15, 0x8F, 0x30, + 0xCC, 0x67, 0xF1, 0x14, 0x9F, 0x29, 0x33, 0xA4, 0x1F, 0xD4, 0xD3, 0x75, 0x85, 0xFF, 0x62, + 0x59, 0xA0, 0x1D, 0x96, 0x60, 0x01, 0x05, 0xF0, 0x79, 0xBA, 0x18, 0x16, 0x80, 0x2C, 0xC6, + 0xF0, 0x25, 0xFB, 0xC2, 0x08, 0x86, 0x69, 0x3A, 0x0A, 0xB5, 0x97, 0x5B, 0xA7, 0x1C, 0xE2, + 0xC5, 0x38, 0xF8, 0xD2, 0x0E, 0x1B, 0xA1, 0x48, 0x29, 0x89, 0x42, 0x2E, 0x5F, 0xA1, 0x11, + 0xF0, 0x8B, 0x2F, 0x95, 0xF1, 0x33, 0xE1, 0xE1, 0x72, 0x46, 0xC2, 0x68, 0xF8, 0x3C, 0x3E, + 0x90, 0xFD, 0xA6, 0x9C, 0x71, 0x51, 0xF1, 0x60, 0xA6, 0xEC, 0xDE, 0x7A, 0x96, 0xEA, 0xD4, + 0x33, 0xE4, 0x05, 0x1D, 0xC1, 0x1C, 0x34, 0x6F, 0x35, 0x76, 0xEF, 0x10, 0xAE, 0x7A, 0xF4, + 0x83, 0xD8, 0xFF, 0xBA, 0xA8, 0x5E, 0x28, 0x55, 0x8B, 0x09, 0x3A, 0x97, 0xC9, 0x65, 0x2E, + 0x65, 0x51, 0xB8, 0x13, 0x9B, 0xA1, 0xBF, 0x79, 0xB7, 0x4E, 0x17, 0x37, 0x20, 0xDE, 0x55, + 0xBB, 0x44, 0xD2, 0x72, 0xEB, 0xFF, 0x67, 0x79, 0xCC, 0x73, 0xCB, 0x4F, 0xFD, 0x5A, 0x9C, + 0x02, 0xED, 0xCB, 0xE2, 0xB7, 0x7E, 0xE9, 0xB7, 0x3E, 0x61, 0xC6, 0x9E, 0x8B, 0x97, 0xF5, + 0xAB, 0xE9, 0x39, 0x60, 0xD8, 0x5B, 0xAB, 0x28, 0xF5, 0x92, 0x47, 0x06, 0xD0, 0x6E, 0xFC, + 0x98, 0x12, 0xFB, 0x1C, 0xDD, 0xE3, 0x17, 0xA2, 0x8E, 0x0E, 0x9A, 0xAE, 0x83, 0xF2, 0x27, + 0xC3, 0xAB, 0x15, 0x11, 0xCA, 0x14, 0x15, 0x12, 0xEC, 0x37, 0x42, 0x58, 0x59, 0x9E, 0x32, + 0xFC, 0xF7, 0xD3, 0x35, 0x7C, 0x3D, 0x40, 0xE5, 0x8F, 0x92, 0x6F, 0xBF, 0x80, 0xE8, 0x5C, + 0x62, 0x63, 0xF1, 0x80, 0xEC, 0x48, 0x30, 0xE7, 0xC3, 0x5F, 0x8C, 0xEA, 0x11, 0xB4, 0x23, + 0xA7, 0x35, 0xDB, 0x47, 0x1A, 0x4B, 0x69, 0x98, 0x2E, 0x64, 0x79, 0x99, 0x9C, 0x3B, 0x06, + 0x58, 0x97, 0x2D, 0xB3, 0x2A, 0xFF, 0xDB, 0x56, 0xAE, 0x9D, 0x49, 0x83, 0x43, 0xE6, 0x99, + 0xE9, 0xEA, 0x22, 0xA1, 0xDE, 0x54, 0x17, 0xE5, 0xAA, 0xB4, 0xBC, 0x0A, 0x99, 0x9B, 0xA8, + 0x6C, 0x19, 0xAA, 0x8B, 0x99, 0x3A, 0xA1, 0x1D, 0xDD, 0x7E, 0x7F, 0xFB, 0xED, 0x4F, 0xB7, + 0xA9, 0x22, 0x1F, 0x0F, 0xF9, 0xA5, 0x14, 0x96, 0x19, 0x61, 0xC5, 0x48, 0x38, 0x9F, 0x01, + 0x5D, 0x30, 0x77, 0xC1, 0x33, 0x11, 0x4E, 0xEE, 0x5D, 0x91, 0x7B, 0x51, 0x5B, 0x75, 0x99, + 0x6D, 0x52, 0xDB, 0x1C, 0x03, 0x74, 0x41, 0x77, 0x13, 0x39, 0x86, 0xE7, 0xEE, 0x6C, 0x77, + 0x1B, 0xAD, 0x25, + ]; let (_pk, sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); let ss = MLKEM512::decaps(&sk, &ct).unwrap(); @@ -320,14 +938,21 @@ fn bench_mlkem512_decaps() { } fn bench_mlkem512_lowmemory_decaps() { - use bouncycastle::mlkem_lowmemory::{MLKEMTrait, MLKEM512}; + use bouncycastle::mlkem_lowmemory::{MLKEM512, MLKEMTrait}; eprintln!("MLKEM512_lowmemory/Decaps"); let seed = KeyMaterial512::from_bytes_as_type( - &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ], KeyType::Seed, - ).unwrap(); + ) + .unwrap(); /* One-time setup of the KAT -- commented out so that we're not capturing keygen in the bench */ // let (pk, _sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); @@ -335,7 +960,60 @@ fn bench_mlkem512_lowmemory_decaps() { // use bouncycastle_hex as hex; // eprintln!("ct:\n{}", &hex::encode(ct)); - let ct: [u8; MLKEM512_CT_LEN] = [0x5a,0x68,0x40,0x8e,0xeb,0x0e,0xe7,0xd1,0xf5,0x11,0x4f,0x4b,0xed,0xae,0xb6,0x00,0x48,0xf5,0x39,0x7e,0xea,0x20,0xca,0x22,0x89,0xe5,0xb2,0xb1,0xc7,0x01,0x65,0x49,0xac,0x72,0x8d,0xb0,0x97,0x74,0xe1,0xc6,0x79,0x8c,0xd7,0xd1,0x93,0xbd,0x74,0x94,0x16,0xf3,0x75,0x2e,0x9d,0x75,0xbb,0x16,0x09,0x01,0xc6,0x39,0xab,0x39,0x41,0xb4,0xe2,0xb2,0xe5,0xa0,0x68,0x3d,0x49,0xcb,0xa9,0xbc,0xe2,0x07,0xf8,0x45,0x8f,0x9e,0xf9,0x54,0xce,0xbb,0xbf,0x15,0xb1,0x8a,0x14,0x8e,0x37,0x05,0xc6,0xb1,0x9b,0xba,0x2e,0x52,0x54,0x69,0x80,0x3d,0x1b,0x86,0x11,0xe7,0x43,0xc8,0x56,0x8b,0x9f,0x07,0x77,0x84,0x71,0xdd,0x0e,0x6c,0x3a,0x00,0x76,0x6c,0xfa,0xdf,0xf1,0x6d,0xf4,0xdb,0x94,0x9b,0x34,0xf0,0x86,0x07,0x06,0x30,0x3a,0x32,0xb6,0x2a,0x9b,0x9d,0x23,0x44,0x69,0x27,0x63,0x4d,0x02,0x45,0x9f,0x3b,0x69,0xbc,0x3b,0xd2,0xf1,0x2f,0x9f,0x66,0x00,0x92,0x10,0xcb,0xe9,0xdf,0xf1,0x1c,0xde,0x5e,0x63,0x3f,0x37,0xb4,0xdc,0xda,0xbe,0x97,0x93,0x0b,0x1b,0xce,0xe5,0x71,0xe9,0x55,0x49,0xe6,0xfd,0x25,0x54,0x98,0xcf,0x0d,0x75,0x4d,0xd2,0x5c,0x1d,0xda,0xe9,0x4f,0xa0,0x7c,0xed,0xc1,0x64,0x17,0xf5,0x51,0x3a,0xd3,0x5e,0x54,0xae,0x67,0xc6,0x4d,0x70,0x76,0x00,0x6d,0x8b,0x41,0x5b,0x8e,0xe8,0x2e,0x40,0xe0,0x4a,0xfb,0xea,0x24,0x37,0xe6,0x71,0xba,0xee,0x25,0x5c,0x9a,0x6c,0x86,0x60,0x8b,0xb7,0xa2,0x3f,0xc9,0xe7,0x11,0xeb,0x32,0x82,0x90,0x41,0x38,0xb3,0xf9,0x23,0x5d,0xd1,0x02,0x8b,0xe6,0xa5,0x6c,0xfc,0xa3,0x64,0xa6,0x57,0x0f,0xf8,0xde,0x67,0x19,0x2e,0x33,0x3e,0x34,0x56,0xf0,0xc9,0xc6,0x5f,0x77,0x1e,0x25,0x6a,0x59,0x09,0x88,0xdb,0x8b,0x56,0x09,0xf3,0x6c,0x14,0x0f,0x16,0x18,0x64,0x01,0x40,0x94,0xab,0x30,0x44,0xb0,0xa8,0x0b,0x37,0x3f,0x33,0x65,0x3b,0x0c,0x29,0xd5,0xb3,0x80,0xd9,0x72,0x7c,0xf2,0x32,0xc5,0x16,0x79,0x86,0x57,0x98,0x51,0xbb,0xcc,0xc8,0x22,0x88,0x28,0xd5,0xb2,0x58,0xb4,0xb0,0x26,0x7e,0xe6,0x65,0x86,0x07,0x5a,0x30,0x36,0xcc,0xcf,0x79,0xb5,0xbc,0xfa,0xb4,0x50,0x28,0x6a,0x6e,0x3d,0xee,0x31,0xae,0x7a,0x15,0x01,0xb1,0x94,0xe8,0xea,0x35,0x2a,0x6c,0x11,0x00,0x3e,0x87,0xdb,0xc6,0x94,0x1a,0x72,0x96,0x6f,0xd3,0x03,0x83,0x7c,0x42,0x16,0xcb,0x0d,0x36,0xa9,0xd6,0x95,0x9c,0xb1,0xe6,0x99,0xa7,0xe3,0x33,0xc4,0xe8,0xc6,0x9e,0xdd,0x77,0x15,0x8f,0x30,0xcc,0x67,0xf1,0x14,0x9f,0x29,0x33,0xa4,0x1f,0xd4,0xd3,0x75,0x85,0xff,0x62,0x59,0xa0,0x1d,0x96,0x60,0x01,0x05,0xf0,0x79,0xba,0x18,0x16,0x80,0x2c,0xc6,0xf0,0x25,0xfb,0xc2,0x08,0x86,0x69,0x3a,0x0a,0xb5,0x97,0x5b,0xa7,0x1c,0xe2,0xc5,0x38,0xf8,0xd2,0x0e,0x1b,0xa1,0x48,0x29,0x89,0x42,0x2e,0x5f,0xa1,0x11,0xf0,0x8b,0x2f,0x95,0xf1,0x33,0xe1,0xe1,0x72,0x46,0xc2,0x68,0xf8,0x3c,0x3e,0x90,0xfd,0xa6,0x9c,0x71,0x51,0xf1,0x60,0xa6,0xec,0xde,0x7a,0x96,0xea,0xd4,0x33,0xe4,0x05,0x1d,0xc1,0x1c,0x34,0x6f,0x35,0x76,0xef,0x10,0xae,0x7a,0xf4,0x83,0xd8,0xff,0xba,0xa8,0x5e,0x28,0x55,0x8b,0x09,0x3a,0x97,0xc9,0x65,0x2e,0x65,0x51,0xb8,0x13,0x9b,0xa1,0xbf,0x79,0xb7,0x4e,0x17,0x37,0x20,0xde,0x55,0xbb,0x44,0xd2,0x72,0xeb,0xff,0x67,0x79,0xcc,0x73,0xcb,0x4f,0xfd,0x5a,0x9c,0x02,0xed,0xcb,0xe2,0xb7,0x7e,0xe9,0xb7,0x3e,0x61,0xc6,0x9e,0x8b,0x97,0xf5,0xab,0xe9,0x39,0x60,0xd8,0x5b,0xab,0x28,0xf5,0x92,0x47,0x06,0xd0,0x6e,0xfc,0x98,0x12,0xfb,0x1c,0xdd,0xe3,0x17,0xa2,0x8e,0x0e,0x9a,0xae,0x83,0xf2,0x27,0xc3,0xab,0x15,0x11,0xca,0x14,0x15,0x12,0xec,0x37,0x42,0x58,0x59,0x9e,0x32,0xfc,0xf7,0xd3,0x35,0x7c,0x3d,0x40,0xe5,0x8f,0x92,0x6f,0xbf,0x80,0xe8,0x5c,0x62,0x63,0xf1,0x80,0xec,0x48,0x30,0xe7,0xc3,0x5f,0x8c,0xea,0x11,0xb4,0x23,0xa7,0x35,0xdb,0x47,0x1a,0x4b,0x69,0x98,0x2e,0x64,0x79,0x99,0x9c,0x3b,0x06,0x58,0x97,0x2d,0xb3,0x2a,0xff,0xdb,0x56,0xae,0x9d,0x49,0x83,0x43,0xe6,0x99,0xe9,0xea,0x22,0xa1,0xde,0x54,0x17,0xe5,0xaa,0xb4,0xbc,0x0a,0x99,0x9b,0xa8,0x6c,0x19,0xaa,0x8b,0x99,0x3a,0xa1,0x1d,0xdd,0x7e,0x7f,0xfb,0xed,0x4f,0xb7,0xa9,0x22,0x1f,0x0f,0xf9,0xa5,0x14,0x96,0x19,0x61,0xc5,0x48,0x38,0x9f,0x01,0x5d,0x30,0x77,0xc1,0x33,0x11,0x4e,0xee,0x5d,0x91,0x7b,0x51,0x5b,0x75,0x99,0x6d,0x52,0xdb,0x1c,0x03,0x74,0x41,0x77,0x13,0x39,0x86,0xe7,0xee,0x6c,0x77,0x1b,0xad,0x25]; + let ct: [u8; MLKEM512_CT_LEN] = [ + 0x5A, 0x68, 0x40, 0x8E, 0xEB, 0x0E, 0xE7, 0xD1, 0xF5, 0x11, 0x4F, 0x4B, 0xED, 0xAE, 0xB6, + 0x00, 0x48, 0xF5, 0x39, 0x7E, 0xEA, 0x20, 0xCA, 0x22, 0x89, 0xE5, 0xB2, 0xB1, 0xC7, 0x01, + 0x65, 0x49, 0xAC, 0x72, 0x8D, 0xB0, 0x97, 0x74, 0xE1, 0xC6, 0x79, 0x8C, 0xD7, 0xD1, 0x93, + 0xBD, 0x74, 0x94, 0x16, 0xF3, 0x75, 0x2E, 0x9D, 0x75, 0xBB, 0x16, 0x09, 0x01, 0xC6, 0x39, + 0xAB, 0x39, 0x41, 0xB4, 0xE2, 0xB2, 0xE5, 0xA0, 0x68, 0x3D, 0x49, 0xCB, 0xA9, 0xBC, 0xE2, + 0x07, 0xF8, 0x45, 0x8F, 0x9E, 0xF9, 0x54, 0xCE, 0xBB, 0xBF, 0x15, 0xB1, 0x8A, 0x14, 0x8E, + 0x37, 0x05, 0xC6, 0xB1, 0x9B, 0xBA, 0x2E, 0x52, 0x54, 0x69, 0x80, 0x3D, 0x1B, 0x86, 0x11, + 0xE7, 0x43, 0xC8, 0x56, 0x8B, 0x9F, 0x07, 0x77, 0x84, 0x71, 0xDD, 0x0E, 0x6C, 0x3A, 0x00, + 0x76, 0x6C, 0xFA, 0xDF, 0xF1, 0x6D, 0xF4, 0xDB, 0x94, 0x9B, 0x34, 0xF0, 0x86, 0x07, 0x06, + 0x30, 0x3A, 0x32, 0xB6, 0x2A, 0x9B, 0x9D, 0x23, 0x44, 0x69, 0x27, 0x63, 0x4D, 0x02, 0x45, + 0x9F, 0x3B, 0x69, 0xBC, 0x3B, 0xD2, 0xF1, 0x2F, 0x9F, 0x66, 0x00, 0x92, 0x10, 0xCB, 0xE9, + 0xDF, 0xF1, 0x1C, 0xDE, 0x5E, 0x63, 0x3F, 0x37, 0xB4, 0xDC, 0xDA, 0xBE, 0x97, 0x93, 0x0B, + 0x1B, 0xCE, 0xE5, 0x71, 0xE9, 0x55, 0x49, 0xE6, 0xFD, 0x25, 0x54, 0x98, 0xCF, 0x0D, 0x75, + 0x4D, 0xD2, 0x5C, 0x1D, 0xDA, 0xE9, 0x4F, 0xA0, 0x7C, 0xED, 0xC1, 0x64, 0x17, 0xF5, 0x51, + 0x3A, 0xD3, 0x5E, 0x54, 0xAE, 0x67, 0xC6, 0x4D, 0x70, 0x76, 0x00, 0x6D, 0x8B, 0x41, 0x5B, + 0x8E, 0xE8, 0x2E, 0x40, 0xE0, 0x4A, 0xFB, 0xEA, 0x24, 0x37, 0xE6, 0x71, 0xBA, 0xEE, 0x25, + 0x5C, 0x9A, 0x6C, 0x86, 0x60, 0x8B, 0xB7, 0xA2, 0x3F, 0xC9, 0xE7, 0x11, 0xEB, 0x32, 0x82, + 0x90, 0x41, 0x38, 0xB3, 0xF9, 0x23, 0x5D, 0xD1, 0x02, 0x8B, 0xE6, 0xA5, 0x6C, 0xFC, 0xA3, + 0x64, 0xA6, 0x57, 0x0F, 0xF8, 0xDE, 0x67, 0x19, 0x2E, 0x33, 0x3E, 0x34, 0x56, 0xF0, 0xC9, + 0xC6, 0x5F, 0x77, 0x1E, 0x25, 0x6A, 0x59, 0x09, 0x88, 0xDB, 0x8B, 0x56, 0x09, 0xF3, 0x6C, + 0x14, 0x0F, 0x16, 0x18, 0x64, 0x01, 0x40, 0x94, 0xAB, 0x30, 0x44, 0xB0, 0xA8, 0x0B, 0x37, + 0x3F, 0x33, 0x65, 0x3B, 0x0C, 0x29, 0xD5, 0xB3, 0x80, 0xD9, 0x72, 0x7C, 0xF2, 0x32, 0xC5, + 0x16, 0x79, 0x86, 0x57, 0x98, 0x51, 0xBB, 0xCC, 0xC8, 0x22, 0x88, 0x28, 0xD5, 0xB2, 0x58, + 0xB4, 0xB0, 0x26, 0x7E, 0xE6, 0x65, 0x86, 0x07, 0x5A, 0x30, 0x36, 0xCC, 0xCF, 0x79, 0xB5, + 0xBC, 0xFA, 0xB4, 0x50, 0x28, 0x6A, 0x6E, 0x3D, 0xEE, 0x31, 0xAE, 0x7A, 0x15, 0x01, 0xB1, + 0x94, 0xE8, 0xEA, 0x35, 0x2A, 0x6C, 0x11, 0x00, 0x3E, 0x87, 0xDB, 0xC6, 0x94, 0x1A, 0x72, + 0x96, 0x6F, 0xD3, 0x03, 0x83, 0x7C, 0x42, 0x16, 0xCB, 0x0D, 0x36, 0xA9, 0xD6, 0x95, 0x9C, + 0xB1, 0xE6, 0x99, 0xA7, 0xE3, 0x33, 0xC4, 0xE8, 0xC6, 0x9E, 0xDD, 0x77, 0x15, 0x8F, 0x30, + 0xCC, 0x67, 0xF1, 0x14, 0x9F, 0x29, 0x33, 0xA4, 0x1F, 0xD4, 0xD3, 0x75, 0x85, 0xFF, 0x62, + 0x59, 0xA0, 0x1D, 0x96, 0x60, 0x01, 0x05, 0xF0, 0x79, 0xBA, 0x18, 0x16, 0x80, 0x2C, 0xC6, + 0xF0, 0x25, 0xFB, 0xC2, 0x08, 0x86, 0x69, 0x3A, 0x0A, 0xB5, 0x97, 0x5B, 0xA7, 0x1C, 0xE2, + 0xC5, 0x38, 0xF8, 0xD2, 0x0E, 0x1B, 0xA1, 0x48, 0x29, 0x89, 0x42, 0x2E, 0x5F, 0xA1, 0x11, + 0xF0, 0x8B, 0x2F, 0x95, 0xF1, 0x33, 0xE1, 0xE1, 0x72, 0x46, 0xC2, 0x68, 0xF8, 0x3C, 0x3E, + 0x90, 0xFD, 0xA6, 0x9C, 0x71, 0x51, 0xF1, 0x60, 0xA6, 0xEC, 0xDE, 0x7A, 0x96, 0xEA, 0xD4, + 0x33, 0xE4, 0x05, 0x1D, 0xC1, 0x1C, 0x34, 0x6F, 0x35, 0x76, 0xEF, 0x10, 0xAE, 0x7A, 0xF4, + 0x83, 0xD8, 0xFF, 0xBA, 0xA8, 0x5E, 0x28, 0x55, 0x8B, 0x09, 0x3A, 0x97, 0xC9, 0x65, 0x2E, + 0x65, 0x51, 0xB8, 0x13, 0x9B, 0xA1, 0xBF, 0x79, 0xB7, 0x4E, 0x17, 0x37, 0x20, 0xDE, 0x55, + 0xBB, 0x44, 0xD2, 0x72, 0xEB, 0xFF, 0x67, 0x79, 0xCC, 0x73, 0xCB, 0x4F, 0xFD, 0x5A, 0x9C, + 0x02, 0xED, 0xCB, 0xE2, 0xB7, 0x7E, 0xE9, 0xB7, 0x3E, 0x61, 0xC6, 0x9E, 0x8B, 0x97, 0xF5, + 0xAB, 0xE9, 0x39, 0x60, 0xD8, 0x5B, 0xAB, 0x28, 0xF5, 0x92, 0x47, 0x06, 0xD0, 0x6E, 0xFC, + 0x98, 0x12, 0xFB, 0x1C, 0xDD, 0xE3, 0x17, 0xA2, 0x8E, 0x0E, 0x9A, 0xAE, 0x83, 0xF2, 0x27, + 0xC3, 0xAB, 0x15, 0x11, 0xCA, 0x14, 0x15, 0x12, 0xEC, 0x37, 0x42, 0x58, 0x59, 0x9E, 0x32, + 0xFC, 0xF7, 0xD3, 0x35, 0x7C, 0x3D, 0x40, 0xE5, 0x8F, 0x92, 0x6F, 0xBF, 0x80, 0xE8, 0x5C, + 0x62, 0x63, 0xF1, 0x80, 0xEC, 0x48, 0x30, 0xE7, 0xC3, 0x5F, 0x8C, 0xEA, 0x11, 0xB4, 0x23, + 0xA7, 0x35, 0xDB, 0x47, 0x1A, 0x4B, 0x69, 0x98, 0x2E, 0x64, 0x79, 0x99, 0x9C, 0x3B, 0x06, + 0x58, 0x97, 0x2D, 0xB3, 0x2A, 0xFF, 0xDB, 0x56, 0xAE, 0x9D, 0x49, 0x83, 0x43, 0xE6, 0x99, + 0xE9, 0xEA, 0x22, 0xA1, 0xDE, 0x54, 0x17, 0xE5, 0xAA, 0xB4, 0xBC, 0x0A, 0x99, 0x9B, 0xA8, + 0x6C, 0x19, 0xAA, 0x8B, 0x99, 0x3A, 0xA1, 0x1D, 0xDD, 0x7E, 0x7F, 0xFB, 0xED, 0x4F, 0xB7, + 0xA9, 0x22, 0x1F, 0x0F, 0xF9, 0xA5, 0x14, 0x96, 0x19, 0x61, 0xC5, 0x48, 0x38, 0x9F, 0x01, + 0x5D, 0x30, 0x77, 0xC1, 0x33, 0x11, 0x4E, 0xEE, 0x5D, 0x91, 0x7B, 0x51, 0x5B, 0x75, 0x99, + 0x6D, 0x52, 0xDB, 0x1C, 0x03, 0x74, 0x41, 0x77, 0x13, 0x39, 0x86, 0xE7, 0xEE, 0x6C, 0x77, + 0x1B, 0xAD, 0x25, + ]; let (_pk, sk) = MLKEM512::keygen_from_seed(&seed).unwrap(); let ss = MLKEM512::decaps(&sk, &ct).unwrap(); @@ -343,14 +1021,21 @@ fn bench_mlkem512_lowmemory_decaps() { } fn bench_mlkem768_decaps() { - use bouncycastle::mlkem::{MLKEMTrait, MLKEM768}; + use bouncycastle::mlkem::{MLKEM768, MLKEMTrait}; eprintln!("MLKEM768/Decaps"); let seed = KeyMaterial512::from_bytes_as_type( - &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ], KeyType::Seed, - ).unwrap(); + ) + .unwrap(); /* One-time setup of the KAT -- commented out so that we're not capturing keygen in the bench */ // let (pk, _sk) = MLKEM768::keygen_from_seed(&seed).unwrap(); @@ -358,7 +1043,81 @@ fn bench_mlkem768_decaps() { // use bouncycastle_hex as hex; // eprintln!("ct:\n{}", &hex::encode(ct)); - let ct: [u8; MLKEM768_CT_LEN] = [0xa8,0xf1,0x73,0xf0,0xf4,0x4b,0xb1,0xc7,0x68,0x12,0x9e,0xf4,0x26,0xea,0x35,0xd1,0x75,0xcf,0x94,0xc5,0xd4,0xae,0x86,0x46,0xcd,0xab,0xef,0x4a,0xa1,0x72,0x78,0x1b,0xbb,0xf8,0x09,0xdc,0x12,0xda,0x50,0x37,0xf6,0x00,0xea,0xf3,0xf7,0xda,0x77,0xa2,0x3d,0xc8,0x46,0x86,0xe6,0xb5,0xec,0xe3,0x72,0xde,0xbd,0xf7,0x8f,0x4b,0x2c,0x06,0xd0,0xea,0x7a,0x8d,0x2a,0xd6,0x78,0x20,0x6f,0x5d,0x51,0x57,0xfd,0x0d,0x7a,0xe0,0x18,0xcb,0x7c,0xba,0xdd,0x42,0x19,0x72,0xf5,0xcd,0xdb,0x86,0xec,0x8e,0x2e,0x4f,0x82,0x83,0x9d,0xc8,0xcc,0x98,0x67,0xec,0x0f,0x2c,0x3b,0x96,0x2f,0x59,0x17,0x7f,0x0f,0x98,0x1d,0x75,0xd8,0xed,0x97,0xfb,0x69,0x53,0xc5,0x5b,0x6a,0xdb,0x4a,0x19,0x60,0x51,0x8c,0xd9,0x59,0x7b,0xd8,0x40,0x1e,0x2d,0xb2,0x03,0xc2,0x69,0xc2,0x61,0x3f,0x0e,0x1f,0xa3,0x2e,0xa0,0x81,0xc4,0x25,0xd8,0x5d,0xfd,0x50,0x97,0x82,0x1f,0x47,0x0c,0x8e,0x99,0x48,0x62,0x4f,0x4b,0x97,0xd7,0x96,0x29,0x2f,0x85,0x0c,0x09,0x95,0xd7,0x72,0x51,0xac,0xc1,0xbb,0xfa,0x76,0x24,0xa5,0x11,0x89,0xe6,0x91,0x18,0x71,0x71,0x05,0x19,0x8b,0x10,0x53,0x1d,0x61,0xad,0x5b,0x13,0x2d,0x0c,0x4c,0x99,0xfa,0x7b,0xc5,0x34,0x4b,0xae,0x1c,0x70,0xd4,0x85,0x4d,0xa8,0x57,0x51,0x57,0xa7,0xd9,0x63,0x0b,0xd9,0x3d,0xa4,0x37,0x21,0xa8,0xf7,0x42,0xd3,0xe1,0x8c,0x8f,0x56,0xf5,0xab,0x31,0x22,0x17,0xe1,0xa7,0xa9,0xc7,0x7a,0x34,0xb7,0x1e,0x23,0x80,0x23,0x1a,0x2a,0x6c,0x9c,0xef,0xcb,0x40,0x04,0x00,0x37,0x26,0xac,0x03,0x69,0xe1,0xdd,0xc7,0x53,0xf3,0xd4,0x3a,0xde,0x56,0x5d,0xff,0x11,0xb7,0x9b,0xf0,0x82,0xc7,0x68,0x47,0xd7,0x4f,0xce,0xeb,0x07,0xa7,0x70,0x6b,0x94,0x91,0x17,0xf3,0xb7,0xfa,0x41,0x46,0xce,0x40,0xc6,0x50,0x51,0xbb,0x5b,0x82,0xce,0x27,0x1c,0x95,0xfd,0x77,0xd6,0xef,0xaa,0x24,0xd4,0x47,0x65,0xcc,0xbc,0xda,0xd6,0xdf,0xb5,0xb5,0x5d,0x01,0x42,0xb6,0x2f,0x91,0x3a,0x41,0x8a,0x82,0x83,0x4c,0x56,0xac,0x70,0x6c,0x40,0x05,0x00,0xe4,0x67,0x9e,0x64,0x24,0xc5,0x33,0xa0,0xb0,0xec,0x6a,0x3b,0x08,0x4c,0x12,0x40,0x3e,0x47,0x1f,0x7a,0x74,0x34,0x37,0xd7,0xc2,0x20,0x3a,0xca,0xeb,0xcf,0x22,0x87,0x23,0x89,0xda,0x78,0x6e,0xff,0xf0,0x7e,0x57,0x99,0x6b,0x0c,0xa8,0x95,0x8f,0xe1,0x90,0x81,0xe6,0x9e,0xc9,0x63,0x91,0xb2,0x61,0xda,0x0a,0x90,0xb0,0x99,0xa1,0xf9,0xdb,0x12,0x08,0xac,0xfc,0x5f,0x0f,0xf1,0xa9,0x04,0xef,0xee,0xa0,0xfe,0x2c,0x42,0x26,0x00,0xa0,0x3f,0xb5,0xa7,0x44,0x19,0x2e,0x0c,0x50,0xf7,0x0f,0x84,0x76,0xf0,0x5c,0x3a,0xb6,0xcb,0x8c,0xd9,0xa2,0x12,0x1c,0x2f,0x4f,0xb9,0x3b,0x53,0x44,0x89,0xf7,0x5d,0xb6,0x97,0xb4,0x80,0x4a,0x44,0xaa,0x3e,0x15,0x8b,0xa1,0x5f,0x0b,0x3c,0x8d,0x3b,0xe0,0x69,0x83,0xd4,0x57,0xdc,0x93,0xa9,0x6a,0x84,0x04,0x53,0x41,0x89,0x59,0xfe,0x5f,0xb6,0xdf,0xc0,0x6a,0x3b,0x2c,0xd3,0xae,0x3e,0x48,0x3e,0x1e,0xe0,0xac,0x74,0x98,0xda,0x0a,0x70,0x65,0xb9,0x46,0x48,0x80,0x64,0x89,0xb6,0xce,0x9f,0xfd,0xce,0x53,0xb8,0x61,0xa0,0x7f,0xed,0xbc,0xa7,0x9b,0x1b,0xc8,0x9b,0xe7,0xb5,0xa2,0x58,0x76,0x5e,0x2c,0xc9,0x09,0xc4,0x89,0x30,0xda,0x50,0xb2,0x38,0xfd,0x6c,0x95,0x7e,0x90,0xab,0x53,0x6a,0x27,0xfa,0x63,0xf5,0xfe,0xa3,0xe2,0x9a,0x2e,0x7a,0x33,0xbf,0x9f,0xb9,0x0e,0xb3,0x8d,0xee,0x0d,0xc2,0xa6,0xd9,0x2f,0x9c,0xec,0x0e,0x78,0xa0,0xd0,0x96,0x47,0xb6,0x51,0x62,0x25,0x07,0x3e,0x6b,0x35,0x00,0xa1,0x49,0xb6,0xe4,0x27,0x27,0x33,0xe4,0xe0,0x5e,0xa8,0x4a,0x0a,0x45,0x67,0x2f,0x62,0xe9,0xa5,0x4f,0xa1,0x76,0xee,0xa6,0x10,0x22,0xd4,0xfc,0xda,0x55,0x3d,0x5b,0xaa,0xb1,0x84,0xd0,0x8a,0xf4,0xb8,0x06,0xbc,0x40,0xc4,0x22,0x9d,0xaf,0x7b,0x5f,0x64,0x4f,0x1a,0xc8,0xd0,0xd4,0xa1,0xa4,0x8a,0xe6,0xb6,0xf2,0xbf,0xaa,0xe5,0xce,0x5a,0xc4,0x6c,0x8b,0x4f,0x1a,0xc8,0x41,0xf9,0xc8,0x2b,0x57,0xb4,0x37,0xd0,0x91,0x7b,0x80,0x5c,0x46,0x88,0x05,0xa3,0x06,0xe9,0x2f,0xb1,0x68,0xaf,0xa8,0xbd,0x34,0xef,0x41,0xeb,0x57,0x57,0x70,0x72,0xd8,0x56,0x83,0xac,0xbe,0x72,0xac,0x9d,0x06,0x10,0x95,0xe5,0xf4,0xd8,0xba,0x1a,0xb7,0x91,0xf9,0xc2,0xb9,0x24,0xc8,0x1e,0xe5,0x33,0xd5,0x81,0x1e,0x15,0x54,0x5e,0xbb,0x01,0x92,0xe8,0xec,0x4e,0xec,0x4e,0xa4,0x95,0x28,0x9a,0x27,0xfd,0x67,0xe5,0x20,0xcf,0x72,0xd7,0xd5,0x95,0x14,0xc0,0x35,0x94,0x66,0x78,0x96,0xed,0x41,0x11,0xf1,0xb2,0x1f,0x0a,0xed,0x19,0xbb,0xf9,0xca,0x4b,0xcb,0x54,0x68,0xe3,0x09,0xca,0xa7,0x45,0xf4,0x0c,0xbf,0x25,0x41,0xa2,0x70,0xa6,0xd6,0x05,0x2b,0x7e,0xd7,0x1e,0x83,0x32,0x8e,0xac,0x0a,0xa3,0xde,0x03,0xeb,0x7c,0x9a,0xde,0x04,0x74,0xab,0x0e,0x42,0x67,0xfb,0xae,0xe5,0xb6,0x8d,0xac,0x44,0x66,0x55,0xdd,0xbb,0x70,0xaf,0x44,0xc1,0x90,0xfb,0x16,0xa0,0x8e,0x98,0xdb,0xf6,0x36,0x94,0xf7,0x04,0xe0,0x7f,0x2b,0xdc,0xee,0x5a,0xbd,0xb6,0x05,0x4e,0x78,0xb5,0x54,0x41,0x22,0xcc,0x93,0xa0,0xbc,0xcd,0x4a,0x8a,0x89,0xc6,0x3c,0x30,0x7b,0x1f,0x4c,0x7d,0xc4,0x2c,0x65,0xfa,0xb5,0xd8,0x95,0x76,0x1b,0x88,0xad,0xc6,0x4a,0x99,0x53,0xc1,0xe5,0x96,0xe0,0x05,0x54,0xd8,0x64,0xd1,0x00,0x2e,0xc6,0x53,0xe8,0x5a,0xf1,0x71,0x72,0x6a,0x6b,0xc2,0x32,0xf0,0xae,0x08,0x1d,0x63,0x76,0xa9,0xa5,0xa0,0x57,0x34,0x6e,0x77,0x54,0x2f,0x73,0x4d,0x1b,0x12,0x7d,0x5d,0xbf,0xae,0x8f,0x5d,0x50,0xbb,0x0d,0x05,0x22,0x9b,0xe2,0xc5,0xd8,0x40,0x3d,0xdb,0xa6,0xdf,0x8f,0xba,0x23,0xa6,0x46,0x0a,0x4c,0x65,0x5d,0x9f,0xbb,0xed,0xff,0x60,0x3a,0x7e,0xa9,0xa4,0xff,0xb5,0x83,0xcf,0xb8,0x95,0xdb,0x37,0x54,0x35,0xdd,0x31,0xf2,0x9f,0x2a,0x8a,0xa2,0x33,0x3b,0x9b,0x48,0x4f,0x33,0xc9,0x70,0xe8,0x07,0xbb,0xd6,0x24,0xeb,0x6f,0xae,0x02,0x32,0x04,0x07,0x6f,0x30,0x9d,0x75,0xb9,0x44,0x73,0x11,0xee,0x16,0x89,0xcf,0x2f,0x01,0x40,0x7b,0xba,0x1f,0x44,0x5e,0xbf,0xbb,0x3e,0x1b,0x3e,0x1b,0x57,0xc1,0x69,0xc0,0x71,0xdd,0x40,0x3c,0x46,0x21,0xcd,0x76,0x61,0x64,0xc5,0x5e,0xdf,0x0f,0xed,0x3b,0xe1,0xff,0xec,0x76,0x46,0x9f,0x86,0x8b,0x88,0xf6,0x53,0xad,0x20,0x4d,0x07,0x0a,0x9e,0x17,0x30,0x49,0xdd,0x4d,0x00,0xbd,0x63,0xe1,0xee,0xde,0xbd,0x6d,0x15]; + let ct: [u8; MLKEM768_CT_LEN] = [ + 0xA8, 0xF1, 0x73, 0xF0, 0xF4, 0x4B, 0xB1, 0xC7, 0x68, 0x12, 0x9E, 0xF4, 0x26, 0xEA, 0x35, + 0xD1, 0x75, 0xCF, 0x94, 0xC5, 0xD4, 0xAE, 0x86, 0x46, 0xCD, 0xAB, 0xEF, 0x4A, 0xA1, 0x72, + 0x78, 0x1B, 0xBB, 0xF8, 0x09, 0xDC, 0x12, 0xDA, 0x50, 0x37, 0xF6, 0x00, 0xEA, 0xF3, 0xF7, + 0xDA, 0x77, 0xA2, 0x3D, 0xC8, 0x46, 0x86, 0xE6, 0xB5, 0xEC, 0xE3, 0x72, 0xDE, 0xBD, 0xF7, + 0x8F, 0x4B, 0x2C, 0x06, 0xD0, 0xEA, 0x7A, 0x8D, 0x2A, 0xD6, 0x78, 0x20, 0x6F, 0x5D, 0x51, + 0x57, 0xFD, 0x0D, 0x7A, 0xE0, 0x18, 0xCB, 0x7C, 0xBA, 0xDD, 0x42, 0x19, 0x72, 0xF5, 0xCD, + 0xDB, 0x86, 0xEC, 0x8E, 0x2E, 0x4F, 0x82, 0x83, 0x9D, 0xC8, 0xCC, 0x98, 0x67, 0xEC, 0x0F, + 0x2C, 0x3B, 0x96, 0x2F, 0x59, 0x17, 0x7F, 0x0F, 0x98, 0x1D, 0x75, 0xD8, 0xED, 0x97, 0xFB, + 0x69, 0x53, 0xC5, 0x5B, 0x6A, 0xDB, 0x4A, 0x19, 0x60, 0x51, 0x8C, 0xD9, 0x59, 0x7B, 0xD8, + 0x40, 0x1E, 0x2D, 0xB2, 0x03, 0xC2, 0x69, 0xC2, 0x61, 0x3F, 0x0E, 0x1F, 0xA3, 0x2E, 0xA0, + 0x81, 0xC4, 0x25, 0xD8, 0x5D, 0xFD, 0x50, 0x97, 0x82, 0x1F, 0x47, 0x0C, 0x8E, 0x99, 0x48, + 0x62, 0x4F, 0x4B, 0x97, 0xD7, 0x96, 0x29, 0x2F, 0x85, 0x0C, 0x09, 0x95, 0xD7, 0x72, 0x51, + 0xAC, 0xC1, 0xBB, 0xFA, 0x76, 0x24, 0xA5, 0x11, 0x89, 0xE6, 0x91, 0x18, 0x71, 0x71, 0x05, + 0x19, 0x8B, 0x10, 0x53, 0x1D, 0x61, 0xAD, 0x5B, 0x13, 0x2D, 0x0C, 0x4C, 0x99, 0xFA, 0x7B, + 0xC5, 0x34, 0x4B, 0xAE, 0x1C, 0x70, 0xD4, 0x85, 0x4D, 0xA8, 0x57, 0x51, 0x57, 0xA7, 0xD9, + 0x63, 0x0B, 0xD9, 0x3D, 0xA4, 0x37, 0x21, 0xA8, 0xF7, 0x42, 0xD3, 0xE1, 0x8C, 0x8F, 0x56, + 0xF5, 0xAB, 0x31, 0x22, 0x17, 0xE1, 0xA7, 0xA9, 0xC7, 0x7A, 0x34, 0xB7, 0x1E, 0x23, 0x80, + 0x23, 0x1A, 0x2A, 0x6C, 0x9C, 0xEF, 0xCB, 0x40, 0x04, 0x00, 0x37, 0x26, 0xAC, 0x03, 0x69, + 0xE1, 0xDD, 0xC7, 0x53, 0xF3, 0xD4, 0x3A, 0xDE, 0x56, 0x5D, 0xFF, 0x11, 0xB7, 0x9B, 0xF0, + 0x82, 0xC7, 0x68, 0x47, 0xD7, 0x4F, 0xCE, 0xEB, 0x07, 0xA7, 0x70, 0x6B, 0x94, 0x91, 0x17, + 0xF3, 0xB7, 0xFA, 0x41, 0x46, 0xCE, 0x40, 0xC6, 0x50, 0x51, 0xBB, 0x5B, 0x82, 0xCE, 0x27, + 0x1C, 0x95, 0xFD, 0x77, 0xD6, 0xEF, 0xAA, 0x24, 0xD4, 0x47, 0x65, 0xCC, 0xBC, 0xDA, 0xD6, + 0xDF, 0xB5, 0xB5, 0x5D, 0x01, 0x42, 0xB6, 0x2F, 0x91, 0x3A, 0x41, 0x8A, 0x82, 0x83, 0x4C, + 0x56, 0xAC, 0x70, 0x6C, 0x40, 0x05, 0x00, 0xE4, 0x67, 0x9E, 0x64, 0x24, 0xC5, 0x33, 0xA0, + 0xB0, 0xEC, 0x6A, 0x3B, 0x08, 0x4C, 0x12, 0x40, 0x3E, 0x47, 0x1F, 0x7A, 0x74, 0x34, 0x37, + 0xD7, 0xC2, 0x20, 0x3A, 0xCA, 0xEB, 0xCF, 0x22, 0x87, 0x23, 0x89, 0xDA, 0x78, 0x6E, 0xFF, + 0xF0, 0x7E, 0x57, 0x99, 0x6B, 0x0C, 0xA8, 0x95, 0x8F, 0xE1, 0x90, 0x81, 0xE6, 0x9E, 0xC9, + 0x63, 0x91, 0xB2, 0x61, 0xDA, 0x0A, 0x90, 0xB0, 0x99, 0xA1, 0xF9, 0xDB, 0x12, 0x08, 0xAC, + 0xFC, 0x5F, 0x0F, 0xF1, 0xA9, 0x04, 0xEF, 0xEE, 0xA0, 0xFE, 0x2C, 0x42, 0x26, 0x00, 0xA0, + 0x3F, 0xB5, 0xA7, 0x44, 0x19, 0x2E, 0x0C, 0x50, 0xF7, 0x0F, 0x84, 0x76, 0xF0, 0x5C, 0x3A, + 0xB6, 0xCB, 0x8C, 0xD9, 0xA2, 0x12, 0x1C, 0x2F, 0x4F, 0xB9, 0x3B, 0x53, 0x44, 0x89, 0xF7, + 0x5D, 0xB6, 0x97, 0xB4, 0x80, 0x4A, 0x44, 0xAA, 0x3E, 0x15, 0x8B, 0xA1, 0x5F, 0x0B, 0x3C, + 0x8D, 0x3B, 0xE0, 0x69, 0x83, 0xD4, 0x57, 0xDC, 0x93, 0xA9, 0x6A, 0x84, 0x04, 0x53, 0x41, + 0x89, 0x59, 0xFE, 0x5F, 0xB6, 0xDF, 0xC0, 0x6A, 0x3B, 0x2C, 0xD3, 0xAE, 0x3E, 0x48, 0x3E, + 0x1E, 0xE0, 0xAC, 0x74, 0x98, 0xDA, 0x0A, 0x70, 0x65, 0xB9, 0x46, 0x48, 0x80, 0x64, 0x89, + 0xB6, 0xCE, 0x9F, 0xFD, 0xCE, 0x53, 0xB8, 0x61, 0xA0, 0x7F, 0xED, 0xBC, 0xA7, 0x9B, 0x1B, + 0xC8, 0x9B, 0xE7, 0xB5, 0xA2, 0x58, 0x76, 0x5E, 0x2C, 0xC9, 0x09, 0xC4, 0x89, 0x30, 0xDA, + 0x50, 0xB2, 0x38, 0xFD, 0x6C, 0x95, 0x7E, 0x90, 0xAB, 0x53, 0x6A, 0x27, 0xFA, 0x63, 0xF5, + 0xFE, 0xA3, 0xE2, 0x9A, 0x2E, 0x7A, 0x33, 0xBF, 0x9F, 0xB9, 0x0E, 0xB3, 0x8D, 0xEE, 0x0D, + 0xC2, 0xA6, 0xD9, 0x2F, 0x9C, 0xEC, 0x0E, 0x78, 0xA0, 0xD0, 0x96, 0x47, 0xB6, 0x51, 0x62, + 0x25, 0x07, 0x3E, 0x6B, 0x35, 0x00, 0xA1, 0x49, 0xB6, 0xE4, 0x27, 0x27, 0x33, 0xE4, 0xE0, + 0x5E, 0xA8, 0x4A, 0x0A, 0x45, 0x67, 0x2F, 0x62, 0xE9, 0xA5, 0x4F, 0xA1, 0x76, 0xEE, 0xA6, + 0x10, 0x22, 0xD4, 0xFC, 0xDA, 0x55, 0x3D, 0x5B, 0xAA, 0xB1, 0x84, 0xD0, 0x8A, 0xF4, 0xB8, + 0x06, 0xBC, 0x40, 0xC4, 0x22, 0x9D, 0xAF, 0x7B, 0x5F, 0x64, 0x4F, 0x1A, 0xC8, 0xD0, 0xD4, + 0xA1, 0xA4, 0x8A, 0xE6, 0xB6, 0xF2, 0xBF, 0xAA, 0xE5, 0xCE, 0x5A, 0xC4, 0x6C, 0x8B, 0x4F, + 0x1A, 0xC8, 0x41, 0xF9, 0xC8, 0x2B, 0x57, 0xB4, 0x37, 0xD0, 0x91, 0x7B, 0x80, 0x5C, 0x46, + 0x88, 0x05, 0xA3, 0x06, 0xE9, 0x2F, 0xB1, 0x68, 0xAF, 0xA8, 0xBD, 0x34, 0xEF, 0x41, 0xEB, + 0x57, 0x57, 0x70, 0x72, 0xD8, 0x56, 0x83, 0xAC, 0xBE, 0x72, 0xAC, 0x9D, 0x06, 0x10, 0x95, + 0xE5, 0xF4, 0xD8, 0xBA, 0x1A, 0xB7, 0x91, 0xF9, 0xC2, 0xB9, 0x24, 0xC8, 0x1E, 0xE5, 0x33, + 0xD5, 0x81, 0x1E, 0x15, 0x54, 0x5E, 0xBB, 0x01, 0x92, 0xE8, 0xEC, 0x4E, 0xEC, 0x4E, 0xA4, + 0x95, 0x28, 0x9A, 0x27, 0xFD, 0x67, 0xE5, 0x20, 0xCF, 0x72, 0xD7, 0xD5, 0x95, 0x14, 0xC0, + 0x35, 0x94, 0x66, 0x78, 0x96, 0xED, 0x41, 0x11, 0xF1, 0xB2, 0x1F, 0x0A, 0xED, 0x19, 0xBB, + 0xF9, 0xCA, 0x4B, 0xCB, 0x54, 0x68, 0xE3, 0x09, 0xCA, 0xA7, 0x45, 0xF4, 0x0C, 0xBF, 0x25, + 0x41, 0xA2, 0x70, 0xA6, 0xD6, 0x05, 0x2B, 0x7E, 0xD7, 0x1E, 0x83, 0x32, 0x8E, 0xAC, 0x0A, + 0xA3, 0xDE, 0x03, 0xEB, 0x7C, 0x9A, 0xDE, 0x04, 0x74, 0xAB, 0x0E, 0x42, 0x67, 0xFB, 0xAE, + 0xE5, 0xB6, 0x8D, 0xAC, 0x44, 0x66, 0x55, 0xDD, 0xBB, 0x70, 0xAF, 0x44, 0xC1, 0x90, 0xFB, + 0x16, 0xA0, 0x8E, 0x98, 0xDB, 0xF6, 0x36, 0x94, 0xF7, 0x04, 0xE0, 0x7F, 0x2B, 0xDC, 0xEE, + 0x5A, 0xBD, 0xB6, 0x05, 0x4E, 0x78, 0xB5, 0x54, 0x41, 0x22, 0xCC, 0x93, 0xA0, 0xBC, 0xCD, + 0x4A, 0x8A, 0x89, 0xC6, 0x3C, 0x30, 0x7B, 0x1F, 0x4C, 0x7D, 0xC4, 0x2C, 0x65, 0xFA, 0xB5, + 0xD8, 0x95, 0x76, 0x1B, 0x88, 0xAD, 0xC6, 0x4A, 0x99, 0x53, 0xC1, 0xE5, 0x96, 0xE0, 0x05, + 0x54, 0xD8, 0x64, 0xD1, 0x00, 0x2E, 0xC6, 0x53, 0xE8, 0x5A, 0xF1, 0x71, 0x72, 0x6A, 0x6B, + 0xC2, 0x32, 0xF0, 0xAE, 0x08, 0x1D, 0x63, 0x76, 0xA9, 0xA5, 0xA0, 0x57, 0x34, 0x6E, 0x77, + 0x54, 0x2F, 0x73, 0x4D, 0x1B, 0x12, 0x7D, 0x5D, 0xBF, 0xAE, 0x8F, 0x5D, 0x50, 0xBB, 0x0D, + 0x05, 0x22, 0x9B, 0xE2, 0xC5, 0xD8, 0x40, 0x3D, 0xDB, 0xA6, 0xDF, 0x8F, 0xBA, 0x23, 0xA6, + 0x46, 0x0A, 0x4C, 0x65, 0x5D, 0x9F, 0xBB, 0xED, 0xFF, 0x60, 0x3A, 0x7E, 0xA9, 0xA4, 0xFF, + 0xB5, 0x83, 0xCF, 0xB8, 0x95, 0xDB, 0x37, 0x54, 0x35, 0xDD, 0x31, 0xF2, 0x9F, 0x2A, 0x8A, + 0xA2, 0x33, 0x3B, 0x9B, 0x48, 0x4F, 0x33, 0xC9, 0x70, 0xE8, 0x07, 0xBB, 0xD6, 0x24, 0xEB, + 0x6F, 0xAE, 0x02, 0x32, 0x04, 0x07, 0x6F, 0x30, 0x9D, 0x75, 0xB9, 0x44, 0x73, 0x11, 0xEE, + 0x16, 0x89, 0xCF, 0x2F, 0x01, 0x40, 0x7B, 0xBA, 0x1F, 0x44, 0x5E, 0xBF, 0xBB, 0x3E, 0x1B, + 0x3E, 0x1B, 0x57, 0xC1, 0x69, 0xC0, 0x71, 0xDD, 0x40, 0x3C, 0x46, 0x21, 0xCD, 0x76, 0x61, + 0x64, 0xC5, 0x5E, 0xDF, 0x0F, 0xED, 0x3B, 0xE1, 0xFF, 0xEC, 0x76, 0x46, 0x9F, 0x86, 0x8B, + 0x88, 0xF6, 0x53, 0xAD, 0x20, 0x4D, 0x07, 0x0A, 0x9E, 0x17, 0x30, 0x49, 0xDD, 0x4D, 0x00, + 0xBD, 0x63, 0xE1, 0xEE, 0xDE, 0xBD, 0x6D, 0x15, + ]; let (_pk, sk) = MLKEM768::keygen_from_seed(&seed).unwrap(); let ss = MLKEM768::decaps(&sk, &ct).unwrap(); @@ -366,14 +1125,21 @@ fn bench_mlkem768_decaps() { } fn bench_mlkem768_lowmemory_decaps() { - use bouncycastle::mlkem_lowmemory::{MLKEMTrait, MLKEM768}; + use bouncycastle::mlkem_lowmemory::{MLKEM768, MLKEMTrait}; eprintln!("MLKEM768_lowmemory/Decaps"); let seed = KeyMaterial512::from_bytes_as_type( - &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ], KeyType::Seed, - ).unwrap(); + ) + .unwrap(); /* One-time setup of the KAT -- commented out so that we're not capturing keygen in the bench */ // let (pk, _sk) = MLKEM768::keygen_from_seed(&seed).unwrap(); @@ -381,7 +1147,81 @@ fn bench_mlkem768_lowmemory_decaps() { // use bouncycastle_hex as hex; // eprintln!("ct:\n{}", &hex::encode(ct)); - let ct: [u8; MLKEM768_CT_LEN] = [0xa8,0xf1,0x73,0xf0,0xf4,0x4b,0xb1,0xc7,0x68,0x12,0x9e,0xf4,0x26,0xea,0x35,0xd1,0x75,0xcf,0x94,0xc5,0xd4,0xae,0x86,0x46,0xcd,0xab,0xef,0x4a,0xa1,0x72,0x78,0x1b,0xbb,0xf8,0x09,0xdc,0x12,0xda,0x50,0x37,0xf6,0x00,0xea,0xf3,0xf7,0xda,0x77,0xa2,0x3d,0xc8,0x46,0x86,0xe6,0xb5,0xec,0xe3,0x72,0xde,0xbd,0xf7,0x8f,0x4b,0x2c,0x06,0xd0,0xea,0x7a,0x8d,0x2a,0xd6,0x78,0x20,0x6f,0x5d,0x51,0x57,0xfd,0x0d,0x7a,0xe0,0x18,0xcb,0x7c,0xba,0xdd,0x42,0x19,0x72,0xf5,0xcd,0xdb,0x86,0xec,0x8e,0x2e,0x4f,0x82,0x83,0x9d,0xc8,0xcc,0x98,0x67,0xec,0x0f,0x2c,0x3b,0x96,0x2f,0x59,0x17,0x7f,0x0f,0x98,0x1d,0x75,0xd8,0xed,0x97,0xfb,0x69,0x53,0xc5,0x5b,0x6a,0xdb,0x4a,0x19,0x60,0x51,0x8c,0xd9,0x59,0x7b,0xd8,0x40,0x1e,0x2d,0xb2,0x03,0xc2,0x69,0xc2,0x61,0x3f,0x0e,0x1f,0xa3,0x2e,0xa0,0x81,0xc4,0x25,0xd8,0x5d,0xfd,0x50,0x97,0x82,0x1f,0x47,0x0c,0x8e,0x99,0x48,0x62,0x4f,0x4b,0x97,0xd7,0x96,0x29,0x2f,0x85,0x0c,0x09,0x95,0xd7,0x72,0x51,0xac,0xc1,0xbb,0xfa,0x76,0x24,0xa5,0x11,0x89,0xe6,0x91,0x18,0x71,0x71,0x05,0x19,0x8b,0x10,0x53,0x1d,0x61,0xad,0x5b,0x13,0x2d,0x0c,0x4c,0x99,0xfa,0x7b,0xc5,0x34,0x4b,0xae,0x1c,0x70,0xd4,0x85,0x4d,0xa8,0x57,0x51,0x57,0xa7,0xd9,0x63,0x0b,0xd9,0x3d,0xa4,0x37,0x21,0xa8,0xf7,0x42,0xd3,0xe1,0x8c,0x8f,0x56,0xf5,0xab,0x31,0x22,0x17,0xe1,0xa7,0xa9,0xc7,0x7a,0x34,0xb7,0x1e,0x23,0x80,0x23,0x1a,0x2a,0x6c,0x9c,0xef,0xcb,0x40,0x04,0x00,0x37,0x26,0xac,0x03,0x69,0xe1,0xdd,0xc7,0x53,0xf3,0xd4,0x3a,0xde,0x56,0x5d,0xff,0x11,0xb7,0x9b,0xf0,0x82,0xc7,0x68,0x47,0xd7,0x4f,0xce,0xeb,0x07,0xa7,0x70,0x6b,0x94,0x91,0x17,0xf3,0xb7,0xfa,0x41,0x46,0xce,0x40,0xc6,0x50,0x51,0xbb,0x5b,0x82,0xce,0x27,0x1c,0x95,0xfd,0x77,0xd6,0xef,0xaa,0x24,0xd4,0x47,0x65,0xcc,0xbc,0xda,0xd6,0xdf,0xb5,0xb5,0x5d,0x01,0x42,0xb6,0x2f,0x91,0x3a,0x41,0x8a,0x82,0x83,0x4c,0x56,0xac,0x70,0x6c,0x40,0x05,0x00,0xe4,0x67,0x9e,0x64,0x24,0xc5,0x33,0xa0,0xb0,0xec,0x6a,0x3b,0x08,0x4c,0x12,0x40,0x3e,0x47,0x1f,0x7a,0x74,0x34,0x37,0xd7,0xc2,0x20,0x3a,0xca,0xeb,0xcf,0x22,0x87,0x23,0x89,0xda,0x78,0x6e,0xff,0xf0,0x7e,0x57,0x99,0x6b,0x0c,0xa8,0x95,0x8f,0xe1,0x90,0x81,0xe6,0x9e,0xc9,0x63,0x91,0xb2,0x61,0xda,0x0a,0x90,0xb0,0x99,0xa1,0xf9,0xdb,0x12,0x08,0xac,0xfc,0x5f,0x0f,0xf1,0xa9,0x04,0xef,0xee,0xa0,0xfe,0x2c,0x42,0x26,0x00,0xa0,0x3f,0xb5,0xa7,0x44,0x19,0x2e,0x0c,0x50,0xf7,0x0f,0x84,0x76,0xf0,0x5c,0x3a,0xb6,0xcb,0x8c,0xd9,0xa2,0x12,0x1c,0x2f,0x4f,0xb9,0x3b,0x53,0x44,0x89,0xf7,0x5d,0xb6,0x97,0xb4,0x80,0x4a,0x44,0xaa,0x3e,0x15,0x8b,0xa1,0x5f,0x0b,0x3c,0x8d,0x3b,0xe0,0x69,0x83,0xd4,0x57,0xdc,0x93,0xa9,0x6a,0x84,0x04,0x53,0x41,0x89,0x59,0xfe,0x5f,0xb6,0xdf,0xc0,0x6a,0x3b,0x2c,0xd3,0xae,0x3e,0x48,0x3e,0x1e,0xe0,0xac,0x74,0x98,0xda,0x0a,0x70,0x65,0xb9,0x46,0x48,0x80,0x64,0x89,0xb6,0xce,0x9f,0xfd,0xce,0x53,0xb8,0x61,0xa0,0x7f,0xed,0xbc,0xa7,0x9b,0x1b,0xc8,0x9b,0xe7,0xb5,0xa2,0x58,0x76,0x5e,0x2c,0xc9,0x09,0xc4,0x89,0x30,0xda,0x50,0xb2,0x38,0xfd,0x6c,0x95,0x7e,0x90,0xab,0x53,0x6a,0x27,0xfa,0x63,0xf5,0xfe,0xa3,0xe2,0x9a,0x2e,0x7a,0x33,0xbf,0x9f,0xb9,0x0e,0xb3,0x8d,0xee,0x0d,0xc2,0xa6,0xd9,0x2f,0x9c,0xec,0x0e,0x78,0xa0,0xd0,0x96,0x47,0xb6,0x51,0x62,0x25,0x07,0x3e,0x6b,0x35,0x00,0xa1,0x49,0xb6,0xe4,0x27,0x27,0x33,0xe4,0xe0,0x5e,0xa8,0x4a,0x0a,0x45,0x67,0x2f,0x62,0xe9,0xa5,0x4f,0xa1,0x76,0xee,0xa6,0x10,0x22,0xd4,0xfc,0xda,0x55,0x3d,0x5b,0xaa,0xb1,0x84,0xd0,0x8a,0xf4,0xb8,0x06,0xbc,0x40,0xc4,0x22,0x9d,0xaf,0x7b,0x5f,0x64,0x4f,0x1a,0xc8,0xd0,0xd4,0xa1,0xa4,0x8a,0xe6,0xb6,0xf2,0xbf,0xaa,0xe5,0xce,0x5a,0xc4,0x6c,0x8b,0x4f,0x1a,0xc8,0x41,0xf9,0xc8,0x2b,0x57,0xb4,0x37,0xd0,0x91,0x7b,0x80,0x5c,0x46,0x88,0x05,0xa3,0x06,0xe9,0x2f,0xb1,0x68,0xaf,0xa8,0xbd,0x34,0xef,0x41,0xeb,0x57,0x57,0x70,0x72,0xd8,0x56,0x83,0xac,0xbe,0x72,0xac,0x9d,0x06,0x10,0x95,0xe5,0xf4,0xd8,0xba,0x1a,0xb7,0x91,0xf9,0xc2,0xb9,0x24,0xc8,0x1e,0xe5,0x33,0xd5,0x81,0x1e,0x15,0x54,0x5e,0xbb,0x01,0x92,0xe8,0xec,0x4e,0xec,0x4e,0xa4,0x95,0x28,0x9a,0x27,0xfd,0x67,0xe5,0x20,0xcf,0x72,0xd7,0xd5,0x95,0x14,0xc0,0x35,0x94,0x66,0x78,0x96,0xed,0x41,0x11,0xf1,0xb2,0x1f,0x0a,0xed,0x19,0xbb,0xf9,0xca,0x4b,0xcb,0x54,0x68,0xe3,0x09,0xca,0xa7,0x45,0xf4,0x0c,0xbf,0x25,0x41,0xa2,0x70,0xa6,0xd6,0x05,0x2b,0x7e,0xd7,0x1e,0x83,0x32,0x8e,0xac,0x0a,0xa3,0xde,0x03,0xeb,0x7c,0x9a,0xde,0x04,0x74,0xab,0x0e,0x42,0x67,0xfb,0xae,0xe5,0xb6,0x8d,0xac,0x44,0x66,0x55,0xdd,0xbb,0x70,0xaf,0x44,0xc1,0x90,0xfb,0x16,0xa0,0x8e,0x98,0xdb,0xf6,0x36,0x94,0xf7,0x04,0xe0,0x7f,0x2b,0xdc,0xee,0x5a,0xbd,0xb6,0x05,0x4e,0x78,0xb5,0x54,0x41,0x22,0xcc,0x93,0xa0,0xbc,0xcd,0x4a,0x8a,0x89,0xc6,0x3c,0x30,0x7b,0x1f,0x4c,0x7d,0xc4,0x2c,0x65,0xfa,0xb5,0xd8,0x95,0x76,0x1b,0x88,0xad,0xc6,0x4a,0x99,0x53,0xc1,0xe5,0x96,0xe0,0x05,0x54,0xd8,0x64,0xd1,0x00,0x2e,0xc6,0x53,0xe8,0x5a,0xf1,0x71,0x72,0x6a,0x6b,0xc2,0x32,0xf0,0xae,0x08,0x1d,0x63,0x76,0xa9,0xa5,0xa0,0x57,0x34,0x6e,0x77,0x54,0x2f,0x73,0x4d,0x1b,0x12,0x7d,0x5d,0xbf,0xae,0x8f,0x5d,0x50,0xbb,0x0d,0x05,0x22,0x9b,0xe2,0xc5,0xd8,0x40,0x3d,0xdb,0xa6,0xdf,0x8f,0xba,0x23,0xa6,0x46,0x0a,0x4c,0x65,0x5d,0x9f,0xbb,0xed,0xff,0x60,0x3a,0x7e,0xa9,0xa4,0xff,0xb5,0x83,0xcf,0xb8,0x95,0xdb,0x37,0x54,0x35,0xdd,0x31,0xf2,0x9f,0x2a,0x8a,0xa2,0x33,0x3b,0x9b,0x48,0x4f,0x33,0xc9,0x70,0xe8,0x07,0xbb,0xd6,0x24,0xeb,0x6f,0xae,0x02,0x32,0x04,0x07,0x6f,0x30,0x9d,0x75,0xb9,0x44,0x73,0x11,0xee,0x16,0x89,0xcf,0x2f,0x01,0x40,0x7b,0xba,0x1f,0x44,0x5e,0xbf,0xbb,0x3e,0x1b,0x3e,0x1b,0x57,0xc1,0x69,0xc0,0x71,0xdd,0x40,0x3c,0x46,0x21,0xcd,0x76,0x61,0x64,0xc5,0x5e,0xdf,0x0f,0xed,0x3b,0xe1,0xff,0xec,0x76,0x46,0x9f,0x86,0x8b,0x88,0xf6,0x53,0xad,0x20,0x4d,0x07,0x0a,0x9e,0x17,0x30,0x49,0xdd,0x4d,0x00,0xbd,0x63,0xe1,0xee,0xde,0xbd,0x6d,0x15]; + let ct: [u8; MLKEM768_CT_LEN] = [ + 0xA8, 0xF1, 0x73, 0xF0, 0xF4, 0x4B, 0xB1, 0xC7, 0x68, 0x12, 0x9E, 0xF4, 0x26, 0xEA, 0x35, + 0xD1, 0x75, 0xCF, 0x94, 0xC5, 0xD4, 0xAE, 0x86, 0x46, 0xCD, 0xAB, 0xEF, 0x4A, 0xA1, 0x72, + 0x78, 0x1B, 0xBB, 0xF8, 0x09, 0xDC, 0x12, 0xDA, 0x50, 0x37, 0xF6, 0x00, 0xEA, 0xF3, 0xF7, + 0xDA, 0x77, 0xA2, 0x3D, 0xC8, 0x46, 0x86, 0xE6, 0xB5, 0xEC, 0xE3, 0x72, 0xDE, 0xBD, 0xF7, + 0x8F, 0x4B, 0x2C, 0x06, 0xD0, 0xEA, 0x7A, 0x8D, 0x2A, 0xD6, 0x78, 0x20, 0x6F, 0x5D, 0x51, + 0x57, 0xFD, 0x0D, 0x7A, 0xE0, 0x18, 0xCB, 0x7C, 0xBA, 0xDD, 0x42, 0x19, 0x72, 0xF5, 0xCD, + 0xDB, 0x86, 0xEC, 0x8E, 0x2E, 0x4F, 0x82, 0x83, 0x9D, 0xC8, 0xCC, 0x98, 0x67, 0xEC, 0x0F, + 0x2C, 0x3B, 0x96, 0x2F, 0x59, 0x17, 0x7F, 0x0F, 0x98, 0x1D, 0x75, 0xD8, 0xED, 0x97, 0xFB, + 0x69, 0x53, 0xC5, 0x5B, 0x6A, 0xDB, 0x4A, 0x19, 0x60, 0x51, 0x8C, 0xD9, 0x59, 0x7B, 0xD8, + 0x40, 0x1E, 0x2D, 0xB2, 0x03, 0xC2, 0x69, 0xC2, 0x61, 0x3F, 0x0E, 0x1F, 0xA3, 0x2E, 0xA0, + 0x81, 0xC4, 0x25, 0xD8, 0x5D, 0xFD, 0x50, 0x97, 0x82, 0x1F, 0x47, 0x0C, 0x8E, 0x99, 0x48, + 0x62, 0x4F, 0x4B, 0x97, 0xD7, 0x96, 0x29, 0x2F, 0x85, 0x0C, 0x09, 0x95, 0xD7, 0x72, 0x51, + 0xAC, 0xC1, 0xBB, 0xFA, 0x76, 0x24, 0xA5, 0x11, 0x89, 0xE6, 0x91, 0x18, 0x71, 0x71, 0x05, + 0x19, 0x8B, 0x10, 0x53, 0x1D, 0x61, 0xAD, 0x5B, 0x13, 0x2D, 0x0C, 0x4C, 0x99, 0xFA, 0x7B, + 0xC5, 0x34, 0x4B, 0xAE, 0x1C, 0x70, 0xD4, 0x85, 0x4D, 0xA8, 0x57, 0x51, 0x57, 0xA7, 0xD9, + 0x63, 0x0B, 0xD9, 0x3D, 0xA4, 0x37, 0x21, 0xA8, 0xF7, 0x42, 0xD3, 0xE1, 0x8C, 0x8F, 0x56, + 0xF5, 0xAB, 0x31, 0x22, 0x17, 0xE1, 0xA7, 0xA9, 0xC7, 0x7A, 0x34, 0xB7, 0x1E, 0x23, 0x80, + 0x23, 0x1A, 0x2A, 0x6C, 0x9C, 0xEF, 0xCB, 0x40, 0x04, 0x00, 0x37, 0x26, 0xAC, 0x03, 0x69, + 0xE1, 0xDD, 0xC7, 0x53, 0xF3, 0xD4, 0x3A, 0xDE, 0x56, 0x5D, 0xFF, 0x11, 0xB7, 0x9B, 0xF0, + 0x82, 0xC7, 0x68, 0x47, 0xD7, 0x4F, 0xCE, 0xEB, 0x07, 0xA7, 0x70, 0x6B, 0x94, 0x91, 0x17, + 0xF3, 0xB7, 0xFA, 0x41, 0x46, 0xCE, 0x40, 0xC6, 0x50, 0x51, 0xBB, 0x5B, 0x82, 0xCE, 0x27, + 0x1C, 0x95, 0xFD, 0x77, 0xD6, 0xEF, 0xAA, 0x24, 0xD4, 0x47, 0x65, 0xCC, 0xBC, 0xDA, 0xD6, + 0xDF, 0xB5, 0xB5, 0x5D, 0x01, 0x42, 0xB6, 0x2F, 0x91, 0x3A, 0x41, 0x8A, 0x82, 0x83, 0x4C, + 0x56, 0xAC, 0x70, 0x6C, 0x40, 0x05, 0x00, 0xE4, 0x67, 0x9E, 0x64, 0x24, 0xC5, 0x33, 0xA0, + 0xB0, 0xEC, 0x6A, 0x3B, 0x08, 0x4C, 0x12, 0x40, 0x3E, 0x47, 0x1F, 0x7A, 0x74, 0x34, 0x37, + 0xD7, 0xC2, 0x20, 0x3A, 0xCA, 0xEB, 0xCF, 0x22, 0x87, 0x23, 0x89, 0xDA, 0x78, 0x6E, 0xFF, + 0xF0, 0x7E, 0x57, 0x99, 0x6B, 0x0C, 0xA8, 0x95, 0x8F, 0xE1, 0x90, 0x81, 0xE6, 0x9E, 0xC9, + 0x63, 0x91, 0xB2, 0x61, 0xDA, 0x0A, 0x90, 0xB0, 0x99, 0xA1, 0xF9, 0xDB, 0x12, 0x08, 0xAC, + 0xFC, 0x5F, 0x0F, 0xF1, 0xA9, 0x04, 0xEF, 0xEE, 0xA0, 0xFE, 0x2C, 0x42, 0x26, 0x00, 0xA0, + 0x3F, 0xB5, 0xA7, 0x44, 0x19, 0x2E, 0x0C, 0x50, 0xF7, 0x0F, 0x84, 0x76, 0xF0, 0x5C, 0x3A, + 0xB6, 0xCB, 0x8C, 0xD9, 0xA2, 0x12, 0x1C, 0x2F, 0x4F, 0xB9, 0x3B, 0x53, 0x44, 0x89, 0xF7, + 0x5D, 0xB6, 0x97, 0xB4, 0x80, 0x4A, 0x44, 0xAA, 0x3E, 0x15, 0x8B, 0xA1, 0x5F, 0x0B, 0x3C, + 0x8D, 0x3B, 0xE0, 0x69, 0x83, 0xD4, 0x57, 0xDC, 0x93, 0xA9, 0x6A, 0x84, 0x04, 0x53, 0x41, + 0x89, 0x59, 0xFE, 0x5F, 0xB6, 0xDF, 0xC0, 0x6A, 0x3B, 0x2C, 0xD3, 0xAE, 0x3E, 0x48, 0x3E, + 0x1E, 0xE0, 0xAC, 0x74, 0x98, 0xDA, 0x0A, 0x70, 0x65, 0xB9, 0x46, 0x48, 0x80, 0x64, 0x89, + 0xB6, 0xCE, 0x9F, 0xFD, 0xCE, 0x53, 0xB8, 0x61, 0xA0, 0x7F, 0xED, 0xBC, 0xA7, 0x9B, 0x1B, + 0xC8, 0x9B, 0xE7, 0xB5, 0xA2, 0x58, 0x76, 0x5E, 0x2C, 0xC9, 0x09, 0xC4, 0x89, 0x30, 0xDA, + 0x50, 0xB2, 0x38, 0xFD, 0x6C, 0x95, 0x7E, 0x90, 0xAB, 0x53, 0x6A, 0x27, 0xFA, 0x63, 0xF5, + 0xFE, 0xA3, 0xE2, 0x9A, 0x2E, 0x7A, 0x33, 0xBF, 0x9F, 0xB9, 0x0E, 0xB3, 0x8D, 0xEE, 0x0D, + 0xC2, 0xA6, 0xD9, 0x2F, 0x9C, 0xEC, 0x0E, 0x78, 0xA0, 0xD0, 0x96, 0x47, 0xB6, 0x51, 0x62, + 0x25, 0x07, 0x3E, 0x6B, 0x35, 0x00, 0xA1, 0x49, 0xB6, 0xE4, 0x27, 0x27, 0x33, 0xE4, 0xE0, + 0x5E, 0xA8, 0x4A, 0x0A, 0x45, 0x67, 0x2F, 0x62, 0xE9, 0xA5, 0x4F, 0xA1, 0x76, 0xEE, 0xA6, + 0x10, 0x22, 0xD4, 0xFC, 0xDA, 0x55, 0x3D, 0x5B, 0xAA, 0xB1, 0x84, 0xD0, 0x8A, 0xF4, 0xB8, + 0x06, 0xBC, 0x40, 0xC4, 0x22, 0x9D, 0xAF, 0x7B, 0x5F, 0x64, 0x4F, 0x1A, 0xC8, 0xD0, 0xD4, + 0xA1, 0xA4, 0x8A, 0xE6, 0xB6, 0xF2, 0xBF, 0xAA, 0xE5, 0xCE, 0x5A, 0xC4, 0x6C, 0x8B, 0x4F, + 0x1A, 0xC8, 0x41, 0xF9, 0xC8, 0x2B, 0x57, 0xB4, 0x37, 0xD0, 0x91, 0x7B, 0x80, 0x5C, 0x46, + 0x88, 0x05, 0xA3, 0x06, 0xE9, 0x2F, 0xB1, 0x68, 0xAF, 0xA8, 0xBD, 0x34, 0xEF, 0x41, 0xEB, + 0x57, 0x57, 0x70, 0x72, 0xD8, 0x56, 0x83, 0xAC, 0xBE, 0x72, 0xAC, 0x9D, 0x06, 0x10, 0x95, + 0xE5, 0xF4, 0xD8, 0xBA, 0x1A, 0xB7, 0x91, 0xF9, 0xC2, 0xB9, 0x24, 0xC8, 0x1E, 0xE5, 0x33, + 0xD5, 0x81, 0x1E, 0x15, 0x54, 0x5E, 0xBB, 0x01, 0x92, 0xE8, 0xEC, 0x4E, 0xEC, 0x4E, 0xA4, + 0x95, 0x28, 0x9A, 0x27, 0xFD, 0x67, 0xE5, 0x20, 0xCF, 0x72, 0xD7, 0xD5, 0x95, 0x14, 0xC0, + 0x35, 0x94, 0x66, 0x78, 0x96, 0xED, 0x41, 0x11, 0xF1, 0xB2, 0x1F, 0x0A, 0xED, 0x19, 0xBB, + 0xF9, 0xCA, 0x4B, 0xCB, 0x54, 0x68, 0xE3, 0x09, 0xCA, 0xA7, 0x45, 0xF4, 0x0C, 0xBF, 0x25, + 0x41, 0xA2, 0x70, 0xA6, 0xD6, 0x05, 0x2B, 0x7E, 0xD7, 0x1E, 0x83, 0x32, 0x8E, 0xAC, 0x0A, + 0xA3, 0xDE, 0x03, 0xEB, 0x7C, 0x9A, 0xDE, 0x04, 0x74, 0xAB, 0x0E, 0x42, 0x67, 0xFB, 0xAE, + 0xE5, 0xB6, 0x8D, 0xAC, 0x44, 0x66, 0x55, 0xDD, 0xBB, 0x70, 0xAF, 0x44, 0xC1, 0x90, 0xFB, + 0x16, 0xA0, 0x8E, 0x98, 0xDB, 0xF6, 0x36, 0x94, 0xF7, 0x04, 0xE0, 0x7F, 0x2B, 0xDC, 0xEE, + 0x5A, 0xBD, 0xB6, 0x05, 0x4E, 0x78, 0xB5, 0x54, 0x41, 0x22, 0xCC, 0x93, 0xA0, 0xBC, 0xCD, + 0x4A, 0x8A, 0x89, 0xC6, 0x3C, 0x30, 0x7B, 0x1F, 0x4C, 0x7D, 0xC4, 0x2C, 0x65, 0xFA, 0xB5, + 0xD8, 0x95, 0x76, 0x1B, 0x88, 0xAD, 0xC6, 0x4A, 0x99, 0x53, 0xC1, 0xE5, 0x96, 0xE0, 0x05, + 0x54, 0xD8, 0x64, 0xD1, 0x00, 0x2E, 0xC6, 0x53, 0xE8, 0x5A, 0xF1, 0x71, 0x72, 0x6A, 0x6B, + 0xC2, 0x32, 0xF0, 0xAE, 0x08, 0x1D, 0x63, 0x76, 0xA9, 0xA5, 0xA0, 0x57, 0x34, 0x6E, 0x77, + 0x54, 0x2F, 0x73, 0x4D, 0x1B, 0x12, 0x7D, 0x5D, 0xBF, 0xAE, 0x8F, 0x5D, 0x50, 0xBB, 0x0D, + 0x05, 0x22, 0x9B, 0xE2, 0xC5, 0xD8, 0x40, 0x3D, 0xDB, 0xA6, 0xDF, 0x8F, 0xBA, 0x23, 0xA6, + 0x46, 0x0A, 0x4C, 0x65, 0x5D, 0x9F, 0xBB, 0xED, 0xFF, 0x60, 0x3A, 0x7E, 0xA9, 0xA4, 0xFF, + 0xB5, 0x83, 0xCF, 0xB8, 0x95, 0xDB, 0x37, 0x54, 0x35, 0xDD, 0x31, 0xF2, 0x9F, 0x2A, 0x8A, + 0xA2, 0x33, 0x3B, 0x9B, 0x48, 0x4F, 0x33, 0xC9, 0x70, 0xE8, 0x07, 0xBB, 0xD6, 0x24, 0xEB, + 0x6F, 0xAE, 0x02, 0x32, 0x04, 0x07, 0x6F, 0x30, 0x9D, 0x75, 0xB9, 0x44, 0x73, 0x11, 0xEE, + 0x16, 0x89, 0xCF, 0x2F, 0x01, 0x40, 0x7B, 0xBA, 0x1F, 0x44, 0x5E, 0xBF, 0xBB, 0x3E, 0x1B, + 0x3E, 0x1B, 0x57, 0xC1, 0x69, 0xC0, 0x71, 0xDD, 0x40, 0x3C, 0x46, 0x21, 0xCD, 0x76, 0x61, + 0x64, 0xC5, 0x5E, 0xDF, 0x0F, 0xED, 0x3B, 0xE1, 0xFF, 0xEC, 0x76, 0x46, 0x9F, 0x86, 0x8B, + 0x88, 0xF6, 0x53, 0xAD, 0x20, 0x4D, 0x07, 0x0A, 0x9E, 0x17, 0x30, 0x49, 0xDD, 0x4D, 0x00, + 0xBD, 0x63, 0xE1, 0xEE, 0xDE, 0xBD, 0x6D, 0x15, + ]; let (_pk, sk) = MLKEM768::keygen_from_seed(&seed).unwrap(); let ss = MLKEM768::decaps(&sk, &ct).unwrap(); @@ -389,14 +1229,21 @@ fn bench_mlkem768_lowmemory_decaps() { } fn bench_mlkem1024_decaps() { - use bouncycastle::mlkem::{MLKEMTrait, MLKEM1024}; + use bouncycastle::mlkem::{MLKEM1024, MLKEMTrait}; eprintln!("MLKEM1024/Decaps"); let seed = KeyMaterial512::from_bytes_as_type( - &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ], KeyType::Seed, - ).unwrap(); + ) + .unwrap(); /* One-time setup of the KAT -- commented out so that we're not capturing keygen in the bench */ // let (pk, _sk) = MLKEM1024::keygen_from_seed(&seed).unwrap(); @@ -404,7 +1251,113 @@ fn bench_mlkem1024_decaps() { // use bouncycastle_hex as hex; // eprintln!("ct:\n{}", &hex::encode(ct)); - let ct: [u8; MLKEM1024_CT_LEN] = [0x6b,0x15,0x08,0x82,0x0e,0x30,0x0e,0x5c,0xfe,0xb3,0xd9,0xd3,0x33,0xf2,0xdf,0x3f,0x6a,0x91,0xb7,0x40,0x07,0x61,0xf0,0x7b,0xf6,0x83,0xf8,0xed,0xcd,0xbe,0x14,0xa0,0xac,0x3f,0x32,0x26,0x0b,0x9b,0x7e,0x74,0xe9,0xa8,0x6e,0x44,0xd5,0x3b,0xa5,0x3b,0xb9,0x1c,0x9a,0x9d,0x4e,0x15,0x7f,0xe5,0x82,0x11,0x5f,0xba,0x56,0x8c,0x29,0x2f,0x2b,0xb9,0x62,0xaa,0x20,0x50,0x41,0xe8,0xd6,0x9d,0xb7,0xa9,0xd7,0x5e,0xaa,0xaa,0xa0,0x21,0xe4,0x5b,0xca,0x83,0x2c,0xa1,0x5b,0xb4,0x4e,0xba,0xa7,0x0e,0x8b,0x95,0x83,0x9b,0xce,0x92,0xf0,0x7c,0x2e,0x29,0xfc,0xca,0x0d,0x7b,0x94,0x00,0x6f,0x99,0x44,0x31,0x40,0x0b,0xf7,0xd6,0xb9,0x34,0x8d,0x2f,0x8a,0x3f,0x57,0x8b,0x52,0x16,0x47,0x50,0xe4,0xaa,0x7d,0x8d,0xda,0xda,0xc1,0x80,0x23,0x21,0x7c,0x26,0xfb,0x4e,0x3a,0xb0,0xec,0x34,0xc3,0x23,0x5d,0xe1,0x2b,0x2b,0xfa,0xf2,0xc3,0x36,0x89,0xd4,0xa5,0x3f,0xe3,0x13,0xcb,0xd2,0x8a,0xbb,0x9d,0xbe,0x23,0x0a,0x35,0x9e,0x41,0x21,0xed,0x9f,0x98,0xf1,0x2f,0x62,0xd1,0x4a,0x9f,0xe8,0x6c,0x46,0x60,0x2f,0xa7,0xc9,0x5d,0x25,0xba,0xcd,0x2c,0xda,0x33,0xd5,0x0b,0xa7,0xb5,0xe2,0xc0,0xb2,0x98,0x17,0x09,0x35,0x8d,0x8f,0xc4,0xe8,0x9e,0x63,0x29,0x67,0xf7,0x88,0xb9,0x34,0xe8,0x9c,0x93,0xbd,0x19,0xcb,0x62,0xd7,0x73,0x7f,0x56,0x5a,0x53,0x25,0xa0,0xc0,0x54,0xf4,0xc4,0xfb,0x27,0x9b,0x1b,0x8f,0x63,0xc2,0x1f,0xd3,0x68,0x0c,0xb8,0x0d,0x35,0x2a,0xc2,0xa9,0x03,0x57,0x24,0x32,0x00,0xa7,0xaa,0xe1,0x60,0xe1,0x26,0xa5,0xbe,0x5f,0xf8,0xf6,0xed,0x4f,0xab,0x22,0x30,0xd9,0x8e,0x1b,0x28,0xfd,0xa6,0xb9,0xd9,0xc5,0xe4,0xdf,0x18,0x85,0xed,0x12,0x54,0x2d,0x98,0xcb,0x1c,0xf0,0xec,0x95,0x9f,0x52,0xb9,0xb7,0x09,0xe6,0xb2,0x8c,0xf1,0xe5,0xa1,0x67,0x23,0x32,0xc8,0x78,0xba,0xf1,0xfd,0x8e,0x5f,0x49,0x1b,0x06,0xae,0xcf,0x5a,0x5d,0x2a,0xd2,0x4c,0x97,0x34,0xf3,0x50,0x08,0xe2,0xdd,0xf6,0x1e,0x4c,0x4f,0x4b,0xdf,0x48,0x42,0x6b,0xbc,0x63,0xde,0x9a,0xe7,0xee,0x5a,0x5d,0x67,0xf3,0x51,0x30,0x27,0xbd,0x68,0xc8,0xc3,0x7f,0x90,0x5b,0x75,0xc1,0x39,0x7d,0x38,0xcc,0xdf,0xe6,0x08,0x79,0xfc,0xbe,0xbe,0xe2,0xce,0xbf,0x19,0x12,0x80,0xb0,0xb8,0xaf,0xba,0xca,0x3d,0x1e,0x03,0xf2,0xaa,0x91,0x11,0x16,0x39,0x34,0xe1,0x28,0xe6,0xea,0x1c,0xc2,0x15,0xb7,0xf3,0x6f,0xb9,0x9c,0x2d,0xaa,0x27,0x25,0xed,0x3a,0x77,0xe9,0x30,0x4f,0x18,0x12,0x0a,0x19,0x78,0x97,0x0c,0xa7,0x60,0x5c,0x8a,0x3c,0x67,0xef,0x3f,0xd3,0x1b,0x02,0x7b,0x06,0x2a,0x35,0x8e,0x32,0xfa,0x48,0xe4,0xb0,0xef,0x31,0xd1,0x1f,0xe0,0x5e,0x8e,0x71,0x0e,0x9a,0x60,0x08,0xb5,0x4b,0xd6,0xac,0x93,0x78,0xc9,0x8c,0x62,0x7b,0x12,0x59,0x82,0x3d,0x6f,0x3e,0xf4,0xf0,0xef,0x03,0x81,0x4e,0x15,0xed,0xde,0x93,0xf7,0x34,0x84,0xe9,0x48,0x27,0x3d,0x76,0x64,0xbf,0xe6,0x60,0x47,0xfc,0x31,0xc4,0x68,0xc8,0x77,0x46,0x78,0xd2,0x7b,0x16,0xb1,0xc0,0xda,0xb8,0x80,0xd1,0xd7,0x16,0xd4,0xdb,0x28,0x89,0x49,0xe3,0x35,0x11,0x17,0x90,0xf0,0xe6,0x6d,0x65,0x29,0xb7,0x2a,0x9b,0x18,0x2f,0xe0,0xb4,0x37,0xaa,0xac,0x2b,0x1f,0xfc,0x09,0x79,0xc1,0x48,0x5c,0x0e,0x16,0x38,0x36,0xc3,0xa5,0xce,0x49,0xc5,0xc8,0x88,0xd3,0xef,0xc8,0xdf,0xd6,0xbc,0x91,0x73,0x9b,0xad,0x0a,0xdd,0x04,0xd9,0x20,0xd3,0x88,0x42,0x28,0x80,0x3a,0xaa,0x2a,0x23,0xd9,0xad,0x75,0xd5,0xd3,0x9b,0x40,0x0e,0x04,0xc9,0xed,0xc2,0x91,0x69,0x7b,0xb4,0xc7,0x1a,0x22,0x91,0xec,0xd8,0x95,0x8b,0x02,0xf0,0x41,0x56,0x11,0x61,0x37,0x68,0x2d,0xd0,0xf3,0x84,0x93,0x14,0x3c,0x91,0x1c,0xf8,0x72,0xf5,0x39,0x8f,0x07,0x83,0x7d,0xf5,0x20,0x1b,0xf6,0x6a,0x06,0xc1,0x4a,0xe2,0x60,0x45,0x69,0xd4,0x27,0xe9,0xdc,0x15,0xb3,0x01,0xa3,0xa9,0xfc,0x7c,0xfb,0xa5,0x02,0x64,0xfc,0x73,0x79,0xe2,0xba,0x83,0xee,0xee,0x68,0xdc,0x33,0x52,0x87,0x74,0xba,0x67,0xfc,0x1e,0x51,0xed,0x3b,0xc4,0x08,0x1b,0xdd,0x3b,0x18,0x16,0xd4,0x0f,0x61,0xbb,0xcf,0x72,0x11,0xd9,0xf4,0x12,0xe1,0x22,0x7f,0x3f,0xbc,0x5d,0x04,0x76,0xf0,0x32,0x86,0x45,0x4e,0xab,0xd5,0xd2,0xa2,0x25,0xaa,0x27,0xa9,0x61,0x61,0x6e,0x24,0xe7,0x53,0x2f,0x28,0x03,0x06,0x64,0xdf,0xc2,0xec,0xbc,0xc5,0xbe,0x77,0x9a,0xf9,0x39,0x92,0xe6,0x5d,0x1c,0x85,0xe2,0x10,0x68,0x8f,0x2b,0x6b,0x91,0xcc,0xc9,0xf1,0xdb,0x32,0x6d,0xd9,0x47,0x53,0xc3,0xaa,0xae,0xd4,0x57,0x1c,0x20,0x4f,0x97,0xc9,0xe1,0x87,0x1f,0xfe,0xcd,0xee,0xf0,0x7b,0x88,0xde,0x4f,0x17,0xf3,0xce,0x40,0xa5,0x8d,0x01,0x5f,0xbe,0xdb,0x8a,0x01,0x1c,0x61,0x8f,0xbb,0x03,0x99,0x87,0x63,0xbc,0x60,0xe7,0x8c,0x3c,0x27,0xab,0xd3,0x70,0x3d,0x67,0xb8,0x6e,0x3a,0x82,0x84,0xfe,0x67,0xd9,0xeb,0x59,0xfc,0x21,0x69,0x39,0x29,0x15,0x7f,0xdb,0x0a,0xe4,0x37,0xa7,0x36,0xc2,0xcf,0xb5,0xb6,0x14,0xd9,0xb8,0x47,0x63,0x5c,0x1b,0x8d,0x04,0x75,0x7c,0xa6,0x2f,0x15,0xf4,0xd5,0x36,0xc7,0x2d,0x7a,0x71,0xd7,0x41,0xd8,0xa0,0x7d,0xd6,0xa8,0x28,0x90,0xb8,0xe1,0xf5,0xad,0x59,0xb1,0x7e,0x5c,0x85,0xfd,0xd7,0x08,0x17,0x76,0xef,0xaa,0x0e,0x29,0x17,0x14,0xde,0xb9,0x79,0xd5,0xe5,0x44,0xbd,0x8b,0xe9,0xf7,0x9a,0x87,0x7e,0x4b,0xad,0x28,0x24,0x6a,0x39,0x33,0x00,0x56,0x97,0x00,0x4b,0xfb,0xe3,0x24,0x23,0xaa,0xda,0x98,0x02,0xc5,0x6f,0xe1,0xa6,0x53,0xa5,0xcb,0x95,0x7d,0x47,0x20,0xf5,0x5d,0x5f,0x40,0x10,0xdb,0x40,0x22,0xa2,0xca,0x49,0xec,0xf5,0xe7,0xdd,0x01,0x45,0xe5,0x82,0xa9,0xbc,0xeb,0x77,0x3a,0x45,0x09,0x7b,0x29,0x9a,0x3b,0x0d,0xc4,0x3b,0x34,0x5d,0x16,0x37,0xe8,0x8f,0xc1,0xd8,0x3e,0x41,0x4e,0x24,0xa0,0xf6,0xbd,0x97,0x75,0x73,0xef,0x52,0x3b,0xba,0x8b,0xa9,0x86,0x45,0x15,0xac,0x71,0xec,0xa5,0xdf,0xef,0xda,0x02,0x3c,0xad,0x07,0xbd,0x88,0x74,0x2b,0x52,0x1f,0x63,0x6b,0xa7,0x08,0xfb,0xa4,0x20,0x81,0x48,0x22,0xae,0x91,0x32,0x75,0xa8,0x51,0xb9,0x0f,0x34,0x62,0xb6,0x4b,0xf9,0x88,0xf8,0xba,0x27,0x18,0xb4,0x9f,0x78,0xca,0xb5,0xba,0xc4,0x9f,0x02,0xcb,0x50,0xf3,0x82,0x1c,0x3a,0x35,0x6d,0x99,0x45,0xc4,0xba,0x8d,0xba,0xb7,0x47,0x0c,0x97,0x79,0x68,0xf7,0xb0,0xcd,0x66,0xb0,0x7b,0xfa,0xcb,0x39,0x7c,0x97,0x38,0x9e,0xb4,0x01,0xc9,0xe7,0x85,0xfa,0x7a,0x98,0x0e,0x89,0xc2,0xf8,0xab,0x0d,0x8a,0xd9,0x1f,0xa2,0xbe,0xf2,0x52,0xa3,0x79,0x25,0x21,0x89,0xf1,0x53,0x7c,0x40,0x4e,0xa3,0x18,0x5a,0xd8,0xf1,0xab,0xf1,0x72,0xce,0x31,0x01,0x5f,0xa5,0xdc,0x4e,0x9a,0xe5,0x44,0x66,0x7a,0xa2,0x12,0x98,0xf0,0x1d,0xb5,0xd9,0xe2,0xc5,0x52,0xc2,0x85,0xd0,0x7a,0x8b,0xc9,0xf5,0xe7,0x69,0xef,0x42,0x73,0x2f,0x08,0x69,0x0c,0xca,0x61,0xd0,0x61,0x34,0x53,0x4e,0x07,0x00,0xef,0x4c,0xc7,0x82,0x70,0x2f,0x30,0x0e,0xb9,0x4a,0x0f,0xf4,0x06,0x5c,0x11,0xff,0x13,0xcf,0x2a,0x3e,0x2d,0x1f,0x85,0x7f,0x3e,0x8e,0xb5,0xdc,0x70,0x51,0xf3,0x1f,0xd6,0xeb,0xf2,0x56,0xa1,0xc5,0xa4,0xee,0x72,0x62,0xb2,0x42,0xdf,0x5f,0xa4,0x6d,0xce,0x43,0x7d,0x20,0xfd,0xf8,0x11,0x82,0xfe,0xac,0x60,0x8a,0xaf,0x51,0x5b,0xfa,0xed,0xa5,0x24,0xc8,0xab,0x1c,0xca,0xc2,0x5e,0x0b,0x76,0x81,0xe3,0x85,0x64,0x5c,0xcf,0xf5,0x33,0x73,0x1e,0x7d,0x11,0x2e,0x22,0x15,0xb3,0x88,0x85,0x52,0x43,0x31,0x54,0x94,0xc6,0x27,0x48,0x46,0x7c,0x49,0xb2,0x68,0x5c,0x02,0xb4,0xcb,0x4c,0x22,0xd5,0xb7,0x1d,0x3e,0x0f,0x63,0xd1,0x11,0xa0,0x55,0x08,0x73,0x85,0x62,0x13,0x57,0x09,0x03,0xcb,0xdb,0x47,0x9d,0xd6,0x6f,0xbd,0xaa,0x05,0x62,0xb9,0x3e,0x8d,0xe8,0x9e,0x1e,0xd8,0x85,0x5a,0x77,0xf2,0x8a,0x26,0x71,0x81,0xe2,0x7f,0xf3,0x35,0x70,0xe9,0x0b,0x97,0xa9,0xfe,0xd9,0xb9,0x25,0xcf,0x68,0x80,0x6d,0x7f,0xb5,0x68,0xf7,0x85,0x07,0x71,0xd9,0xf8,0xef,0x39,0x14,0x80,0x2e,0xc2,0x17,0x46,0xf7,0xfb,0xe8,0xf9,0x10,0xd6,0x17,0xcf,0x3a,0x4f,0x73,0xae,0x08,0xbc,0xc2,0x39,0x10,0x3a,0xd6,0xf3,0x77,0xa1,0x91,0x93,0x5c,0xfe,0xf4,0x76,0x11,0xd9,0xb7,0x25,0xc2,0x9e,0x12,0xda,0x0f,0xbd,0x25,0x69,0x03,0xa8,0xea,0x78,0x88,0x3d,0xa3,0xc9,0xfe,0x38,0x9c,0x04,0xc6,0x38,0x32,0xd2,0x1a,0xc0,0xc7,0x86,0x09,0x73,0x24,0xfa,0x5b,0x66,0x81,0x26,0xb3,0x1b,0x90,0x14,0xb2,0xbe,0x34,0x78,0xb1,0x48,0x0f,0x36,0xde,0xcf,0xf1,0x06,0x7d,0x04,0x7d,0x54,0x16,0x2b,0xeb,0xc7,0x38,0x17,0x71,0x95,0xcc,0xb3,0xd9,0x80,0x64,0x90,0x0e,0x26,0x5a,0x87,0x48,0xff,0x6c,0xa2,0x65,0xfe,0xe5,0xea,0x27,0x7b,0x03,0xd5,0x42,0x68,0xd4,0xe5,0x1e,0x09,0x3e,0x11,0xae,0xdd,0x07,0x14,0x6c,0x3c,0x26,0x2e,0x58,0xde,0xe9,0xe7,0x95,0xa9,0x6d,0x4f,0x6d,0x0e,0x2a,0xbf,0x02,0xf7,0xcf,0x11,0xe9,0x39,0x69,0xf5,0x63,0x9c,0x62,0xbd,0xa7,0x50,0xe9,0x5f,0xf4,0x67,0xc7,0x4c,0xb9,0xbf,0xb6,0xd5,0xd5,0x0b,0x1f,0x8a,0xf8,0x97,0x60,0x42,0xf2,0xc0,0x51,0xc8,0x70,0x97,0x9f,0xc3,0xb7,0x41,0xde,0xc8,0xe6,0x59,0x80,0x28,0x66,0x0b,0x3f,0xbe,0x54,0xc5,0x1d,0x5b,0x7b,0x25,0x11]; + let ct: [u8; MLKEM1024_CT_LEN] = [ + 0x6B, 0x15, 0x08, 0x82, 0x0E, 0x30, 0x0E, 0x5C, 0xFE, 0xB3, 0xD9, 0xD3, 0x33, 0xF2, 0xDF, + 0x3F, 0x6A, 0x91, 0xB7, 0x40, 0x07, 0x61, 0xF0, 0x7B, 0xF6, 0x83, 0xF8, 0xED, 0xCD, 0xBE, + 0x14, 0xA0, 0xAC, 0x3F, 0x32, 0x26, 0x0B, 0x9B, 0x7E, 0x74, 0xE9, 0xA8, 0x6E, 0x44, 0xD5, + 0x3B, 0xA5, 0x3B, 0xB9, 0x1C, 0x9A, 0x9D, 0x4E, 0x15, 0x7F, 0xE5, 0x82, 0x11, 0x5F, 0xBA, + 0x56, 0x8C, 0x29, 0x2F, 0x2B, 0xB9, 0x62, 0xAA, 0x20, 0x50, 0x41, 0xE8, 0xD6, 0x9D, 0xB7, + 0xA9, 0xD7, 0x5E, 0xAA, 0xAA, 0xA0, 0x21, 0xE4, 0x5B, 0xCA, 0x83, 0x2C, 0xA1, 0x5B, 0xB4, + 0x4E, 0xBA, 0xA7, 0x0E, 0x8B, 0x95, 0x83, 0x9B, 0xCE, 0x92, 0xF0, 0x7C, 0x2E, 0x29, 0xFC, + 0xCA, 0x0D, 0x7B, 0x94, 0x00, 0x6F, 0x99, 0x44, 0x31, 0x40, 0x0B, 0xF7, 0xD6, 0xB9, 0x34, + 0x8D, 0x2F, 0x8A, 0x3F, 0x57, 0x8B, 0x52, 0x16, 0x47, 0x50, 0xE4, 0xAA, 0x7D, 0x8D, 0xDA, + 0xDA, 0xC1, 0x80, 0x23, 0x21, 0x7C, 0x26, 0xFB, 0x4E, 0x3A, 0xB0, 0xEC, 0x34, 0xC3, 0x23, + 0x5D, 0xE1, 0x2B, 0x2B, 0xFA, 0xF2, 0xC3, 0x36, 0x89, 0xD4, 0xA5, 0x3F, 0xE3, 0x13, 0xCB, + 0xD2, 0x8A, 0xBB, 0x9D, 0xBE, 0x23, 0x0A, 0x35, 0x9E, 0x41, 0x21, 0xED, 0x9F, 0x98, 0xF1, + 0x2F, 0x62, 0xD1, 0x4A, 0x9F, 0xE8, 0x6C, 0x46, 0x60, 0x2F, 0xA7, 0xC9, 0x5D, 0x25, 0xBA, + 0xCD, 0x2C, 0xDA, 0x33, 0xD5, 0x0B, 0xA7, 0xB5, 0xE2, 0xC0, 0xB2, 0x98, 0x17, 0x09, 0x35, + 0x8D, 0x8F, 0xC4, 0xE8, 0x9E, 0x63, 0x29, 0x67, 0xF7, 0x88, 0xB9, 0x34, 0xE8, 0x9C, 0x93, + 0xBD, 0x19, 0xCB, 0x62, 0xD7, 0x73, 0x7F, 0x56, 0x5A, 0x53, 0x25, 0xA0, 0xC0, 0x54, 0xF4, + 0xC4, 0xFB, 0x27, 0x9B, 0x1B, 0x8F, 0x63, 0xC2, 0x1F, 0xD3, 0x68, 0x0C, 0xB8, 0x0D, 0x35, + 0x2A, 0xC2, 0xA9, 0x03, 0x57, 0x24, 0x32, 0x00, 0xA7, 0xAA, 0xE1, 0x60, 0xE1, 0x26, 0xA5, + 0xBE, 0x5F, 0xF8, 0xF6, 0xED, 0x4F, 0xAB, 0x22, 0x30, 0xD9, 0x8E, 0x1B, 0x28, 0xFD, 0xA6, + 0xB9, 0xD9, 0xC5, 0xE4, 0xDF, 0x18, 0x85, 0xED, 0x12, 0x54, 0x2D, 0x98, 0xCB, 0x1C, 0xF0, + 0xEC, 0x95, 0x9F, 0x52, 0xB9, 0xB7, 0x09, 0xE6, 0xB2, 0x8C, 0xF1, 0xE5, 0xA1, 0x67, 0x23, + 0x32, 0xC8, 0x78, 0xBA, 0xF1, 0xFD, 0x8E, 0x5F, 0x49, 0x1B, 0x06, 0xAE, 0xCF, 0x5A, 0x5D, + 0x2A, 0xD2, 0x4C, 0x97, 0x34, 0xF3, 0x50, 0x08, 0xE2, 0xDD, 0xF6, 0x1E, 0x4C, 0x4F, 0x4B, + 0xDF, 0x48, 0x42, 0x6B, 0xBC, 0x63, 0xDE, 0x9A, 0xE7, 0xEE, 0x5A, 0x5D, 0x67, 0xF3, 0x51, + 0x30, 0x27, 0xBD, 0x68, 0xC8, 0xC3, 0x7F, 0x90, 0x5B, 0x75, 0xC1, 0x39, 0x7D, 0x38, 0xCC, + 0xDF, 0xE6, 0x08, 0x79, 0xFC, 0xBE, 0xBE, 0xE2, 0xCE, 0xBF, 0x19, 0x12, 0x80, 0xB0, 0xB8, + 0xAF, 0xBA, 0xCA, 0x3D, 0x1E, 0x03, 0xF2, 0xAA, 0x91, 0x11, 0x16, 0x39, 0x34, 0xE1, 0x28, + 0xE6, 0xEA, 0x1C, 0xC2, 0x15, 0xB7, 0xF3, 0x6F, 0xB9, 0x9C, 0x2D, 0xAA, 0x27, 0x25, 0xED, + 0x3A, 0x77, 0xE9, 0x30, 0x4F, 0x18, 0x12, 0x0A, 0x19, 0x78, 0x97, 0x0C, 0xA7, 0x60, 0x5C, + 0x8A, 0x3C, 0x67, 0xEF, 0x3F, 0xD3, 0x1B, 0x02, 0x7B, 0x06, 0x2A, 0x35, 0x8E, 0x32, 0xFA, + 0x48, 0xE4, 0xB0, 0xEF, 0x31, 0xD1, 0x1F, 0xE0, 0x5E, 0x8E, 0x71, 0x0E, 0x9A, 0x60, 0x08, + 0xB5, 0x4B, 0xD6, 0xAC, 0x93, 0x78, 0xC9, 0x8C, 0x62, 0x7B, 0x12, 0x59, 0x82, 0x3D, 0x6F, + 0x3E, 0xF4, 0xF0, 0xEF, 0x03, 0x81, 0x4E, 0x15, 0xED, 0xDE, 0x93, 0xF7, 0x34, 0x84, 0xE9, + 0x48, 0x27, 0x3D, 0x76, 0x64, 0xBF, 0xE6, 0x60, 0x47, 0xFC, 0x31, 0xC4, 0x68, 0xC8, 0x77, + 0x46, 0x78, 0xD2, 0x7B, 0x16, 0xB1, 0xC0, 0xDA, 0xB8, 0x80, 0xD1, 0xD7, 0x16, 0xD4, 0xDB, + 0x28, 0x89, 0x49, 0xE3, 0x35, 0x11, 0x17, 0x90, 0xF0, 0xE6, 0x6D, 0x65, 0x29, 0xB7, 0x2A, + 0x9B, 0x18, 0x2F, 0xE0, 0xB4, 0x37, 0xAA, 0xAC, 0x2B, 0x1F, 0xFC, 0x09, 0x79, 0xC1, 0x48, + 0x5C, 0x0E, 0x16, 0x38, 0x36, 0xC3, 0xA5, 0xCE, 0x49, 0xC5, 0xC8, 0x88, 0xD3, 0xEF, 0xC8, + 0xDF, 0xD6, 0xBC, 0x91, 0x73, 0x9B, 0xAD, 0x0A, 0xDD, 0x04, 0xD9, 0x20, 0xD3, 0x88, 0x42, + 0x28, 0x80, 0x3A, 0xAA, 0x2A, 0x23, 0xD9, 0xAD, 0x75, 0xD5, 0xD3, 0x9B, 0x40, 0x0E, 0x04, + 0xC9, 0xED, 0xC2, 0x91, 0x69, 0x7B, 0xB4, 0xC7, 0x1A, 0x22, 0x91, 0xEC, 0xD8, 0x95, 0x8B, + 0x02, 0xF0, 0x41, 0x56, 0x11, 0x61, 0x37, 0x68, 0x2D, 0xD0, 0xF3, 0x84, 0x93, 0x14, 0x3C, + 0x91, 0x1C, 0xF8, 0x72, 0xF5, 0x39, 0x8F, 0x07, 0x83, 0x7D, 0xF5, 0x20, 0x1B, 0xF6, 0x6A, + 0x06, 0xC1, 0x4A, 0xE2, 0x60, 0x45, 0x69, 0xD4, 0x27, 0xE9, 0xDC, 0x15, 0xB3, 0x01, 0xA3, + 0xA9, 0xFC, 0x7C, 0xFB, 0xA5, 0x02, 0x64, 0xFC, 0x73, 0x79, 0xE2, 0xBA, 0x83, 0xEE, 0xEE, + 0x68, 0xDC, 0x33, 0x52, 0x87, 0x74, 0xBA, 0x67, 0xFC, 0x1E, 0x51, 0xED, 0x3B, 0xC4, 0x08, + 0x1B, 0xDD, 0x3B, 0x18, 0x16, 0xD4, 0x0F, 0x61, 0xBB, 0xCF, 0x72, 0x11, 0xD9, 0xF4, 0x12, + 0xE1, 0x22, 0x7F, 0x3F, 0xBC, 0x5D, 0x04, 0x76, 0xF0, 0x32, 0x86, 0x45, 0x4E, 0xAB, 0xD5, + 0xD2, 0xA2, 0x25, 0xAA, 0x27, 0xA9, 0x61, 0x61, 0x6E, 0x24, 0xE7, 0x53, 0x2F, 0x28, 0x03, + 0x06, 0x64, 0xDF, 0xC2, 0xEC, 0xBC, 0xC5, 0xBE, 0x77, 0x9A, 0xF9, 0x39, 0x92, 0xE6, 0x5D, + 0x1C, 0x85, 0xE2, 0x10, 0x68, 0x8F, 0x2B, 0x6B, 0x91, 0xCC, 0xC9, 0xF1, 0xDB, 0x32, 0x6D, + 0xD9, 0x47, 0x53, 0xC3, 0xAA, 0xAE, 0xD4, 0x57, 0x1C, 0x20, 0x4F, 0x97, 0xC9, 0xE1, 0x87, + 0x1F, 0xFE, 0xCD, 0xEE, 0xF0, 0x7B, 0x88, 0xDE, 0x4F, 0x17, 0xF3, 0xCE, 0x40, 0xA5, 0x8D, + 0x01, 0x5F, 0xBE, 0xDB, 0x8A, 0x01, 0x1C, 0x61, 0x8F, 0xBB, 0x03, 0x99, 0x87, 0x63, 0xBC, + 0x60, 0xE7, 0x8C, 0x3C, 0x27, 0xAB, 0xD3, 0x70, 0x3D, 0x67, 0xB8, 0x6E, 0x3A, 0x82, 0x84, + 0xFE, 0x67, 0xD9, 0xEB, 0x59, 0xFC, 0x21, 0x69, 0x39, 0x29, 0x15, 0x7F, 0xDB, 0x0A, 0xE4, + 0x37, 0xA7, 0x36, 0xC2, 0xCF, 0xB5, 0xB6, 0x14, 0xD9, 0xB8, 0x47, 0x63, 0x5C, 0x1B, 0x8D, + 0x04, 0x75, 0x7C, 0xA6, 0x2F, 0x15, 0xF4, 0xD5, 0x36, 0xC7, 0x2D, 0x7A, 0x71, 0xD7, 0x41, + 0xD8, 0xA0, 0x7D, 0xD6, 0xA8, 0x28, 0x90, 0xB8, 0xE1, 0xF5, 0xAD, 0x59, 0xB1, 0x7E, 0x5C, + 0x85, 0xFD, 0xD7, 0x08, 0x17, 0x76, 0xEF, 0xAA, 0x0E, 0x29, 0x17, 0x14, 0xDE, 0xB9, 0x79, + 0xD5, 0xE5, 0x44, 0xBD, 0x8B, 0xE9, 0xF7, 0x9A, 0x87, 0x7E, 0x4B, 0xAD, 0x28, 0x24, 0x6A, + 0x39, 0x33, 0x00, 0x56, 0x97, 0x00, 0x4B, 0xFB, 0xE3, 0x24, 0x23, 0xAA, 0xDA, 0x98, 0x02, + 0xC5, 0x6F, 0xE1, 0xA6, 0x53, 0xA5, 0xCB, 0x95, 0x7D, 0x47, 0x20, 0xF5, 0x5D, 0x5F, 0x40, + 0x10, 0xDB, 0x40, 0x22, 0xA2, 0xCA, 0x49, 0xEC, 0xF5, 0xE7, 0xDD, 0x01, 0x45, 0xE5, 0x82, + 0xA9, 0xBC, 0xEB, 0x77, 0x3A, 0x45, 0x09, 0x7B, 0x29, 0x9A, 0x3B, 0x0D, 0xC4, 0x3B, 0x34, + 0x5D, 0x16, 0x37, 0xE8, 0x8F, 0xC1, 0xD8, 0x3E, 0x41, 0x4E, 0x24, 0xA0, 0xF6, 0xBD, 0x97, + 0x75, 0x73, 0xEF, 0x52, 0x3B, 0xBA, 0x8B, 0xA9, 0x86, 0x45, 0x15, 0xAC, 0x71, 0xEC, 0xA5, + 0xDF, 0xEF, 0xDA, 0x02, 0x3C, 0xAD, 0x07, 0xBD, 0x88, 0x74, 0x2B, 0x52, 0x1F, 0x63, 0x6B, + 0xA7, 0x08, 0xFB, 0xA4, 0x20, 0x81, 0x48, 0x22, 0xAE, 0x91, 0x32, 0x75, 0xA8, 0x51, 0xB9, + 0x0F, 0x34, 0x62, 0xB6, 0x4B, 0xF9, 0x88, 0xF8, 0xBA, 0x27, 0x18, 0xB4, 0x9F, 0x78, 0xCA, + 0xB5, 0xBA, 0xC4, 0x9F, 0x02, 0xCB, 0x50, 0xF3, 0x82, 0x1C, 0x3A, 0x35, 0x6D, 0x99, 0x45, + 0xC4, 0xBA, 0x8D, 0xBA, 0xB7, 0x47, 0x0C, 0x97, 0x79, 0x68, 0xF7, 0xB0, 0xCD, 0x66, 0xB0, + 0x7B, 0xFA, 0xCB, 0x39, 0x7C, 0x97, 0x38, 0x9E, 0xB4, 0x01, 0xC9, 0xE7, 0x85, 0xFA, 0x7A, + 0x98, 0x0E, 0x89, 0xC2, 0xF8, 0xAB, 0x0D, 0x8A, 0xD9, 0x1F, 0xA2, 0xBE, 0xF2, 0x52, 0xA3, + 0x79, 0x25, 0x21, 0x89, 0xF1, 0x53, 0x7C, 0x40, 0x4E, 0xA3, 0x18, 0x5A, 0xD8, 0xF1, 0xAB, + 0xF1, 0x72, 0xCE, 0x31, 0x01, 0x5F, 0xA5, 0xDC, 0x4E, 0x9A, 0xE5, 0x44, 0x66, 0x7A, 0xA2, + 0x12, 0x98, 0xF0, 0x1D, 0xB5, 0xD9, 0xE2, 0xC5, 0x52, 0xC2, 0x85, 0xD0, 0x7A, 0x8B, 0xC9, + 0xF5, 0xE7, 0x69, 0xEF, 0x42, 0x73, 0x2F, 0x08, 0x69, 0x0C, 0xCA, 0x61, 0xD0, 0x61, 0x34, + 0x53, 0x4E, 0x07, 0x00, 0xEF, 0x4C, 0xC7, 0x82, 0x70, 0x2F, 0x30, 0x0E, 0xB9, 0x4A, 0x0F, + 0xF4, 0x06, 0x5C, 0x11, 0xFF, 0x13, 0xCF, 0x2A, 0x3E, 0x2D, 0x1F, 0x85, 0x7F, 0x3E, 0x8E, + 0xB5, 0xDC, 0x70, 0x51, 0xF3, 0x1F, 0xD6, 0xEB, 0xF2, 0x56, 0xA1, 0xC5, 0xA4, 0xEE, 0x72, + 0x62, 0xB2, 0x42, 0xDF, 0x5F, 0xA4, 0x6D, 0xCE, 0x43, 0x7D, 0x20, 0xFD, 0xF8, 0x11, 0x82, + 0xFE, 0xAC, 0x60, 0x8A, 0xAF, 0x51, 0x5B, 0xFA, 0xED, 0xA5, 0x24, 0xC8, 0xAB, 0x1C, 0xCA, + 0xC2, 0x5E, 0x0B, 0x76, 0x81, 0xE3, 0x85, 0x64, 0x5C, 0xCF, 0xF5, 0x33, 0x73, 0x1E, 0x7D, + 0x11, 0x2E, 0x22, 0x15, 0xB3, 0x88, 0x85, 0x52, 0x43, 0x31, 0x54, 0x94, 0xC6, 0x27, 0x48, + 0x46, 0x7C, 0x49, 0xB2, 0x68, 0x5C, 0x02, 0xB4, 0xCB, 0x4C, 0x22, 0xD5, 0xB7, 0x1D, 0x3E, + 0x0F, 0x63, 0xD1, 0x11, 0xA0, 0x55, 0x08, 0x73, 0x85, 0x62, 0x13, 0x57, 0x09, 0x03, 0xCB, + 0xDB, 0x47, 0x9D, 0xD6, 0x6F, 0xBD, 0xAA, 0x05, 0x62, 0xB9, 0x3E, 0x8D, 0xE8, 0x9E, 0x1E, + 0xD8, 0x85, 0x5A, 0x77, 0xF2, 0x8A, 0x26, 0x71, 0x81, 0xE2, 0x7F, 0xF3, 0x35, 0x70, 0xE9, + 0x0B, 0x97, 0xA9, 0xFE, 0xD9, 0xB9, 0x25, 0xCF, 0x68, 0x80, 0x6D, 0x7F, 0xB5, 0x68, 0xF7, + 0x85, 0x07, 0x71, 0xD9, 0xF8, 0xEF, 0x39, 0x14, 0x80, 0x2E, 0xC2, 0x17, 0x46, 0xF7, 0xFB, + 0xE8, 0xF9, 0x10, 0xD6, 0x17, 0xCF, 0x3A, 0x4F, 0x73, 0xAE, 0x08, 0xBC, 0xC2, 0x39, 0x10, + 0x3A, 0xD6, 0xF3, 0x77, 0xA1, 0x91, 0x93, 0x5C, 0xFE, 0xF4, 0x76, 0x11, 0xD9, 0xB7, 0x25, + 0xC2, 0x9E, 0x12, 0xDA, 0x0F, 0xBD, 0x25, 0x69, 0x03, 0xA8, 0xEA, 0x78, 0x88, 0x3D, 0xA3, + 0xC9, 0xFE, 0x38, 0x9C, 0x04, 0xC6, 0x38, 0x32, 0xD2, 0x1A, 0xC0, 0xC7, 0x86, 0x09, 0x73, + 0x24, 0xFA, 0x5B, 0x66, 0x81, 0x26, 0xB3, 0x1B, 0x90, 0x14, 0xB2, 0xBE, 0x34, 0x78, 0xB1, + 0x48, 0x0F, 0x36, 0xDE, 0xCF, 0xF1, 0x06, 0x7D, 0x04, 0x7D, 0x54, 0x16, 0x2B, 0xEB, 0xC7, + 0x38, 0x17, 0x71, 0x95, 0xCC, 0xB3, 0xD9, 0x80, 0x64, 0x90, 0x0E, 0x26, 0x5A, 0x87, 0x48, + 0xFF, 0x6C, 0xA2, 0x65, 0xFE, 0xE5, 0xEA, 0x27, 0x7B, 0x03, 0xD5, 0x42, 0x68, 0xD4, 0xE5, + 0x1E, 0x09, 0x3E, 0x11, 0xAE, 0xDD, 0x07, 0x14, 0x6C, 0x3C, 0x26, 0x2E, 0x58, 0xDE, 0xE9, + 0xE7, 0x95, 0xA9, 0x6D, 0x4F, 0x6D, 0x0E, 0x2A, 0xBF, 0x02, 0xF7, 0xCF, 0x11, 0xE9, 0x39, + 0x69, 0xF5, 0x63, 0x9C, 0x62, 0xBD, 0xA7, 0x50, 0xE9, 0x5F, 0xF4, 0x67, 0xC7, 0x4C, 0xB9, + 0xBF, 0xB6, 0xD5, 0xD5, 0x0B, 0x1F, 0x8A, 0xF8, 0x97, 0x60, 0x42, 0xF2, 0xC0, 0x51, 0xC8, + 0x70, 0x97, 0x9F, 0xC3, 0xB7, 0x41, 0xDE, 0xC8, 0xE6, 0x59, 0x80, 0x28, 0x66, 0x0B, 0x3F, + 0xBE, 0x54, 0xC5, 0x1D, 0x5B, 0x7B, 0x25, 0x11, + ]; let (_pk, sk) = MLKEM1024::keygen_from_seed(&seed).unwrap(); let ss = MLKEM1024::decaps(&sk, &ct).unwrap(); @@ -412,14 +1365,21 @@ fn bench_mlkem1024_decaps() { } fn bench_mlkem1024_lowmemory_decaps() { - use bouncycastle::mlkem_lowmemory::{MLKEMTrait, MLKEM1024}; + use bouncycastle::mlkem_lowmemory::{MLKEM1024, MLKEMTrait}; eprintln!("MLKEM1024_lowmemory/Decaps"); let seed = KeyMaterial512::from_bytes_as_type( - &[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + ], KeyType::Seed, - ).unwrap(); + ) + .unwrap(); /* One-time setup of the KAT -- commented out so that we're not capturing keygen in the bench */ // let (pk, _sk) = MLKEM1024::keygen_from_seed(&seed).unwrap(); @@ -427,15 +1387,119 @@ fn bench_mlkem1024_lowmemory_decaps() { // use bouncycastle_hex as hex; // eprintln!("ct:\n{}", &hex::encode(ct)); - let ct: [u8; MLKEM1024_CT_LEN] = [0x6b,0x15,0x08,0x82,0x0e,0x30,0x0e,0x5c,0xfe,0xb3,0xd9,0xd3,0x33,0xf2,0xdf,0x3f,0x6a,0x91,0xb7,0x40,0x07,0x61,0xf0,0x7b,0xf6,0x83,0xf8,0xed,0xcd,0xbe,0x14,0xa0,0xac,0x3f,0x32,0x26,0x0b,0x9b,0x7e,0x74,0xe9,0xa8,0x6e,0x44,0xd5,0x3b,0xa5,0x3b,0xb9,0x1c,0x9a,0x9d,0x4e,0x15,0x7f,0xe5,0x82,0x11,0x5f,0xba,0x56,0x8c,0x29,0x2f,0x2b,0xb9,0x62,0xaa,0x20,0x50,0x41,0xe8,0xd6,0x9d,0xb7,0xa9,0xd7,0x5e,0xaa,0xaa,0xa0,0x21,0xe4,0x5b,0xca,0x83,0x2c,0xa1,0x5b,0xb4,0x4e,0xba,0xa7,0x0e,0x8b,0x95,0x83,0x9b,0xce,0x92,0xf0,0x7c,0x2e,0x29,0xfc,0xca,0x0d,0x7b,0x94,0x00,0x6f,0x99,0x44,0x31,0x40,0x0b,0xf7,0xd6,0xb9,0x34,0x8d,0x2f,0x8a,0x3f,0x57,0x8b,0x52,0x16,0x47,0x50,0xe4,0xaa,0x7d,0x8d,0xda,0xda,0xc1,0x80,0x23,0x21,0x7c,0x26,0xfb,0x4e,0x3a,0xb0,0xec,0x34,0xc3,0x23,0x5d,0xe1,0x2b,0x2b,0xfa,0xf2,0xc3,0x36,0x89,0xd4,0xa5,0x3f,0xe3,0x13,0xcb,0xd2,0x8a,0xbb,0x9d,0xbe,0x23,0x0a,0x35,0x9e,0x41,0x21,0xed,0x9f,0x98,0xf1,0x2f,0x62,0xd1,0x4a,0x9f,0xe8,0x6c,0x46,0x60,0x2f,0xa7,0xc9,0x5d,0x25,0xba,0xcd,0x2c,0xda,0x33,0xd5,0x0b,0xa7,0xb5,0xe2,0xc0,0xb2,0x98,0x17,0x09,0x35,0x8d,0x8f,0xc4,0xe8,0x9e,0x63,0x29,0x67,0xf7,0x88,0xb9,0x34,0xe8,0x9c,0x93,0xbd,0x19,0xcb,0x62,0xd7,0x73,0x7f,0x56,0x5a,0x53,0x25,0xa0,0xc0,0x54,0xf4,0xc4,0xfb,0x27,0x9b,0x1b,0x8f,0x63,0xc2,0x1f,0xd3,0x68,0x0c,0xb8,0x0d,0x35,0x2a,0xc2,0xa9,0x03,0x57,0x24,0x32,0x00,0xa7,0xaa,0xe1,0x60,0xe1,0x26,0xa5,0xbe,0x5f,0xf8,0xf6,0xed,0x4f,0xab,0x22,0x30,0xd9,0x8e,0x1b,0x28,0xfd,0xa6,0xb9,0xd9,0xc5,0xe4,0xdf,0x18,0x85,0xed,0x12,0x54,0x2d,0x98,0xcb,0x1c,0xf0,0xec,0x95,0x9f,0x52,0xb9,0xb7,0x09,0xe6,0xb2,0x8c,0xf1,0xe5,0xa1,0x67,0x23,0x32,0xc8,0x78,0xba,0xf1,0xfd,0x8e,0x5f,0x49,0x1b,0x06,0xae,0xcf,0x5a,0x5d,0x2a,0xd2,0x4c,0x97,0x34,0xf3,0x50,0x08,0xe2,0xdd,0xf6,0x1e,0x4c,0x4f,0x4b,0xdf,0x48,0x42,0x6b,0xbc,0x63,0xde,0x9a,0xe7,0xee,0x5a,0x5d,0x67,0xf3,0x51,0x30,0x27,0xbd,0x68,0xc8,0xc3,0x7f,0x90,0x5b,0x75,0xc1,0x39,0x7d,0x38,0xcc,0xdf,0xe6,0x08,0x79,0xfc,0xbe,0xbe,0xe2,0xce,0xbf,0x19,0x12,0x80,0xb0,0xb8,0xaf,0xba,0xca,0x3d,0x1e,0x03,0xf2,0xaa,0x91,0x11,0x16,0x39,0x34,0xe1,0x28,0xe6,0xea,0x1c,0xc2,0x15,0xb7,0xf3,0x6f,0xb9,0x9c,0x2d,0xaa,0x27,0x25,0xed,0x3a,0x77,0xe9,0x30,0x4f,0x18,0x12,0x0a,0x19,0x78,0x97,0x0c,0xa7,0x60,0x5c,0x8a,0x3c,0x67,0xef,0x3f,0xd3,0x1b,0x02,0x7b,0x06,0x2a,0x35,0x8e,0x32,0xfa,0x48,0xe4,0xb0,0xef,0x31,0xd1,0x1f,0xe0,0x5e,0x8e,0x71,0x0e,0x9a,0x60,0x08,0xb5,0x4b,0xd6,0xac,0x93,0x78,0xc9,0x8c,0x62,0x7b,0x12,0x59,0x82,0x3d,0x6f,0x3e,0xf4,0xf0,0xef,0x03,0x81,0x4e,0x15,0xed,0xde,0x93,0xf7,0x34,0x84,0xe9,0x48,0x27,0x3d,0x76,0x64,0xbf,0xe6,0x60,0x47,0xfc,0x31,0xc4,0x68,0xc8,0x77,0x46,0x78,0xd2,0x7b,0x16,0xb1,0xc0,0xda,0xb8,0x80,0xd1,0xd7,0x16,0xd4,0xdb,0x28,0x89,0x49,0xe3,0x35,0x11,0x17,0x90,0xf0,0xe6,0x6d,0x65,0x29,0xb7,0x2a,0x9b,0x18,0x2f,0xe0,0xb4,0x37,0xaa,0xac,0x2b,0x1f,0xfc,0x09,0x79,0xc1,0x48,0x5c,0x0e,0x16,0x38,0x36,0xc3,0xa5,0xce,0x49,0xc5,0xc8,0x88,0xd3,0xef,0xc8,0xdf,0xd6,0xbc,0x91,0x73,0x9b,0xad,0x0a,0xdd,0x04,0xd9,0x20,0xd3,0x88,0x42,0x28,0x80,0x3a,0xaa,0x2a,0x23,0xd9,0xad,0x75,0xd5,0xd3,0x9b,0x40,0x0e,0x04,0xc9,0xed,0xc2,0x91,0x69,0x7b,0xb4,0xc7,0x1a,0x22,0x91,0xec,0xd8,0x95,0x8b,0x02,0xf0,0x41,0x56,0x11,0x61,0x37,0x68,0x2d,0xd0,0xf3,0x84,0x93,0x14,0x3c,0x91,0x1c,0xf8,0x72,0xf5,0x39,0x8f,0x07,0x83,0x7d,0xf5,0x20,0x1b,0xf6,0x6a,0x06,0xc1,0x4a,0xe2,0x60,0x45,0x69,0xd4,0x27,0xe9,0xdc,0x15,0xb3,0x01,0xa3,0xa9,0xfc,0x7c,0xfb,0xa5,0x02,0x64,0xfc,0x73,0x79,0xe2,0xba,0x83,0xee,0xee,0x68,0xdc,0x33,0x52,0x87,0x74,0xba,0x67,0xfc,0x1e,0x51,0xed,0x3b,0xc4,0x08,0x1b,0xdd,0x3b,0x18,0x16,0xd4,0x0f,0x61,0xbb,0xcf,0x72,0x11,0xd9,0xf4,0x12,0xe1,0x22,0x7f,0x3f,0xbc,0x5d,0x04,0x76,0xf0,0x32,0x86,0x45,0x4e,0xab,0xd5,0xd2,0xa2,0x25,0xaa,0x27,0xa9,0x61,0x61,0x6e,0x24,0xe7,0x53,0x2f,0x28,0x03,0x06,0x64,0xdf,0xc2,0xec,0xbc,0xc5,0xbe,0x77,0x9a,0xf9,0x39,0x92,0xe6,0x5d,0x1c,0x85,0xe2,0x10,0x68,0x8f,0x2b,0x6b,0x91,0xcc,0xc9,0xf1,0xdb,0x32,0x6d,0xd9,0x47,0x53,0xc3,0xaa,0xae,0xd4,0x57,0x1c,0x20,0x4f,0x97,0xc9,0xe1,0x87,0x1f,0xfe,0xcd,0xee,0xf0,0x7b,0x88,0xde,0x4f,0x17,0xf3,0xce,0x40,0xa5,0x8d,0x01,0x5f,0xbe,0xdb,0x8a,0x01,0x1c,0x61,0x8f,0xbb,0x03,0x99,0x87,0x63,0xbc,0x60,0xe7,0x8c,0x3c,0x27,0xab,0xd3,0x70,0x3d,0x67,0xb8,0x6e,0x3a,0x82,0x84,0xfe,0x67,0xd9,0xeb,0x59,0xfc,0x21,0x69,0x39,0x29,0x15,0x7f,0xdb,0x0a,0xe4,0x37,0xa7,0x36,0xc2,0xcf,0xb5,0xb6,0x14,0xd9,0xb8,0x47,0x63,0x5c,0x1b,0x8d,0x04,0x75,0x7c,0xa6,0x2f,0x15,0xf4,0xd5,0x36,0xc7,0x2d,0x7a,0x71,0xd7,0x41,0xd8,0xa0,0x7d,0xd6,0xa8,0x28,0x90,0xb8,0xe1,0xf5,0xad,0x59,0xb1,0x7e,0x5c,0x85,0xfd,0xd7,0x08,0x17,0x76,0xef,0xaa,0x0e,0x29,0x17,0x14,0xde,0xb9,0x79,0xd5,0xe5,0x44,0xbd,0x8b,0xe9,0xf7,0x9a,0x87,0x7e,0x4b,0xad,0x28,0x24,0x6a,0x39,0x33,0x00,0x56,0x97,0x00,0x4b,0xfb,0xe3,0x24,0x23,0xaa,0xda,0x98,0x02,0xc5,0x6f,0xe1,0xa6,0x53,0xa5,0xcb,0x95,0x7d,0x47,0x20,0xf5,0x5d,0x5f,0x40,0x10,0xdb,0x40,0x22,0xa2,0xca,0x49,0xec,0xf5,0xe7,0xdd,0x01,0x45,0xe5,0x82,0xa9,0xbc,0xeb,0x77,0x3a,0x45,0x09,0x7b,0x29,0x9a,0x3b,0x0d,0xc4,0x3b,0x34,0x5d,0x16,0x37,0xe8,0x8f,0xc1,0xd8,0x3e,0x41,0x4e,0x24,0xa0,0xf6,0xbd,0x97,0x75,0x73,0xef,0x52,0x3b,0xba,0x8b,0xa9,0x86,0x45,0x15,0xac,0x71,0xec,0xa5,0xdf,0xef,0xda,0x02,0x3c,0xad,0x07,0xbd,0x88,0x74,0x2b,0x52,0x1f,0x63,0x6b,0xa7,0x08,0xfb,0xa4,0x20,0x81,0x48,0x22,0xae,0x91,0x32,0x75,0xa8,0x51,0xb9,0x0f,0x34,0x62,0xb6,0x4b,0xf9,0x88,0xf8,0xba,0x27,0x18,0xb4,0x9f,0x78,0xca,0xb5,0xba,0xc4,0x9f,0x02,0xcb,0x50,0xf3,0x82,0x1c,0x3a,0x35,0x6d,0x99,0x45,0xc4,0xba,0x8d,0xba,0xb7,0x47,0x0c,0x97,0x79,0x68,0xf7,0xb0,0xcd,0x66,0xb0,0x7b,0xfa,0xcb,0x39,0x7c,0x97,0x38,0x9e,0xb4,0x01,0xc9,0xe7,0x85,0xfa,0x7a,0x98,0x0e,0x89,0xc2,0xf8,0xab,0x0d,0x8a,0xd9,0x1f,0xa2,0xbe,0xf2,0x52,0xa3,0x79,0x25,0x21,0x89,0xf1,0x53,0x7c,0x40,0x4e,0xa3,0x18,0x5a,0xd8,0xf1,0xab,0xf1,0x72,0xce,0x31,0x01,0x5f,0xa5,0xdc,0x4e,0x9a,0xe5,0x44,0x66,0x7a,0xa2,0x12,0x98,0xf0,0x1d,0xb5,0xd9,0xe2,0xc5,0x52,0xc2,0x85,0xd0,0x7a,0x8b,0xc9,0xf5,0xe7,0x69,0xef,0x42,0x73,0x2f,0x08,0x69,0x0c,0xca,0x61,0xd0,0x61,0x34,0x53,0x4e,0x07,0x00,0xef,0x4c,0xc7,0x82,0x70,0x2f,0x30,0x0e,0xb9,0x4a,0x0f,0xf4,0x06,0x5c,0x11,0xff,0x13,0xcf,0x2a,0x3e,0x2d,0x1f,0x85,0x7f,0x3e,0x8e,0xb5,0xdc,0x70,0x51,0xf3,0x1f,0xd6,0xeb,0xf2,0x56,0xa1,0xc5,0xa4,0xee,0x72,0x62,0xb2,0x42,0xdf,0x5f,0xa4,0x6d,0xce,0x43,0x7d,0x20,0xfd,0xf8,0x11,0x82,0xfe,0xac,0x60,0x8a,0xaf,0x51,0x5b,0xfa,0xed,0xa5,0x24,0xc8,0xab,0x1c,0xca,0xc2,0x5e,0x0b,0x76,0x81,0xe3,0x85,0x64,0x5c,0xcf,0xf5,0x33,0x73,0x1e,0x7d,0x11,0x2e,0x22,0x15,0xb3,0x88,0x85,0x52,0x43,0x31,0x54,0x94,0xc6,0x27,0x48,0x46,0x7c,0x49,0xb2,0x68,0x5c,0x02,0xb4,0xcb,0x4c,0x22,0xd5,0xb7,0x1d,0x3e,0x0f,0x63,0xd1,0x11,0xa0,0x55,0x08,0x73,0x85,0x62,0x13,0x57,0x09,0x03,0xcb,0xdb,0x47,0x9d,0xd6,0x6f,0xbd,0xaa,0x05,0x62,0xb9,0x3e,0x8d,0xe8,0x9e,0x1e,0xd8,0x85,0x5a,0x77,0xf2,0x8a,0x26,0x71,0x81,0xe2,0x7f,0xf3,0x35,0x70,0xe9,0x0b,0x97,0xa9,0xfe,0xd9,0xb9,0x25,0xcf,0x68,0x80,0x6d,0x7f,0xb5,0x68,0xf7,0x85,0x07,0x71,0xd9,0xf8,0xef,0x39,0x14,0x80,0x2e,0xc2,0x17,0x46,0xf7,0xfb,0xe8,0xf9,0x10,0xd6,0x17,0xcf,0x3a,0x4f,0x73,0xae,0x08,0xbc,0xc2,0x39,0x10,0x3a,0xd6,0xf3,0x77,0xa1,0x91,0x93,0x5c,0xfe,0xf4,0x76,0x11,0xd9,0xb7,0x25,0xc2,0x9e,0x12,0xda,0x0f,0xbd,0x25,0x69,0x03,0xa8,0xea,0x78,0x88,0x3d,0xa3,0xc9,0xfe,0x38,0x9c,0x04,0xc6,0x38,0x32,0xd2,0x1a,0xc0,0xc7,0x86,0x09,0x73,0x24,0xfa,0x5b,0x66,0x81,0x26,0xb3,0x1b,0x90,0x14,0xb2,0xbe,0x34,0x78,0xb1,0x48,0x0f,0x36,0xde,0xcf,0xf1,0x06,0x7d,0x04,0x7d,0x54,0x16,0x2b,0xeb,0xc7,0x38,0x17,0x71,0x95,0xcc,0xb3,0xd9,0x80,0x64,0x90,0x0e,0x26,0x5a,0x87,0x48,0xff,0x6c,0xa2,0x65,0xfe,0xe5,0xea,0x27,0x7b,0x03,0xd5,0x42,0x68,0xd4,0xe5,0x1e,0x09,0x3e,0x11,0xae,0xdd,0x07,0x14,0x6c,0x3c,0x26,0x2e,0x58,0xde,0xe9,0xe7,0x95,0xa9,0x6d,0x4f,0x6d,0x0e,0x2a,0xbf,0x02,0xf7,0xcf,0x11,0xe9,0x39,0x69,0xf5,0x63,0x9c,0x62,0xbd,0xa7,0x50,0xe9,0x5f,0xf4,0x67,0xc7,0x4c,0xb9,0xbf,0xb6,0xd5,0xd5,0x0b,0x1f,0x8a,0xf8,0x97,0x60,0x42,0xf2,0xc0,0x51,0xc8,0x70,0x97,0x9f,0xc3,0xb7,0x41,0xde,0xc8,0xe6,0x59,0x80,0x28,0x66,0x0b,0x3f,0xbe,0x54,0xc5,0x1d,0x5b,0x7b,0x25,0x11]; + let ct: [u8; MLKEM1024_CT_LEN] = [ + 0x6B, 0x15, 0x08, 0x82, 0x0E, 0x30, 0x0E, 0x5C, 0xFE, 0xB3, 0xD9, 0xD3, 0x33, 0xF2, 0xDF, + 0x3F, 0x6A, 0x91, 0xB7, 0x40, 0x07, 0x61, 0xF0, 0x7B, 0xF6, 0x83, 0xF8, 0xED, 0xCD, 0xBE, + 0x14, 0xA0, 0xAC, 0x3F, 0x32, 0x26, 0x0B, 0x9B, 0x7E, 0x74, 0xE9, 0xA8, 0x6E, 0x44, 0xD5, + 0x3B, 0xA5, 0x3B, 0xB9, 0x1C, 0x9A, 0x9D, 0x4E, 0x15, 0x7F, 0xE5, 0x82, 0x11, 0x5F, 0xBA, + 0x56, 0x8C, 0x29, 0x2F, 0x2B, 0xB9, 0x62, 0xAA, 0x20, 0x50, 0x41, 0xE8, 0xD6, 0x9D, 0xB7, + 0xA9, 0xD7, 0x5E, 0xAA, 0xAA, 0xA0, 0x21, 0xE4, 0x5B, 0xCA, 0x83, 0x2C, 0xA1, 0x5B, 0xB4, + 0x4E, 0xBA, 0xA7, 0x0E, 0x8B, 0x95, 0x83, 0x9B, 0xCE, 0x92, 0xF0, 0x7C, 0x2E, 0x29, 0xFC, + 0xCA, 0x0D, 0x7B, 0x94, 0x00, 0x6F, 0x99, 0x44, 0x31, 0x40, 0x0B, 0xF7, 0xD6, 0xB9, 0x34, + 0x8D, 0x2F, 0x8A, 0x3F, 0x57, 0x8B, 0x52, 0x16, 0x47, 0x50, 0xE4, 0xAA, 0x7D, 0x8D, 0xDA, + 0xDA, 0xC1, 0x80, 0x23, 0x21, 0x7C, 0x26, 0xFB, 0x4E, 0x3A, 0xB0, 0xEC, 0x34, 0xC3, 0x23, + 0x5D, 0xE1, 0x2B, 0x2B, 0xFA, 0xF2, 0xC3, 0x36, 0x89, 0xD4, 0xA5, 0x3F, 0xE3, 0x13, 0xCB, + 0xD2, 0x8A, 0xBB, 0x9D, 0xBE, 0x23, 0x0A, 0x35, 0x9E, 0x41, 0x21, 0xED, 0x9F, 0x98, 0xF1, + 0x2F, 0x62, 0xD1, 0x4A, 0x9F, 0xE8, 0x6C, 0x46, 0x60, 0x2F, 0xA7, 0xC9, 0x5D, 0x25, 0xBA, + 0xCD, 0x2C, 0xDA, 0x33, 0xD5, 0x0B, 0xA7, 0xB5, 0xE2, 0xC0, 0xB2, 0x98, 0x17, 0x09, 0x35, + 0x8D, 0x8F, 0xC4, 0xE8, 0x9E, 0x63, 0x29, 0x67, 0xF7, 0x88, 0xB9, 0x34, 0xE8, 0x9C, 0x93, + 0xBD, 0x19, 0xCB, 0x62, 0xD7, 0x73, 0x7F, 0x56, 0x5A, 0x53, 0x25, 0xA0, 0xC0, 0x54, 0xF4, + 0xC4, 0xFB, 0x27, 0x9B, 0x1B, 0x8F, 0x63, 0xC2, 0x1F, 0xD3, 0x68, 0x0C, 0xB8, 0x0D, 0x35, + 0x2A, 0xC2, 0xA9, 0x03, 0x57, 0x24, 0x32, 0x00, 0xA7, 0xAA, 0xE1, 0x60, 0xE1, 0x26, 0xA5, + 0xBE, 0x5F, 0xF8, 0xF6, 0xED, 0x4F, 0xAB, 0x22, 0x30, 0xD9, 0x8E, 0x1B, 0x28, 0xFD, 0xA6, + 0xB9, 0xD9, 0xC5, 0xE4, 0xDF, 0x18, 0x85, 0xED, 0x12, 0x54, 0x2D, 0x98, 0xCB, 0x1C, 0xF0, + 0xEC, 0x95, 0x9F, 0x52, 0xB9, 0xB7, 0x09, 0xE6, 0xB2, 0x8C, 0xF1, 0xE5, 0xA1, 0x67, 0x23, + 0x32, 0xC8, 0x78, 0xBA, 0xF1, 0xFD, 0x8E, 0x5F, 0x49, 0x1B, 0x06, 0xAE, 0xCF, 0x5A, 0x5D, + 0x2A, 0xD2, 0x4C, 0x97, 0x34, 0xF3, 0x50, 0x08, 0xE2, 0xDD, 0xF6, 0x1E, 0x4C, 0x4F, 0x4B, + 0xDF, 0x48, 0x42, 0x6B, 0xBC, 0x63, 0xDE, 0x9A, 0xE7, 0xEE, 0x5A, 0x5D, 0x67, 0xF3, 0x51, + 0x30, 0x27, 0xBD, 0x68, 0xC8, 0xC3, 0x7F, 0x90, 0x5B, 0x75, 0xC1, 0x39, 0x7D, 0x38, 0xCC, + 0xDF, 0xE6, 0x08, 0x79, 0xFC, 0xBE, 0xBE, 0xE2, 0xCE, 0xBF, 0x19, 0x12, 0x80, 0xB0, 0xB8, + 0xAF, 0xBA, 0xCA, 0x3D, 0x1E, 0x03, 0xF2, 0xAA, 0x91, 0x11, 0x16, 0x39, 0x34, 0xE1, 0x28, + 0xE6, 0xEA, 0x1C, 0xC2, 0x15, 0xB7, 0xF3, 0x6F, 0xB9, 0x9C, 0x2D, 0xAA, 0x27, 0x25, 0xED, + 0x3A, 0x77, 0xE9, 0x30, 0x4F, 0x18, 0x12, 0x0A, 0x19, 0x78, 0x97, 0x0C, 0xA7, 0x60, 0x5C, + 0x8A, 0x3C, 0x67, 0xEF, 0x3F, 0xD3, 0x1B, 0x02, 0x7B, 0x06, 0x2A, 0x35, 0x8E, 0x32, 0xFA, + 0x48, 0xE4, 0xB0, 0xEF, 0x31, 0xD1, 0x1F, 0xE0, 0x5E, 0x8E, 0x71, 0x0E, 0x9A, 0x60, 0x08, + 0xB5, 0x4B, 0xD6, 0xAC, 0x93, 0x78, 0xC9, 0x8C, 0x62, 0x7B, 0x12, 0x59, 0x82, 0x3D, 0x6F, + 0x3E, 0xF4, 0xF0, 0xEF, 0x03, 0x81, 0x4E, 0x15, 0xED, 0xDE, 0x93, 0xF7, 0x34, 0x84, 0xE9, + 0x48, 0x27, 0x3D, 0x76, 0x64, 0xBF, 0xE6, 0x60, 0x47, 0xFC, 0x31, 0xC4, 0x68, 0xC8, 0x77, + 0x46, 0x78, 0xD2, 0x7B, 0x16, 0xB1, 0xC0, 0xDA, 0xB8, 0x80, 0xD1, 0xD7, 0x16, 0xD4, 0xDB, + 0x28, 0x89, 0x49, 0xE3, 0x35, 0x11, 0x17, 0x90, 0xF0, 0xE6, 0x6D, 0x65, 0x29, 0xB7, 0x2A, + 0x9B, 0x18, 0x2F, 0xE0, 0xB4, 0x37, 0xAA, 0xAC, 0x2B, 0x1F, 0xFC, 0x09, 0x79, 0xC1, 0x48, + 0x5C, 0x0E, 0x16, 0x38, 0x36, 0xC3, 0xA5, 0xCE, 0x49, 0xC5, 0xC8, 0x88, 0xD3, 0xEF, 0xC8, + 0xDF, 0xD6, 0xBC, 0x91, 0x73, 0x9B, 0xAD, 0x0A, 0xDD, 0x04, 0xD9, 0x20, 0xD3, 0x88, 0x42, + 0x28, 0x80, 0x3A, 0xAA, 0x2A, 0x23, 0xD9, 0xAD, 0x75, 0xD5, 0xD3, 0x9B, 0x40, 0x0E, 0x04, + 0xC9, 0xED, 0xC2, 0x91, 0x69, 0x7B, 0xB4, 0xC7, 0x1A, 0x22, 0x91, 0xEC, 0xD8, 0x95, 0x8B, + 0x02, 0xF0, 0x41, 0x56, 0x11, 0x61, 0x37, 0x68, 0x2D, 0xD0, 0xF3, 0x84, 0x93, 0x14, 0x3C, + 0x91, 0x1C, 0xF8, 0x72, 0xF5, 0x39, 0x8F, 0x07, 0x83, 0x7D, 0xF5, 0x20, 0x1B, 0xF6, 0x6A, + 0x06, 0xC1, 0x4A, 0xE2, 0x60, 0x45, 0x69, 0xD4, 0x27, 0xE9, 0xDC, 0x15, 0xB3, 0x01, 0xA3, + 0xA9, 0xFC, 0x7C, 0xFB, 0xA5, 0x02, 0x64, 0xFC, 0x73, 0x79, 0xE2, 0xBA, 0x83, 0xEE, 0xEE, + 0x68, 0xDC, 0x33, 0x52, 0x87, 0x74, 0xBA, 0x67, 0xFC, 0x1E, 0x51, 0xED, 0x3B, 0xC4, 0x08, + 0x1B, 0xDD, 0x3B, 0x18, 0x16, 0xD4, 0x0F, 0x61, 0xBB, 0xCF, 0x72, 0x11, 0xD9, 0xF4, 0x12, + 0xE1, 0x22, 0x7F, 0x3F, 0xBC, 0x5D, 0x04, 0x76, 0xF0, 0x32, 0x86, 0x45, 0x4E, 0xAB, 0xD5, + 0xD2, 0xA2, 0x25, 0xAA, 0x27, 0xA9, 0x61, 0x61, 0x6E, 0x24, 0xE7, 0x53, 0x2F, 0x28, 0x03, + 0x06, 0x64, 0xDF, 0xC2, 0xEC, 0xBC, 0xC5, 0xBE, 0x77, 0x9A, 0xF9, 0x39, 0x92, 0xE6, 0x5D, + 0x1C, 0x85, 0xE2, 0x10, 0x68, 0x8F, 0x2B, 0x6B, 0x91, 0xCC, 0xC9, 0xF1, 0xDB, 0x32, 0x6D, + 0xD9, 0x47, 0x53, 0xC3, 0xAA, 0xAE, 0xD4, 0x57, 0x1C, 0x20, 0x4F, 0x97, 0xC9, 0xE1, 0x87, + 0x1F, 0xFE, 0xCD, 0xEE, 0xF0, 0x7B, 0x88, 0xDE, 0x4F, 0x17, 0xF3, 0xCE, 0x40, 0xA5, 0x8D, + 0x01, 0x5F, 0xBE, 0xDB, 0x8A, 0x01, 0x1C, 0x61, 0x8F, 0xBB, 0x03, 0x99, 0x87, 0x63, 0xBC, + 0x60, 0xE7, 0x8C, 0x3C, 0x27, 0xAB, 0xD3, 0x70, 0x3D, 0x67, 0xB8, 0x6E, 0x3A, 0x82, 0x84, + 0xFE, 0x67, 0xD9, 0xEB, 0x59, 0xFC, 0x21, 0x69, 0x39, 0x29, 0x15, 0x7F, 0xDB, 0x0A, 0xE4, + 0x37, 0xA7, 0x36, 0xC2, 0xCF, 0xB5, 0xB6, 0x14, 0xD9, 0xB8, 0x47, 0x63, 0x5C, 0x1B, 0x8D, + 0x04, 0x75, 0x7C, 0xA6, 0x2F, 0x15, 0xF4, 0xD5, 0x36, 0xC7, 0x2D, 0x7A, 0x71, 0xD7, 0x41, + 0xD8, 0xA0, 0x7D, 0xD6, 0xA8, 0x28, 0x90, 0xB8, 0xE1, 0xF5, 0xAD, 0x59, 0xB1, 0x7E, 0x5C, + 0x85, 0xFD, 0xD7, 0x08, 0x17, 0x76, 0xEF, 0xAA, 0x0E, 0x29, 0x17, 0x14, 0xDE, 0xB9, 0x79, + 0xD5, 0xE5, 0x44, 0xBD, 0x8B, 0xE9, 0xF7, 0x9A, 0x87, 0x7E, 0x4B, 0xAD, 0x28, 0x24, 0x6A, + 0x39, 0x33, 0x00, 0x56, 0x97, 0x00, 0x4B, 0xFB, 0xE3, 0x24, 0x23, 0xAA, 0xDA, 0x98, 0x02, + 0xC5, 0x6F, 0xE1, 0xA6, 0x53, 0xA5, 0xCB, 0x95, 0x7D, 0x47, 0x20, 0xF5, 0x5D, 0x5F, 0x40, + 0x10, 0xDB, 0x40, 0x22, 0xA2, 0xCA, 0x49, 0xEC, 0xF5, 0xE7, 0xDD, 0x01, 0x45, 0xE5, 0x82, + 0xA9, 0xBC, 0xEB, 0x77, 0x3A, 0x45, 0x09, 0x7B, 0x29, 0x9A, 0x3B, 0x0D, 0xC4, 0x3B, 0x34, + 0x5D, 0x16, 0x37, 0xE8, 0x8F, 0xC1, 0xD8, 0x3E, 0x41, 0x4E, 0x24, 0xA0, 0xF6, 0xBD, 0x97, + 0x75, 0x73, 0xEF, 0x52, 0x3B, 0xBA, 0x8B, 0xA9, 0x86, 0x45, 0x15, 0xAC, 0x71, 0xEC, 0xA5, + 0xDF, 0xEF, 0xDA, 0x02, 0x3C, 0xAD, 0x07, 0xBD, 0x88, 0x74, 0x2B, 0x52, 0x1F, 0x63, 0x6B, + 0xA7, 0x08, 0xFB, 0xA4, 0x20, 0x81, 0x48, 0x22, 0xAE, 0x91, 0x32, 0x75, 0xA8, 0x51, 0xB9, + 0x0F, 0x34, 0x62, 0xB6, 0x4B, 0xF9, 0x88, 0xF8, 0xBA, 0x27, 0x18, 0xB4, 0x9F, 0x78, 0xCA, + 0xB5, 0xBA, 0xC4, 0x9F, 0x02, 0xCB, 0x50, 0xF3, 0x82, 0x1C, 0x3A, 0x35, 0x6D, 0x99, 0x45, + 0xC4, 0xBA, 0x8D, 0xBA, 0xB7, 0x47, 0x0C, 0x97, 0x79, 0x68, 0xF7, 0xB0, 0xCD, 0x66, 0xB0, + 0x7B, 0xFA, 0xCB, 0x39, 0x7C, 0x97, 0x38, 0x9E, 0xB4, 0x01, 0xC9, 0xE7, 0x85, 0xFA, 0x7A, + 0x98, 0x0E, 0x89, 0xC2, 0xF8, 0xAB, 0x0D, 0x8A, 0xD9, 0x1F, 0xA2, 0xBE, 0xF2, 0x52, 0xA3, + 0x79, 0x25, 0x21, 0x89, 0xF1, 0x53, 0x7C, 0x40, 0x4E, 0xA3, 0x18, 0x5A, 0xD8, 0xF1, 0xAB, + 0xF1, 0x72, 0xCE, 0x31, 0x01, 0x5F, 0xA5, 0xDC, 0x4E, 0x9A, 0xE5, 0x44, 0x66, 0x7A, 0xA2, + 0x12, 0x98, 0xF0, 0x1D, 0xB5, 0xD9, 0xE2, 0xC5, 0x52, 0xC2, 0x85, 0xD0, 0x7A, 0x8B, 0xC9, + 0xF5, 0xE7, 0x69, 0xEF, 0x42, 0x73, 0x2F, 0x08, 0x69, 0x0C, 0xCA, 0x61, 0xD0, 0x61, 0x34, + 0x53, 0x4E, 0x07, 0x00, 0xEF, 0x4C, 0xC7, 0x82, 0x70, 0x2F, 0x30, 0x0E, 0xB9, 0x4A, 0x0F, + 0xF4, 0x06, 0x5C, 0x11, 0xFF, 0x13, 0xCF, 0x2A, 0x3E, 0x2D, 0x1F, 0x85, 0x7F, 0x3E, 0x8E, + 0xB5, 0xDC, 0x70, 0x51, 0xF3, 0x1F, 0xD6, 0xEB, 0xF2, 0x56, 0xA1, 0xC5, 0xA4, 0xEE, 0x72, + 0x62, 0xB2, 0x42, 0xDF, 0x5F, 0xA4, 0x6D, 0xCE, 0x43, 0x7D, 0x20, 0xFD, 0xF8, 0x11, 0x82, + 0xFE, 0xAC, 0x60, 0x8A, 0xAF, 0x51, 0x5B, 0xFA, 0xED, 0xA5, 0x24, 0xC8, 0xAB, 0x1C, 0xCA, + 0xC2, 0x5E, 0x0B, 0x76, 0x81, 0xE3, 0x85, 0x64, 0x5C, 0xCF, 0xF5, 0x33, 0x73, 0x1E, 0x7D, + 0x11, 0x2E, 0x22, 0x15, 0xB3, 0x88, 0x85, 0x52, 0x43, 0x31, 0x54, 0x94, 0xC6, 0x27, 0x48, + 0x46, 0x7C, 0x49, 0xB2, 0x68, 0x5C, 0x02, 0xB4, 0xCB, 0x4C, 0x22, 0xD5, 0xB7, 0x1D, 0x3E, + 0x0F, 0x63, 0xD1, 0x11, 0xA0, 0x55, 0x08, 0x73, 0x85, 0x62, 0x13, 0x57, 0x09, 0x03, 0xCB, + 0xDB, 0x47, 0x9D, 0xD6, 0x6F, 0xBD, 0xAA, 0x05, 0x62, 0xB9, 0x3E, 0x8D, 0xE8, 0x9E, 0x1E, + 0xD8, 0x85, 0x5A, 0x77, 0xF2, 0x8A, 0x26, 0x71, 0x81, 0xE2, 0x7F, 0xF3, 0x35, 0x70, 0xE9, + 0x0B, 0x97, 0xA9, 0xFE, 0xD9, 0xB9, 0x25, 0xCF, 0x68, 0x80, 0x6D, 0x7F, 0xB5, 0x68, 0xF7, + 0x85, 0x07, 0x71, 0xD9, 0xF8, 0xEF, 0x39, 0x14, 0x80, 0x2E, 0xC2, 0x17, 0x46, 0xF7, 0xFB, + 0xE8, 0xF9, 0x10, 0xD6, 0x17, 0xCF, 0x3A, 0x4F, 0x73, 0xAE, 0x08, 0xBC, 0xC2, 0x39, 0x10, + 0x3A, 0xD6, 0xF3, 0x77, 0xA1, 0x91, 0x93, 0x5C, 0xFE, 0xF4, 0x76, 0x11, 0xD9, 0xB7, 0x25, + 0xC2, 0x9E, 0x12, 0xDA, 0x0F, 0xBD, 0x25, 0x69, 0x03, 0xA8, 0xEA, 0x78, 0x88, 0x3D, 0xA3, + 0xC9, 0xFE, 0x38, 0x9C, 0x04, 0xC6, 0x38, 0x32, 0xD2, 0x1A, 0xC0, 0xC7, 0x86, 0x09, 0x73, + 0x24, 0xFA, 0x5B, 0x66, 0x81, 0x26, 0xB3, 0x1B, 0x90, 0x14, 0xB2, 0xBE, 0x34, 0x78, 0xB1, + 0x48, 0x0F, 0x36, 0xDE, 0xCF, 0xF1, 0x06, 0x7D, 0x04, 0x7D, 0x54, 0x16, 0x2B, 0xEB, 0xC7, + 0x38, 0x17, 0x71, 0x95, 0xCC, 0xB3, 0xD9, 0x80, 0x64, 0x90, 0x0E, 0x26, 0x5A, 0x87, 0x48, + 0xFF, 0x6C, 0xA2, 0x65, 0xFE, 0xE5, 0xEA, 0x27, 0x7B, 0x03, 0xD5, 0x42, 0x68, 0xD4, 0xE5, + 0x1E, 0x09, 0x3E, 0x11, 0xAE, 0xDD, 0x07, 0x14, 0x6C, 0x3C, 0x26, 0x2E, 0x58, 0xDE, 0xE9, + 0xE7, 0x95, 0xA9, 0x6D, 0x4F, 0x6D, 0x0E, 0x2A, 0xBF, 0x02, 0xF7, 0xCF, 0x11, 0xE9, 0x39, + 0x69, 0xF5, 0x63, 0x9C, 0x62, 0xBD, 0xA7, 0x50, 0xE9, 0x5F, 0xF4, 0x67, 0xC7, 0x4C, 0xB9, + 0xBF, 0xB6, 0xD5, 0xD5, 0x0B, 0x1F, 0x8A, 0xF8, 0x97, 0x60, 0x42, 0xF2, 0xC0, 0x51, 0xC8, + 0x70, 0x97, 0x9F, 0xC3, 0xB7, 0x41, 0xDE, 0xC8, 0xE6, 0x59, 0x80, 0x28, 0x66, 0x0B, 0x3F, + 0xBE, 0x54, 0xC5, 0x1D, 0x5B, 0x7B, 0x25, 0x11, + ]; let (_pk, sk) = MLKEM1024::keygen_from_seed(&seed).unwrap(); let ss = MLKEM1024::decaps(&sk, &ct).unwrap(); print!("{:x?}", ss); } - - fn main() { // print_struct_sizes() // bench_do_nothing() @@ -457,4 +1521,4 @@ fn main() { // bench_mlkem768_lowmemory_decaps() // bench_mlkem1024_decaps() // bench_mlkem1024_lowmemory_decaps() -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index 21b4895..b46df8c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,10 +4,10 @@ pub use bouncycastle_factory as factory; pub use bouncycastle_hex as hex; pub use bouncycastle_hkdf as hkdf; pub use bouncycastle_hmac as hmac; -pub use bouncycastle_mlkem as mlkem; -pub use bouncycastle_mlkem_lowmemory as mlkem_lowmemory; pub use bouncycastle_mldsa as mldsa; pub use bouncycastle_mldsa_lowmemory as mldsa_lowmemory; +pub use bouncycastle_mlkem as mlkem; +pub use bouncycastle_mlkem_lowmemory as mlkem_lowmemory; pub use bouncycastle_rng as rng; pub use bouncycastle_sha2 as sha2; -pub use bouncycastle_sha3 as sha3; \ No newline at end of file +pub use bouncycastle_sha3 as sha3; From 1e13941f3ddf16a1cc60e6a81f3b403e323b86ea Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Thu, 4 Jun 2026 08:21:50 +0200 Subject: [PATCH 2/2] ci: add rust-style CI workflow Run `cargo fmt --all --check` on every pull request to enforce the project's rustfmt.toml. Installs nightly rustfmt explicitly since rustfmt.toml sets `unstable_features = true`. Per-PR concurrency group cancels superseded runs. Signed-off-by: Nikola Pajkovsky --- .github/workflows/rust-style.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/rust-style.yml diff --git a/.github/workflows/rust-style.yml b/.github/workflows/rust-style.yml new file mode 100644 index 0000000..05dfed1 --- /dev/null +++ b/.github/workflows/rust-style.yml @@ -0,0 +1,27 @@ +name: Rust Style + +on: + pull_request: + +permissions: + contents: read + +concurrency: + group: rust-style-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + rustfmt: + name: rustfmt + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install nightly rustfmt + run: | + rustup toolchain install nightly --profile minimal --component rustfmt + rustup override set nightly + + - name: Check formatting + run: cargo fmt --all --check