clock-hash 1.0.0

ClockHash-256: Consensus hash function for ClockinChain
Documentation
//! Security property benchmarks for ClockHash-256
//!
//! This module provides comprehensive benchmarks for verifying and measuring
//! the cryptographic security properties of ClockHash-256 implementations.

use clock_hash::{clockhash256, tags, verify_avalanche, verify_collision_resistance, verify_domain_separation};
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use std::hint::black_box;

/// Benchmark constant-time verification
///
/// This benchmark measures the performance of constant-time verification,
/// which is crucial for side-channel resistance.
fn bench_constant_time_verification(c: &mut Criterion) {
    let mut group = c.benchmark_group("constant_time_verification");

    let iterations = [100, 1000, 10000];

    for &iter in &iterations {
        group.bench_with_input(
            BenchmarkId::from_parameter(format!("{}_iterations", iter)),
            &iter,
            |b, &iter| {
                b.iter(|| {
                    // Note: This would normally call verify_constant_time, but it's currently unused
                    // For now, we'll benchmark a representative constant-time operation
                    let mut result = 0u64;
                    for i in 0..iter {
                        // Simulate constant-time operation with data-dependent computation
                        let data = vec![(i % 256) as u8; 1024];
                        let hash = clockhash256(black_box(&data));
                        result ^= u64::from_le_bytes(hash[0..8].try_into().unwrap());
                    }
                    black_box(result);
                });
            },
        );
    }

    group.finish();
}

/// Benchmark avalanche effect verification
///
/// Measures how well single-bit changes in input propagate to output bits.
/// Good avalanche effect is essential for cryptographic strength.
fn bench_avalanche_verification(c: &mut Criterion) {
    let mut group = c.benchmark_group("avalanche_verification");

    let sizes = [64, 256, 1024, 4096]; // Input sizes in bytes

    for &size in &sizes {
        let input1 = vec![0x00u8; size];
        let input2 = {
            let mut v = vec![0x00u8; size];
            if !v.is_empty() {
                v[0] = 0x01; // Single bit difference
            }
            v
        };

        group.bench_with_input(
            BenchmarkId::from_parameter(format!("{}_bytes", size)),
            &(input1, input2),
            |b, (input1, input2)| {
                b.iter(|| {
                    let avalanche = verify_avalanche(black_box(input1), black_box(input2));
                    black_box(avalanche);
                });
            },
        );
    }

    group.finish();
}

/// Benchmark collision resistance verification
///
/// Tests the hash function's resistance to finding collisions.
/// This is a fundamental security property.
fn bench_collision_resistance(c: &mut Criterion) {
    let mut group = c.benchmark_group("collision_resistance");

    let test_case_counts = [10, 50, 100, 500];

    for &count in &test_case_counts {
        // Generate test cases with different patterns
        let test_cases: Vec<Vec<u8>> = (0..count)
            .map(|i| {
                match i % 4 {
                    0 => vec![0x00u8; 32], // All zeros
                    1 => vec![0xFFu8; 32], // All ones
                    2 => (0..32).map(|j| (i * j) as u8).collect(), // Pattern
                    _ => vec![i as u8; 32], // Constant value
                }
            })
            .collect();

        let test_refs: Vec<&[u8]> = test_cases.iter().map(|v| v.as_slice()).collect();

        group.bench_with_input(
            BenchmarkId::from_parameter(format!("{}_cases", count)),
            &test_refs,
            |b, test_refs| {
                b.iter(|| {
                    let is_collision_resistant = verify_collision_resistance(black_box(test_refs));
                    black_box(is_collision_resistant);
                });
            },
        );
    }

    group.finish();
}

