[RFC] Replace the BLAKE2b-based PRNG with ChaCha20 (ChaCha20Rng) - #425
Open
davidrusu wants to merge 5 commits into
Open
[RFC] Replace the BLAKE2b-based PRNG with ChaCha20 (ChaCha20Rng)#425davidrusu wants to merge 5 commits into
davidrusu wants to merge 5 commits into
Conversation
…0Rng) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Applies the RFC to the specifications and moves the RFC text to the PR description, following the convention of #365/#375: - common-cryptographic-components: PRNG construction replaced with the ChaCha20 keystream (DJB variant, zero nonce), recommendation table split - message-encapsulation: CSPRBG reseated on ChaCha20Rng, seed truncated to 32 bytes at the CSPRBG boundary - blend-protocol: CSPRNG notation and modulo-bias parenthetical updated Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
davidrusu
marked this pull request as draft
August 27, 2026 21:03
With a zero nonce the DJB and RFC 8439 variants produce identical keystreams for the first 2^32 blocks, so implementations without a ChaCha20Rng-compatible library (e.g. the Nim client via BearSSL's br_chacha20_ct_run) can use any IETF ChaCha20 as-is. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Open
7 tasks
davidrusu
marked this pull request as ready for review
August 28, 2026 07:10
Contributor
Author
|
Implementation PR: logos-blockchain/logos-blockchain#3435 |
davidrusu
commented
Aug 28, 2026
Comment on lines
+123
to
+124
| - Implementations MAY use the IETF variant of ChaCha20 ([RFC 8439](https://datatracker.ietf.org/doc/html/rfc8439): 32-bit block counter, 96-bit nonce) with the nonce set to zero. With a zero nonce the two variants produce identical keystreams for the first $`2^{32}`$ blocks (256 GiB) of output: the original variant's upper counter word is zero in that range and coincides with the IETF variant's zero nonce words. | ||
| - Every use of this construction in the Logos Blockchain generates far less than $`2^{32}`$ blocks per seed, so any RFC 8439 implementation with a zero nonce and an initial counter of zero is byte-for-byte compatible with the definition above. |
Contributor
Author
There was a problem hiding this comment.
This note is here for Nim where the IETF variant is the dominant version in the ecosystem (The non-IETF variant is the popular form in rust)
The ChaCha20 construction no longer truncates internally: it takes exactly a 32-byte seed, and each protocol states once, normatively, that CSPRBG(H(x)) means seeding with the first 32 bytes of the digest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The four domain-separated hash functions existed solely to seed the CSPRBG, so their 64-byte digests were always immediately halved. With 32-byte output the digest is the seed and no truncation exists anywhere. Note BLAKE2b-256 is not truncated BLAKE2b-512 (digest length is in the parameter block), so derived values change; the RFC is already wire-value-breaking. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
davidrusu
added a commit
to logos-blockchain/logos-blockchain
that referenced
this pull request
Aug 28, 2026
Implements the RFC v3 change (logos-co/logos-lips#425): the domain-separated seed hash is re-parameterized from BLAKE2b-512 to BLAKE2b-256, so the digest is the ChaCha20 seed and no truncation exists. The now-unused blake2b512 helper is removed. BLAKE2b-256 is not truncated BLAKE2b-512 (digest length is in the parameter block), so all keystream-derived values change: codec fixtures regenerated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
[RFC] Replace the BLAKE2b-Based PRNG with ChaCha20 (ChaCha20Rng)
Authors: David Rusu
Approvals (research):
Approvals (engineering):
Reviewer Orientation
Read Motivation first.
common-cryptographic-components.md, PRNG construction replaced (Details §1)message-encapsulation.md,CSPRBGreseated on ChaCha20 (Details §2)E_k/D_k, fillers, header randomization) changes value; zero-nonce safetyblend-protocol.md,CSPRNGnotation and Proof of Selection (Details §3)m_iderivation changes value; little-endian and modulo-bias analysis unaffectedStatus tracker
Change log
Motivation
All deterministic randomness in the Blend protocol and Message Encapsulation comes from a home-grown construction: BLAKE2b in counter mode over a 64-byte seed. Its dominant use is as an encryption keystream:
E_k(x) = CSPRBG(k) ⊕ xprotects blend payloads and headers, making the PRNG a de facto stream cipher.No weakness is known, but the construction is bespoke: no dedicated cryptanalysis as a stream cipher, no published test vectors, and every implementation must hand-roll it. ChaCha20 is a standardized, extensively analyzed stream cipher with audited implementations in every mainstream language (
ChaCha20Rngfromrand_chachain Rust). Switching removes a bespoke construction from the protocol's trusted surface at equal or better performance.Proposal
Replace the BLAKE2b-Based PRNG Construction with the ChaCha20 keystream:
ChaCha20 is used in Bernstein's original variant (20 rounds, 256-bit key, 64-bit nonce, 64-bit block counter). This is byte-for-byte the output of
rand_chacha::ChaCha20Rng::from_seed(key)with the default stream identifier. Consumers take the firstnbytes (orkbits) of the keystream, as today.All call-site formulas are unchanged as written, but every produced value changes with the keystream. The only structural change is at the seeding boundary: the construction takes exactly a 32-byte seed, and the four domain-separated seed hashes (
H_N/H_I/H_b/H_P) are re-parameterized from BLAKE2b-512 to BLAKE2b-256, so the digest is the seed and no truncation exists anywhere.This PR applies the change to Common Cryptographic Components, Message Encapsulation, and the Blend Protocol.
Discussion
Security
H_N/H_I/H_b/H_Pare re-parameterized to 32-byte output, since seeding the CSPRBG is their only use: the digest is the seed, with no truncation step to get wrong. Note BLAKE2b-256 is not a truncated BLAKE2b-512 (the digest length is part of BLAKE2b's parameter block), so this changes derived values; the RFC is wire-value-breaking regardless.Alternatives considered
ChaCha20Rng's default construction. The DJB variant makes "useChaCha20Rngoff the shelf" a conforming implementation.Compatibility and rollout
Wire-value-breaking with an unchanged wire format: sizes, layouts, and serialization are identical, but every keystream, filler, randomized header, and Proof of Selection index takes a different value. Old and new nodes cannot interoperate, so the change must ship as a coordinated protocol version bump (or before any deployed network exists).
Ancillary properties
CSPRBG()_8/ little-endian conventions apply unchanged, and the modulo-bias analysis in the Blend Protocol is unaffected.ChaCha20Rngships SIMD backends), and the keystream is cheaply seekable.Details
1. Common Cryptographic Components: replace the PRNG construction
The "BLAKE2b-Based PRNG Construction" section becomes "ChaCha20-Based PRNG Construction":
The new section specifies:
ChaCha20Rng(rand_chacha) with the default stream identifier.nbytes; forkbits, truncate the last byte.br_chacha20_ct_runalready in its dependency tree.The recommendation table is updated:
2. Message Encapsulation:
CSPRBGnotation and pseudocodeThe
CSPRBG()/CSPRBG()_xdefinitions point at the new construction and the reference pseudocode becomes:The
hashdsreference implementations ofH_N/H_I/H_b/H_Pchange fromBlake2b.hash512toBlake2b.hash256; their 32-byte digest is the CSPRBG seed.The
E_k/D_k, filler (r_{t,1..4}), header randomization, and node selection (l_i) formulas are textually unchanged. A note points at the interoperability condition (allCSPRBGoutputs are message-sized, so IETF ChaCha20 with a zero nonce is compatible).3. Blend Protocol:
CSPRNGnotation and Proof of SelectionCSPRNG()now links to the ChaCha20-Based PRNG Construction.m_i = CSPRNG(H_N(ρ))_8 mod Nis unchanged as written; the 8-byte output is now the first 8 bytes of the keystream seeded withH_N(ρ)[0..32], still little-endian.Chores
Implementation
CSPRBGonChaCha20Rng(rand_chacha), seeded with the first 32 bytes of the domain-separated BLAKE2b digest, replacingBlakeRngm_i) and its verificationCSPRBGoutputs for known seeds, encapsulate/decapsulate round trips,m_iselection vectorsBlakeRngimplementation once no call sites remainAffected Specifications
CSPRBGreseated on ChaCha20; all keystream values changeCSPRNGnotation and Proof of Selection updatedρ; listed for reviewer attention to confirm no PRNG dependency🤖 Generated with Claude Code