#[cfg(test)]
mod tests {
use crate::common::Result;
use crate::dsign::Ed25519;
use crate::kes::{KesAlgorithm, SingleKes, Sum2Kes, Sum6Kes};
#[test]
fn test_single_kes_deterministic() -> Result<()> {
type TestKes = SingleKes<Ed25519>;
let seed = [42u8; 32];
let sk1 = TestKes::gen_key_kes_from_seed_bytes(&seed)?;
let vk1 = TestKes::derive_verification_key(&sk1)?;
let sk2 = TestKes::gen_key_kes_from_seed_bytes(&seed)?;
let vk2 = TestKes::derive_verification_key(&sk2)?;
assert_eq!(vk1.as_bytes(), vk2.as_bytes());
let message = b"test message";
let sig1 = TestKes::sign_kes(&(), 0, message, &sk1)?;
let sig2 = TestKes::sign_kes(&(), 0, message, &sk2)?;
assert_eq!(sig1.as_bytes(), sig2.as_bytes());
TestKes::verify_kes(&(), &vk1, 0, message, &sig1)?;
TestKes::verify_kes(&(), &vk2, 0, message, &sig2)?;
Ok(())
}
#[test]
fn test_sum2_kes_evolution() -> Result<()> {
type TestKes = Sum2Kes;
let seed = [99u8; 32];
let mut sk = TestKes::gen_key_kes_from_seed_bytes(&seed)?;
let vk = TestKes::derive_verification_key(&sk)?;
for period in 0..4 {
let message = format!("period_{}", period);
let sig = TestKes::sign_kes(&(), period, message.as_bytes(), &sk)?;
TestKes::verify_kes(&(), &vk, period, message.as_bytes(), &sig)?;
if period > 0 {
let wrong_result =
TestKes::verify_kes(&(), &vk, period - 1, message.as_bytes(), &sig);
assert!(wrong_result.is_err());
}
if period < 3 {
sk = TestKes::update_kes(&(), sk, period)?
.expect("Key should not expire before period 3");
}
}
let expired = TestKes::update_kes(&(), sk, 3)?;
assert!(expired.is_none());
Ok(())
}
#[test]
fn test_sum6_kes_cardano_standard() -> Result<()> {
type TestKes = Sum6Kes;
let seed = [0x5F; 32];
let sk = TestKes::gen_key_kes_from_seed_bytes(&seed)?;
let vk = TestKes::derive_verification_key(&sk)?;
let test_periods = [0, 1, 31, 32, 63];
for &period in &test_periods {
let message = format!("Cardano block slot {}", period * 1000);
if period == 0 {
let sig = TestKes::sign_kes(&(), period, message.as_bytes(), &sk)?;
TestKes::verify_kes(&(), &vk, period, message.as_bytes(), &sig)?;
}
}
Ok(())
}
#[test]
fn test_verification_key_stability() -> Result<()> {
type TestKes = Sum2Kes;
let seed = [7u8; 32];
let mut sk = TestKes::gen_key_kes_from_seed_bytes(&seed)?;
let vk_initial = TestKes::derive_verification_key(&sk)?;
for period in 0..3 {
let vk_current = TestKes::derive_verification_key(&sk)?;
assert_eq!(vk_initial, vk_current);
sk = TestKes::update_kes(&(), sk, period)?.expect("Key should not expire");
}
let vk_final = TestKes::derive_verification_key(&sk)?;
assert_eq!(vk_initial, vk_final);
Ok(())
}
#[test]
fn test_cross_period_validation_failure() -> Result<()> {
type TestKes = Sum2Kes;
let seed = [3u8; 32];
let sk = TestKes::gen_key_kes_from_seed_bytes(&seed)?;
let vk = TestKes::derive_verification_key(&sk)?;
let message = b"cross period test";
let sig_p0 = TestKes::sign_kes(&(), 0, message, &sk)?;
TestKes::verify_kes(&(), &vk, 0, message, &sig_p0)?;
let result_p1 = TestKes::verify_kes(&(), &vk, 1, message, &sig_p0);
assert!(result_p1.is_err());
let result_p2 = TestKes::verify_kes(&(), &vk, 2, message, &sig_p0);
assert!(result_p2.is_err());
Ok(())
}
#[test]
fn test_wrong_message_fails() -> Result<()> {
type TestKes = SingleKes<Ed25519>;
let seed = [11u8; 32];
let sk = TestKes::gen_key_kes_from_seed_bytes(&seed)?;
let vk = TestKes::derive_verification_key(&sk)?;
let message1 = b"original message";
let message2 = b"different message";
let sig = TestKes::sign_kes(&(), 0, message1, &sk)?;
TestKes::verify_kes(&(), &vk, 0, message1, &sig)?;
let wrong_result = TestKes::verify_kes(&(), &vk, 0, message2, &sig);
assert!(wrong_result.is_err());
Ok(())
}
#[test]
fn test_kes_size_constants() {
type TestSingleKes = SingleKes<Ed25519>;
type TestSum2Kes = Sum2Kes;
type TestSum6Kes = Sum6Kes;
assert_eq!(TestSingleKes::SEED_SIZE, 32);
assert_eq!(TestSingleKes::VERIFICATION_KEY_SIZE, 32);
assert_eq!(TestSingleKes::SIGNATURE_SIZE, 64);
assert_eq!(TestSingleKes::total_periods(), 1);
assert_eq!(TestSum2Kes::SEED_SIZE, 32);
assert_eq!(TestSum2Kes::VERIFICATION_KEY_SIZE, 32); assert_eq!(TestSum2Kes::total_periods(), 4);
assert_eq!(TestSum6Kes::SEED_SIZE, 32);
assert_eq!(TestSum6Kes::VERIFICATION_KEY_SIZE, 32);
assert_eq!(TestSum6Kes::total_periods(), 64);
}
}