Skip to content

Commit

Permalink
Add rand_core impls for OutputReader
Browse files Browse the repository at this point in the history
  • Loading branch information
Taylor C. Richberger committed Nov 14, 2023
1 parent 92e4cd7 commit 0933c1f
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ mmap = ["std", "dep:memmap2"]
# Implement the zeroize::Zeroize trait for types in this crate.
zeroize = ["dep:zeroize", "arrayvec/zeroize"]

# Implement the rand_core Rng traits for OutputReader, allowing using it as
# a rand::Rng.
rand = ["dep:rand_core"]

# This crate implements traits from the RustCrypto project, exposed here as the
# "traits-preview" feature. However, these traits aren't stable, and they're
# expected to change in incompatible ways before they reach 1.0. For that
Expand Down Expand Up @@ -101,6 +105,7 @@ memmap2 = { version = "0.7.1", optional = true }
rayon = { version = "1.2.1", optional = true }
serde = { version = "1.0", default-features = false, features = ["derive"], optional = true }
zeroize = { version = "1", default-features = false, features = ["zeroize_derive"], optional = true }
rand_core = { version = "0.6", default-features = false, optional = true }

[dev-dependencies]
hmac = "0.12.0"
Expand Down
39 changes: 39 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1643,3 +1643,42 @@ impl std::io::Seek for OutputReader {
Ok(self.position())
}
}

#[cfg(feature = "rand")]
impl rand_core::SeedableRng for OutputReader {
type Seed = [u8; 32];

#[inline]
fn from_seed(seed: Self::Seed) -> Self {
let mut hasher = Hasher::new();
hasher.update(&seed);
hasher.finalize_xof()
}
}

#[cfg(feature = "rand")]
impl rand_core::RngCore for OutputReader {
#[inline]
fn next_u32(&mut self) -> u32 {
rand_core::impls::next_u32_via_fill(self)
}

#[inline]
fn next_u64(&mut self) -> u64 {
rand_core::impls::next_u64_via_fill(self)
}

#[inline]
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.fill(dest);
}

#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
self.fill(dest);
Ok(())
}
}

#[cfg(feature = "rand")]
impl rand_core::CryptoRng for OutputReader {}
22 changes: 22 additions & 0 deletions src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,3 +820,25 @@ fn test_serde() {
let hash2: crate::Hash = serde_json::from_str(&json).unwrap();
assert_eq!(hash, hash2);
}

#[test]
#[cfg(feature = "rand")]
fn test_rand_core() {
let mut seeded = crate::OutputReader::from_seed([b'0'; 32]);
let mut buf = [0u8; 64];
seeded.fill_bytes(&mut buf);
// Verified using: printf 00000000000000000000000000000000 | b3sum -l 76
assert_eq!(
&buf,
b"\
\x9a\x91\x3b\xc3\x24\xb1\x7e\x97\x31\x3a\x3e\x6b\x1d\x24\x05\x44\
\xbd\xab\xb7\x0e\xe2\xd0\xdd\x0f\x80\x25\x8c\x95\x70\x43\x1e\xb1\
\x43\x9a\x91\x99\xca\x39\xbe\xae\x7f\x16\xe7\x0a\x96\xc4\x60\xba\
\x11\x57\xb6\xc9\xd7\x85\x07\xd7\x37\xef\xae\x55\x23\x1f\x08\x6f\
",
);

// defers to rand_core::impls, which interpret bytes little-endian.
assert_eq!(seeded.gen::<u32>(), 0x91bd7fa7u32);
assert_eq!(seeded.gen::<u64>(), 0x81f88d825bee930fu64);
}

0 comments on commit 0933c1f

Please sign in to comment.