Files
HIPs/HIPs/hip-0089-drbg-randomness-beacon.md
zeekay ad5a010f79 Three words for what a proposal is, and a generator that refuses
The same fact lived in nine hand-kept places and they disagreed about 58
proposals. This makes the file the only authority and everything else a
projection of it.

ONE VOCABULARY, in vocabulary.json, read by the lint, the generator and the
doc site. Three words, each answering "can I rely on this?" and nothing else:

    Draft    nothing implements it yet, or its own text says the work is ahead
    Final    the thing it specifies exists in the code
    Living   governance and process: amended in place, never finished

Eight spellings folded in. `Active` was the one doing real damage: on four Meta
and Process HIPs it meant living, on 48 others it meant shipped, and one word
doing two jobs is why nothing agreed. `Review` and `Last Call` described a
queue rather than a document, and a proposal under review is still one you
cannot build against.

STATUS IS EARNED, not declared. Every Standards Track proposal was checked
against the estate: 235 have their implementation, and eight do not and say so.
HIP-0095 carries a twelve-week plan ending at "mainnet launch" and has no code.
HIP-0525 specifies an all-machine meeting while apps/meet refuses a machine a
seat. HIP-0078 names a prover at a "planned location" that does not exist.
HIP-0114 is the cog.* procedure set, and that procedure set returns nothing.
HIP-0003, HIP-0102, HIP-0305 and HIP-0901 likewise: looked, found nothing.

SIXTEEN TOMBSTONES DELETED rather than statused. A dead document kept alive in
the index is one concept wearing two names. Each successor exists and carries
the text, and the 90 references that pointed at a tombstone now point at it --
whole markdown links at once, so link text cannot outlive its target. Three of
the sixteen were pure compatibility: HIP-0028 specified a migration off a
Bitnami chart, HIP-0029 dual-engine MySQL, HIP-0030 a schema-deprecation
policy. We ship no backwards compatibility, so we do not specify it.

Nine links were already broken and had been since the corpus was renumbered:
short-form ./hip-5.md paths that never existed. Two named the wrong proposal --
one cited "HIP-1: Hanzo Multimodal Models" where multimodal is HIP-0003.

THE GENERATOR REFUSES more often than it writes, because a short table looks
exactly as authoritative as a complete one. Rows must equal files; a shrinking
index must say by how much; a section whose input is missing is an error, not
an omission; nothing is written until all of it validates. Its self-test breaks
the corpus eleven ways and requires each to refuse AND leave README byte-
identical -- a guard that reports after half-writing has protected nothing.
The lint's second implementation of the same comparison is gone.

The site rendered 52 proposals with a fallback grey badge and counted them
toward none of its three stat tiles, because docs/lib/source.ts declared a
status union by hand: it admitted a `Stagnant` no file has ever carried and
omitted the one 52 files did. Five components each kept their own copy of the
colours. All six now read vocabulary.json.
2026-08-28 18:05:41 -07:00

6.7 KiB

hip, title, type, category, status, author, created, requires
hip title type category status author created requires
0089 DRBG / Randomness Beacon (SP 800-90A/B) Standards Track Cryptography Final Hanzo AI 2026-05-11 HIP-0005, HIP-0077, HIP-0078, HIP-0079, HIP-0084

HIP-0089: DRBG / Randomness Beacon (SP 800-90A/B)

Abstract

HIP-0089 specifies the randomness beacon and DRBG (Deterministic Random Bit Generator) construction under the strict-PQ profile, together with the SP 800-90B health testing and conditioning the entropy feeding it must pass. The beacon emits per-block randomness derived from a Hash-DRBG (NIST SP 800-90A Rev. 1, §10.1) instantiated over SHA3-384, reseeded each epoch from a quantum-random entropy source supplemented with beacon participants' ML-DSA-65 contributions threshold-aggregated via Pulsar-M (HIP-0084). The beacon output is bound into Q-Chain blocks via the existing TupleHash256 transcript (HIP-0079). LP-131's ECVRF-Ed25519 randomness is classical and explicitly NOT used under strict-PQ.

Specification

Canonical reference: luxfi/consensus/protocol/auth/beacon.go (auth-pq-surface branch).

HashDRBG state (per SP 800-90A §10.1.1):
    V                 [48]byte    // 384-bit internal state
    C                 [48]byte    // 384-bit constant
    reseed_counter    uint64
    security_strength = 256       // FIPS PQ Cat 5 floor

instantiation:
    seed_material = entropy_in (≥ 384 bits of conditioned QRNG)
                  || nonce_in    (≥ 192 bits)
                  || personalization "LUX-BEACON-V1"
    V = SHA3-384("INIT" || seed_material)
    C = SHA3-384("CONST" || V || seed_material)
    reseed_counter = 1

generate(num_bits):
    output ← SHA3-384(V) truncated/extended to num_bits
    V = (V + C + reseed_counter) mod 2^384
    reseed_counter += 1
    return output

