Skip to content

fix(keypairs): use OsRng directly for seed entropy (#286)#300

Open
satyakwok wants to merge 1 commit into
XRPLF:mainfrom
satyakwok:fix/wallet-seed-rng-osrng-286
Open

fix(keypairs): use OsRng directly for seed entropy (#286)#300
satyakwok wants to merge 1 commit into
XRPLF:mainfrom
satyakwok:fix/wallet-seed-rng-osrng-286

Conversation

@satyakwok

Copy link
Copy Markdown

Closes #286.

Summary

generate_seed was seeding an Hc128Rng stream cipher from the OS once per call, then filling the seed buffer from that cipher's keystream:

let mut rng = rand_hc::Hc128Rng::from_entropy();
rng.fill(&mut random_bytes);

HC-128 is a recognised eSTREAM-portfolio cipher, but the choice means a single compromise of the initial entropy snapshot inside the process can expose every wallet generated during that process lifetime — and it departs from what xrpl-py and xrpl.js use.

This PR replaces the call with rand::rngs::OsRng, which reads from the OS entropy pool on every call:

rand::rngs::OsRng.fill(&mut random_bytes);

Also:

  • Drops the rand_hc = "0.3.1" dependency from Cargo.toml — no other call sites.
  • Removes the now-unused use rand::SeedableRng;.
  • The existing rand = "0.8.5" already has the getrandom feature enabled, so OsRng works in both std and no_std modes.

Tests

Adds generate_seed_without_entropy_produces_distinct_outputs — pins the property that two consecutive generate_seed(None, None) calls return different seeds. Trivially true with OsRng but worth locking so any future RNG swap is forced to preserve it.

The existing deterministic-path tests (generate_seed(Some(TEST_BYTES), ...)) are unchanged and still pass.

Smoke gate

  • cargo build
  • cargo build --no-default-features --features embassy-rt,core,utils,wallet,models,helpers,websocket,json-rpc ✓ (no_std mode)
  • cargo test --lib -- --skip asynch:: — 587 passed, 0 failed
  • The 4 asynch::* tests that hit live XRPL testnet endpoints are skipped here; they're network-flaky and unrelated to this change.

`generate_seed` was seeding an `Hc128Rng` stream cipher from the OS once
per call, then filling the seed buffer from that cipher's keystream.
HC-128 is a recognised eSTREAM-portfolio cipher, but the choice means a
single compromise of the initial entropy snapshot inside the process
exposes every wallet generated during the process lifetime — and it
departs from what xrpl-py and xrpl.js use for secret-material
generation.

Replace `rand_hc::Hc128Rng::from_entropy()` with `rand::rngs::OsRng`,
which reads from the OS entropy pool on each call. Drop the
`rand_hc = "0.3.1"` dependency from `Cargo.toml` (it had no other call
sites) and remove the now-unused `use rand::SeedableRng;`.

Adds `generate_seed_without_entropy_produces_distinct_outputs` — pins
the property that two consecutive `generate_seed(None, None)` calls
return different seeds. Trivially true with `OsRng` but worth locking
so any future RNG swap is forced to preserve it.

The existing `generate_seed(Some(TEST_BYTES), ...)` deterministic-path
tests are unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wallet seed generation uses Hc128Rng::from_entropy instead of OsRng

1 participant