montana/Монтана-Протокол/Код/crates/mt-mnemonic/tests/test_vectors.rs

122 lines
4.3 KiB
Rust
Raw Normal View History

// spec, раздел "Ключи → Мнемоника и seed" → M-1 binding test vectors для v29.9.1
use mt_codec::domain;
use mt_crypto::sha256_raw;
use mt_mnemonic::{
entropy_to_mnemonic, mldsa_seed_for_role, mlkem_seed_for_role, mnemonic_to_master_seed,
};
fn hex(bytes: &[u8]) -> String {
let mut s = String::with_capacity(bytes.len() * 2);
for b in bytes {
s.push_str(&format!("{b:02x}"));
}
s
}
// === M-1 Test Vectors ===
#[test]
fn m1_vector_1_entropy_zero() {
let entropy = [0u8; 32];
let mnemonic = entropy_to_mnemonic(&entropy);
println!("\n=== M-1 Vector 1: entropy = [0x00; 32] ===");
println!("mnemonic: {mnemonic}");
let master_seed = mnemonic_to_master_seed(&mnemonic).expect("valid");
println!("master_seed: {}", hex(&master_seed));
assert_eq!(
hex(&master_seed),
concat!(
"38a1421ac3ce191fbdc46b1cca266a9d72d22320fb38bda6a3df90a1ead664a7",
"8951703197be882ace38e0f557a492a8e9ff5e3c02290a8eecf5939468708edb",
)
);
}
#[test]
fn m1_vector_2_entropy_all_ff() {
let entropy = [0xFFu8; 32];
let mnemonic = entropy_to_mnemonic(&entropy);
println!("\n=== M-1 Vector 2: entropy = [0xFF; 32] ===");
println!("mnemonic: {mnemonic}");
let master_seed = mnemonic_to_master_seed(&mnemonic).expect("valid");
println!("master_seed: {}", hex(&master_seed));
assert_eq!(
hex(&master_seed),
concat!(
"a5925c51583447a0abe43b65dbc591f3780a91c7d44c6b333975a211096039f3",
"d1d0ca9e125aa4e756f0a35b0006378ac69450e8254e32f16409a350f3ca9104",
)
);
}
#[test]
fn m1_vector_3_entropy_sha256_montana_test_vector_3() {
let entropy_hash = sha256_raw(b"Montana test vector 3");
let mut entropy = [0u8; 32];
entropy.copy_from_slice(&entropy_hash);
let mnemonic = entropy_to_mnemonic(&entropy);
println!("\n=== M-1 Vector 3: entropy = SHA-256(\"Montana test vector 3\") ===");
println!("entropy: {}", hex(&entropy));
println!("mnemonic: {mnemonic}");
let master_seed = mnemonic_to_master_seed(&mnemonic).expect("valid");
println!("master_seed: {}", hex(&master_seed));
assert_eq!(
hex(&master_seed),
concat!(
"da13e259eb58c79a650c312efe79d2ef42861ad114206ec48cb4b1eb5dcf0c22",
"75b074ef8b02fbc2123032090ff004d7cc546d2bbf34c4e10ec3c6fb092f9a47",
)
);
}
// === Per-role derivation Test Vectors (master_seed из M-1 Vector 1) ===
fn master_seed_vector_1() -> [u8; 64] {
let entropy = [0u8; 32];
let mnemonic = entropy_to_mnemonic(&entropy);
mnemonic_to_master_seed(&mnemonic).expect("valid")
}
// Vectors regenerated для ML-DSA-65 seed length L=32 (was Falcon L=48).
// HKDF-Expand детерминирован: hex значения вычислены первым прогоном теста
// и зафиксированы как binding vectors.
#[test]
fn derivation_vector_1_mldsa_account() {
let master = master_seed_vector_1();
let mldsa_seed = mldsa_seed_for_role(&master, domain::ACCOUNT_KEY);
println!("\n=== Derivation Vector 1: mldsa_seed(master_v1, \"mt-account-key\") ===");
println!("mldsa_seed_32: {}", hex(&mldsa_seed));
assert_eq!(
hex(&mldsa_seed),
"08ce5c19768c679fda24c0d3360e57ce03d00c94c175e59f50e9c77894c20818",
);
}
#[test]
fn derivation_vector_2_mldsa_node() {
let master = master_seed_vector_1();
let mldsa_seed = mldsa_seed_for_role(&master, domain::NODE_KEY);
println!("\n=== Derivation Vector 2: mldsa_seed(master_v1, \"mt-node-key\") ===");
println!("mldsa_seed_32: {}", hex(&mldsa_seed));
assert_eq!(
hex(&mldsa_seed),
"efe527d96de2cb82b3ee2e8ad24b4aca71014e37896b0c025a376335ad456acc",
);
}
#[test]
fn derivation_vector_3_mlkem_app_encryption() {
let master = master_seed_vector_1();
let mlkem_seed = mlkem_seed_for_role(&master, domain::APP_ENCRYPTION_KEY);
println!("\n=== Derivation Vector 3: mlkem_seed(master_v1, \"mt-app-encryption-key\") ===");
println!("mlkem_seed_64: {}", hex(&mlkem_seed));
assert_eq!(
hex(&mlkem_seed),
concat!(
"3eb9bcd201a1d5e671c9d23a929589a26ceb53338cd0684b5d77314a14601b03",
"9f3e2ae7e5e0be8acd47b4b928c3e73b5d875b9fc7089b22bc1d59e9dc31077e",
)
);
}