Expand description
Persisted entropy pool: a flash-seeded, hash-ratcheted CSPRNG.
The pool exists for platforms whose hardware entropy source is not always available — on the ESP32 the TRNG is only trustworthy while the RF subsystem is up, which used to chain the RNG’s lifetime to the BLE controller’s. A seed stored in flash breaks that chain: the pool is cryptographically strong from the first instruction of boot, and the hardware source becomes something it harvests when available rather than something it dies without.
§The seed-file protocol (Fortuna’s, with a lazy write)
- Read the stored seed
Sand build the pool withEntropyPool::from_seed. The working key isHKDF(S, salt)with per-boot salt (chip id, reset reason) — flash never holds the working key, and a flash image taken later reveals nothing about this session’s outputs. - Before the first draw, write
next_seedto flash and, once the write is confirmed, callseed_committed. - Draw.
drawrefuses until step 2 has happened — that ordering is the whole crash-safety story. A boot that dies before the commit replays a working key that never emitted a byte, which is harmless; a boot that dies after it ratchets forward next time. No boot counter is needed.
The write is deliberately lazy: nothing touches flash until something actually wants randomness, so a reboot loop that dies before its first draw costs zero flash cycles.
§Mixing
mix folds harvested entropy into the working
key whenever a hardware source happens to be live. Mixing is what
heals a compromised or cloned seed file, so callers should persist a
fresh next_seed afterwards — but mixing
never invalidates the commit, because replay safety comes from the
boot-time ratchet, not from the stored seed tracking the live key.
§Construction
Everything is HKDF-SHA256 over the platform’s Sha256Provider;
there is no stream cipher because every consumer wants a small seed
or nonce, not a keystream. Each draw ratchets the working key
one-way, so compromising the pool later reveals nothing already
emitted. Domain separation comes from distinct info strings plus
the caller’s label as HKDF salt.
Structs§
- Draw
Before Commit - A draw was attempted before the next seed was committed to storage.
- Entropy
Pool - The pool: a 32-byte working key that only ever moves forward.