#[cfg(feature = "std")]
pub fn verify_constant_time(iterations: usize) -> bool {
use crate::clockhash256;
use std::time::Instant;
let mut times = Vec::with_capacity(iterations);
for i in 0..iterations {
let input = if i % 2 == 0 { [0u8; 64] } else { [0xFFu8; 64] };
let start = Instant::now();
let _hash = clockhash256(&input);
let elapsed = start.elapsed();
times.push(elapsed.as_nanos());
}
if let (Some(&min), Some(&max)) = (times.iter().min(), times.iter().max()) {
let variation = (max - min) as f64 / min as f64;
variation < 0.1 } else {
false
}
}
pub fn verify_avalanche(input1: &[u8], input2: &[u8]) -> f64 {
use crate::clockhash256;
let hash1 = clockhash256(input1);
let hash2 = clockhash256(input2);
let mut diff_bits = 0;
for i in 0..32 {
diff_bits += (hash1[i] ^ hash2[i]).count_ones() as usize;
}
diff_bits as f64 / 256.0
}
pub fn verify_collision_resistance(test_cases: &[&[u8]]) -> bool {
use crate::clockhash256;
for i in 0..test_cases.len() {
let hash_i = clockhash256(test_cases[i]);
for j in (i + 1)..test_cases.len() {
let hash_j = clockhash256(test_cases[j]);
if hash_i == hash_j {
return false; }
}
}
true }
pub fn verify_domain_separation(data: &[u8], domains: &[&[u8]]) -> bool {
use crate::clockhash256_domain;
for i in 0..domains.len() {
let hash_i = clockhash256_domain(domains[i], data);
for j in (i + 1)..domains.len() {
let hash_j = clockhash256_domain(domains[j], data);
if hash_i == hash_j {
return false; }
}
}
true }
#[cfg(test)]
mod tests {
use super::*;
use crate::{clockhash256, tags};
#[test]
fn test_avalanche_effect() {
let input1 = [0u8; 64];
let mut input2 = input1;
input2[0] ^= 1;
let avalanche = verify_avalanche(&input1, &input2);
assert!(
avalanche > 0.3 && avalanche < 0.7,
"Avalanche coefficient {} should be close to 0.5",
avalanche
);
}
#[test]
fn test_collision_resistance() {
let test_cases: &[&[u8]] = &[
b"",
b"a",
b"abc",
b"message digest",
b"abcdefghijklmnopqrstuvwxyz",
&[0u8; 64],
&[0xFFu8; 64],
];
assert!(
verify_collision_resistance(test_cases),
"Collision resistance test failed"
);
}
#[test]
fn test_domain_separation() {
let data = b"test data";
let domains = [
tags::CLK_BLOCK,
tags::CLK_TX,
tags::CLK_MERKLE,
tags::CLK_NONCE,
tags::CLK_RNG,
];
assert!(
verify_domain_separation(data, &domains),
"Domain separation test failed"
);
}
#[test]
#[cfg(feature = "std")]
fn test_constant_time() {
let is_constant_time = verify_constant_time(100);
if !is_constant_time {
println!("Warning: Constant-time test failed - may be due to system noise");
println!("For proper constant-time verification, use ctgrind or valgrind");
}
}
#[test]
fn test_preimage_resistance() {
let target_hash = clockhash256(b"known input");
let different_input = b"different input";
let different_hash = clockhash256(different_input);
assert_ne!(
target_hash, different_hash,
"Different inputs should produce different hashes"
);
}
#[test]
fn test_second_preimage_resistance() {
let original_data = b"original message";
let original_hash = clockhash256(original_data);
let test_cases: &[&[u8]] = &[
b"different message",
b"another message",
b"modified message",
];
for &test_case in test_cases {
let test_hash = clockhash256(test_case);
assert_ne!(
original_hash, test_hash,
"Second preimage resistance: different data should not collide"
);
}
}
}