mirror of
https://github.com/PR0M3TH3AN/bitlogin.git
synced 2026-10-27 08:31:21 +00:00
crypto/random.ts is the single chokepoint for every secret this codebase mints -- recovery entropy, everyday keys, vault roots, AEAD nonces, account ids, generated passphrases. It is correct today: it throws when no secure source exists rather than falling back, and rejection-samples to avoid modulo bias. Nothing in CI would have reported it if either stopped being true. That is the gap this closes. The existing suite is strong on known-answer vectors -- HKDF, ScalarExpand, Argon2id, BIP-39, Schnorr, GCM tamper detection, NIP-44 official vectors -- but every one of them is satisfied by a deterministic stream. Same input, same output. That is exactly how a predictable RNG survives a health check that only asks whether the output looks random. Adds two blocks, nine tests: - Fail-closed: no crypto object, crypto without getRandomValues, and getRandomValues present but not callable must each throw, and randomEntropy128 / generatePrivateKey / randomUniformInt must abort rather than substitute a value. Plus a check that normal operation resumes once a source is available again, so the guard cannot be satisfied by breaking everything permanently. - Uniformity: chi-square over 200k draws at modulus 94, full-range coverage at the EFF wordlist modulus of 7776, rejection of invalid bounds, and the degenerate modulus of 1. Both mutation-verified rather than assumed. Replacing the throw with a zero-filling stub turns five fail-closed tests red. Replacing rejection sampling with a bare `value % maxExclusive` gives chi-square 5614 against a threshold of 147 -- while leaving every other test in the suite green, which is the whole reason the distribution test has to exist. Tests only; no source or behaviour change. Suite 172 -> 181. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01HtNMsKzzFTPURemX7tT19u