crypto_api_osrandom 0.2.0

An interface to the OS' secure random number generator for `crypto_api`
Documentation
use crypto_api_osrandom::error::Error;

/// The amount of iterations over all tests
const TEST_ITERATIONS: usize = 8;
/// The data lengths for a test
const TEST_LENS: &[usize] = &[1024 * 1024, 4 * 1024 * 1024, (4 * 1024 * 1024) + 15];

/// A simple function to test the uniform distribution of byte values to catch an all-zero array or similar results of an
/// API misuse
///
/// _Important: This function *does not* attempt to test the randomness of the OS' CSPRNG_
fn test_uniform_dist(buf: &[u8]) {
    // Count the occurrences of each byte
    let mut occurrences = vec![0f64; 256];
    buf.iter().for_each(|b| occurrences[*b as usize] += 1.0);

    // Compute the estimated average occurrences and the according thresholds
    let est_avg = (buf.len() as f64) / 256.0;
    let (est_avg_min, est_avg_max) = (est_avg * 0.9, est_avg * 1.1);

    // Ensure that the occurrence of each byte is within the estimated average
    occurrences.iter().for_each(|d| {
        assert!(*d > est_avg_min, "{d} is not > {est_avg_min}");
        assert!(*d < est_avg_max, "{d} is not < {est_avg_max}");
    });
}

/// Tests the random number generator
#[test]
fn test() -> Result<(), Error> {
    // Perform multiple tests
    for _ in 0..TEST_ITERATIONS {
        for len in TEST_LENS {
            // Test the random data
            let buf = crypto_api_osrandom::to_vec(*len)?;
            test_uniform_dist(&buf)
        }
    }
    Ok(())
}

/// Test `test_uniform_dist` itself
#[test]
#[should_panic]
fn test_test_uniform_dist() {
    // Generate non-uniform data set
    let mut non_uniform_data = vec![0; (4 * 1024 * 1024) + 15];
    non_uniform_data.extend(vec![7; (4 * 1024 * 1024) + 15]);
    non_uniform_data.extend(vec![255; (4 * 1024 * 1024) + 15]);

    // Test function
    test_uniform_dist(&non_uniform_data);
}