/// Benchmark domain separation verification
///
/// Ensures that different domain tags produce different hash outputs,
/// preventing cross-domain collision attacks.
fn bench_domain_separation_verification(c: &mut Criterion) {
    let mut group = c.benchmark_group("domain_separation_verification");

    let data_sizes = [64, 256, 1024];

    for &size in &data_sizes {
        let data = vec![0x42u8; size];
        let domains = vec![
            tags::CLK_BLOCK,
            tags::CLK_TX,
            tags::CLK_MERKLE,
            tags::CLK_NONCE,
            tags::CLK_RNG,
        ];

        group.bench_with_input(
            BenchmarkId::from_parameter(format!("{}_bytes", size)),
            &(data, domains),
            |b, (data, domains)| {
                b.iter(|| {
                    let is_domain_separated = verify_domain_separation(
                        black_box(data),
                        black_box(&domains.iter().map(|d| *d).collect::<Vec<_>>()),
                    );
                    black_box(is_domain_separated);
                });
            },
        );
    }

    group.finish();
}

/// Benchmark security property verification suite
///
/// Runs the complete security verification suite to ensure
/// all cryptographic properties are maintained.
fn bench_security_property_suite(c: &mut Criterion) {
    let mut group = c.benchmark_group("security_property_suite");

    group.bench_function("full_security_verification", |b| {
        b.iter(|| {
            // Avalanche effect test
            let input1 = vec![0x00u8; 1024];
            let input2 = {
                let mut v = vec![0x00u8; 1024];
                v[0] = 0x01;
                v
            };
            let avalanche = verify_avalanche(&input1, &input2);
            black_box(avalanche);

            // Collision resistance test
            let test_cases = vec![
                &[0x00u8; 32][..],
                &[0xFFu8; 32][..],
                &[0xAAu8; 32][..],
            ];
            let collision_resistant = verify_collision_resistance(&test_cases);
            black_box(collision_resistant);

            // Domain separation test
            let data = vec![0x42u8; 256];
            let domains = vec![tags::CLK_BLOCK, tags::CLK_TX, tags::CLK_MERKLE];
            let domain_separated = verify_domain_separation(&data, &domains);
            black_box(domain_separated);
        });
    });

    group.finish();
}

/// Benchmark hash function security under adversarial inputs
///
/// Tests hash function behavior with inputs designed to potentially
/// reveal weaknesses or timing variations.
fn bench_adversarial_inputs(c: &mut Criterion) {
    let mut group = c.benchmark_group("adversarial_inputs");

    // Different types of adversarial inputs
    let inputs = vec![
        ("all_zeros", vec![0x00u8; 4096]),
        ("all_ones", vec![0xFFu8; 4096]),
        ("alternating", (0..4096).map(|i| if i % 2 == 0 { 0x00 } else { 0xFF }).collect()),
        ("increasing", (0..4096).map(|i| (i % 256) as u8).collect()),
        ("decreasing", (0..4096).map(|i| (255 - (i % 256)) as u8).collect()),
        ("sparse_ones", (0..4096).map(|i| if i % 128 == 0 { 0xFF } else { 0x00 }).collect()),
    ];

    for (name, data) in inputs {
        group.bench_with_input(
            BenchmarkId::from_parameter(name),
            &data,
            |b, data| {
                b.iter(|| {
                    let hash = clockhash256(black_box(data));
                    black_box(hash);
                });
            },
        );
    }

    group.finish();
}

/// Benchmark timing analysis resistance
///
/// Measures hash function timing with inputs of different lengths
/// to verify resistance to timing-based side-channel attacks.
fn bench_timing_resistance(c: &mut Criterion) {
    let mut group = c.benchmark_group("timing_resistance");

    // Test various input sizes to check for timing variations
    let sizes = [0, 1, 32, 64, 128, 256, 512, 1024, 2048, 4096];

    for &size in &sizes {
        let data = vec![0x42u8; size];

        group.bench_with_input(
            BenchmarkId::from_parameter(format!("{}_bytes", size)),
            &data,
            |b, data| {
                b.iter(|| {
                    let hash = clockhash256(black_box(data));
                    black_box(hash);
                });
            },
        );
    }

    group.finish();
}

criterion_group!(
    benches,
    bench_constant_time_verification,
    bench_avalanche_verification,
    bench_collision_resistance,
    bench_domain_separation_verification,
    bench_security_property_suite,
    bench_adversarial_inputs,
    bench_timing_resistance,
);
criterion_main!(benches);