Use fast key erasure in the ChaCha20 random number generator - #268
Merged
Merged
Conversation
chacha20_rng() kept its key until the next reseed, which happened only on the first call, after a fork or when the 32-bit block counter wrapped. Anyone who learned the generator state could therefore compute all output since the last reseed. - Fast key erasure: every refill generates 256 bytes of keystream; the first 32 bytes immediately replace the key, and only the remaining 224 bytes are handed out. Output that has already been returned can no longer be reconstructed from the current state. - Reseed from entropy() every 16384 refills (3.5 MiB of output), in addition to the first call and the fork detection. - Wipe handed-out bytes from the buffer.
Owner
|
Hi Markus, thanks for this PR, and for the detailed explanation of the changes, and the references to the literature.. |
This was referenced Sep 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hi Ulrich,
this is the last of the random number follow-ups I mentioned in #262. It changes only
chacha20_rng()insrc/chacha20poly1305.cand keeps your structure: the fork detection, the locking and the failure handling stay as they are.Type: Enhancement (security hardening)
Background
Same background as #267. For random number generators, the BSI technical guideline BSI TR-02102-1 (chapter 8) recommends deterministic generators of class DRG.3 or DRG.4 in the sense of AIS 20. DRG.3 requires that earlier output can't be computed from the generator's current state.
The problem
chacha20_rng()draws a key and a nonce fromentropy()once and derives all output from them. It reseeds only on the first call, after a fork, or when the 32-bit block counter wraps, which takes 256 GiB of output. Anyone who learns the generator state at some point, for example from a memory dump, can therefore compute all output since the last reseed: the salts, IVs and nonces that were already used.The change (only
chacha20_rng())entropy()every 16384 refills (3.5 MiB of output), in addition to the first call and the fork detection.This is the construction D. J. Bernstein describes in "Fast-key-erasure random-number generators" (2017). The random number generator of the Linux kernel (
crng_fast_key_erasure()indrivers/char/random.c) and OpenBSD'sarc4randomwork the same way.Cost (Apple M4):
chacha20scheme)sqlcipherscheme)Both are small compared to encrypting the page itself.
How serious is it? Low in practice: salts, IVs and nonces end up in the database file anyway, and whoever can read the process memory usually has the database key as well. But backtracking resistance is one of the properties an audit of the random number generation checks, and the change is small.
How I tested it
getrandom()is called twice for the first 3.5 MiB of output and twice more after one more byte.fork(), and two draws differ.autoreconf,./configure,make, the SQL tests andcryptotest) passes on Linux aarch64 and x86_64 with GCC and Clang.cryptotestalso passes on macOS and WebAssembly.Best regards,
Markus