#entropy #hash #random #csprng #no-alloc

no-std rand_hash

Cryptographically-secure pseudo-random generator based on cryptographic hash function

3 releases

0.1.0 Jun 20, 2024
0.1.0-rc2 Jun 17, 2024
0.1.0-rc1 Jun 7, 2024

#651 in Cryptography

Download history 134/week @ 2024-06-03 15/week @ 2024-06-10 397/week @ 2024-06-17 6/week @ 2024-06-24 5/week @ 2024-07-01 53/week @ 2024-07-08 63/week @ 2024-07-15 11/week @ 2024-07-22 22/week @ 2024-07-29 5/week @ 2024-08-05 24/week @ 2024-08-12 101/week @ 2024-08-19 105/week @ 2024-08-26

235 downloads per month
Used in 4 crates (3 directly)

Apache-2.0

13KB
138 lines

Cryptographically-secure pseudo-random generator based on cryptographic hash function

HashRng is CSPRNG that takes any hashable data as seed and produces a stream of randomness that has the same entropy as the seed. It uses udigest crate to unambiguously hash the seed.

Motivation

Usually, CSPRNGs have a fixed-size seed. For instance, ChaCha20Rng has seed of 32 bytes. That means that when you want to derive randomness from data which has entropy exceeding 32 bytes, you'll have to truncate the seed to 32 bytes (e.g. by hashing it), so you won't be able to take advantage of exceeding entropy. This may influence security parameter and make it less secure than desired.

HashRng, on other hand, takes advantage of full entropy of the seed. It does so by hashing a counter and then the seed for each block, i.e. the output randomness is:

HashRng(seed) = H(0, seed) || H(1, seed) || ...

Security and performance considerations

HashRng internally uses u64 counter, which means that the period of the sequence is 264 times Digest::OutputSize (size of hash output).

Although we did not perform benchmarks, intuitively, HashRng is expected to be noticeably slower than other CSPRNG based on permutations (such as ChaCha20Rng)

Example

use rand::RngCore;

#[derive(udigest::Digestable)]
pub struct Seed<'a> {
    nonce: &'a u8,
    param_a: &'a str,
    param_b: &'a str,
    // ...
}

let seed = Seed {
    nonce: b"very unpredictable string",
    param_a: "some other data containing entropy",
    param_b: "something else",
    // ...
};
let mut rng = rand_hash::HashRng::<sha2::Sha256, _>::from_seed(&seed);

let mut randomness = 0u8; 256;
rng.fill_bytes(&mut randomness);

Dependencies

~445KB