reseed:
    triggered at epoch boundary OR when reseed_counter ≥ 2^48
    additional_input = QRNG entropy ⊕ Pulsar-M aggregated contribution
    V = SHA3-384("RESEED" || V || additional_input)
    reseed_counter = 1

Per-block beacon output:

beacon_round(H) = HashDRBG.generate(384)
beacon_commit(H) = TupleHash256(
    "BEACON-V1",
    [ height_be8, beacon_round(H), epoch_be8, drbg_state_root ],
    384
)

beacon_commit(H) is included in the Q-Block transcript (HIP-0079 clause 7) and signed by Pulsar-M-65. Subsequent randomness consumers (committee selection, leader election, on-chain RNG opcode) derive their values via TupleHash256 with consumer-specific cust strings (COMMITTEE-V1, LEADER-V1, RNG-V1).

Entropy source validation (SP 800-90B)

entropy_in is only as good as the source behind it, so the QRNG is validated continuously per SP 800-90B rather than sampled and trusted. Two online health tests run on every sample, permanently.

Repetition count detects a stuck source. It tracks the longest run of identical consecutive samples and alarms when the run exceeds

C = 1 + ceil(-log2(alpha) / H_min)

where alpha is the false-positive probability (2^-20) and H_min is the assessed min-entropy per sample.

Adaptive proportion detects a biased source. Over a sliding window of W samples (512 or 1024) it counts occurrences of the most recent sample value and alarms when that count exceeds the cutoff for the claimed H_min.

At startup, and after any device reconnect, a source MUST pass 1,024 consecutive samples through both tests before one bit of its output reaches the DRBG. On failure the source is quarantined immediately, the failure is counted and alerted, and instantiation and reseed draw from the remaining healthy sources.

A quarantined source MUST NOT be replaced by a classical PRNG. If every quantum source is quarantined, instantiation and reseed fail and the beacon stalls. A stalled beacon is a detected liveness fault; a silently classical one is an undetected soundness fault, and under strict-PQ the second is not a degraded mode of the first.

Conditioning

Raw quantum bits are near-uniform, not uniform: dark counts, intensity fluctuation and digitization each leave bias. Entropy is conditioned before it becomes entropy_in, and the conditioner MUST be a strong extractor rather than a hash of convenience.

Raw quantum bits
    |
    v
Von Neumann debiasing (optional pre-filter)
    |
    v
SP 800-90B health tests (continuous)
    |
    v
Toeplitz hashing (primary extractor)
    |
    v
entropy_in -> instantiation / reseed

Toeplitz hashing is the primary extractor. It is a strong extractor by the Leftover Hash Lemma, needs only a short seed — the first row of the matrix, fixed per device and stored with it — to process arbitrarily long input, and costs O(n log n) via FFT. Output length follows the entropy deficit:

m = n * H_min - 2*log2(1/epsilon)

for n raw input bits, min-entropy H_min per bit, and statistical distance epsilon from uniform.

Von Neumann debiasing — emit the first bit of a differing pair, discard equal pairs — removes first-order bias only, never higher-order correlation. It is a pre-filter, or a fallback where Toeplitz extraction is infeasible, and never the extractor on its own.

Because instantiation and each reseed consume ≥ 384 conditioned bits, the raw draw per reseed is (384 + 2*log2(1/epsilon)) / H_min bits. The extraction ratio, not the raw sample rate, is what the epoch cadence must be budgeted against.

Backwards compatibility

None. Strict-PQ refuses ECVRF-Ed25519 (LP-131) at the consensus boundary. The classical VRF lives only on permissive profiles. Existing contracts using block.difficulty / RANDAO-style opcodes read from the PQ beacon directly under strict-PQ.

Reference implementation

luxfi/consensus/protocol/auth/beacon.go (auth-pq-surface). QRNG source binding: luxfi/qrng adapter. KAT vectors: luxfi/consensus/protocol/auth/testdata/hash_drbg_v1.json. The generator passes the NIST CAVP DRBGVS test vectors for Hash-DRBG / SHA-3 family.

Security considerations

Hash-DRBG provides backtracking resistance via the additive V + C + counter update; an attacker who observes the current state cannot recover prior outputs without inverting SHA3-384. Forward-prediction resistance is provided by periodic reseed (every epoch or 2^48 generates). Pulsar-M committee threshold over QRNG contributions prevents single-validator bias; a Byzantine subset below threshold cannot influence the beacon. Beacon output is bound into Q-Block transcripts, so post-finality tampering is impossible without invalidating Pulsar-M-65 finality.

References

  • NIST SP 800-90A Rev. 1 — DRBG constructions.
  • NIST SP 800-90B — entropy sources.
  • NIST FIPS 202 + SP 800-185 — SHA-3 family.
  • HIP-0079, HIP-0084 — Q-Chain transcript and Pulsar-M.
  • LP-131 — ECVRF (classical, explicitly NOT used under strict-PQ).
  • luxfi/consensus/protocol/auth/beacon.go.

CC0.