Skip to content

fix: use CSPRNG for Proof-of-Iron nonces#5099

Merged
Scottcjn merged 1 commit into
Scottcjn:mainfrom
galpetame:codex-fix-proof-of-iron-csprng-5040
May 14, 2026
Merged

fix: use CSPRNG for Proof-of-Iron nonces#5099
Scottcjn merged 1 commit into
Scottcjn:mainfrom
galpetame:codex-fix-proof-of-iron-csprng-5040

Conversation

@galpetame
Copy link
Copy Markdown

Fixes #5040.

What changed

  • Replaced np.random.random() entropy in Proof-of-Iron challenge ID generation with secrets.token_hex(16).
  • Replaced nonce generation with secrets.token_hex(8) so the existing 16-hex-character nonce contract is preserved while using CSPRNG entropy.
  • Added regressions proving challenge IDs/nonces no longer call NumPy's Mersenne Twister path and that nonce generation comes from secrets.token_hex(8).

Validation

  • PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python -m pytest issue2307_boot_chime\tests\test_boot_chime.py::TestProofOfIron -q -> 12 passed
  • python -m py_compile issue2307_boot_chime\src\proof_of_iron.py issue2307_boot_chime\tests\test_boot_chime.py -> passed
  • git diff --check origin/main...HEAD -- issue2307_boot_chime\src\proof_of_iron.py issue2307_boot_chime\tests\test_boot_chime.py -> passed
  • python tools\bcos_spdx_check.py --base-ref origin/main -> BCOS SPDX check: OK

Duplicate / scope check

@galpetame
RTC wallet address: RTCe4fbe4c9085b8b2ed3f1228504de66799025f6ce

@github-actions github-actions Bot added size/S PR: 11-50 lines BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) and removed size/S PR: 11-50 lines labels May 13, 2026
@508704820
Copy link
Copy Markdown
Contributor

Code Review: Use CSPRNG for Proof-of-Iron nonces

Summary

Fixes #5040 (our bug report) -- replaces numpy.random with secrets for nonce generation in proof_of_iron.py.

This is the same class of PRNG vulnerability we found across multiple modules (#4607, #4886, #4887, #4962, #5040, #5080).

LGTM -- critical security fix.

**Review quality: Security-focused review (CWE-331)

Copy link
Copy Markdown
Contributor

@jaxint jaxint left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for contributing. Approved.

Copy link
Copy Markdown
Contributor

@loganoe loganoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. I verified the ProofOfIron challenge ID and nonce entropy paths no longer call NumPy PRNG for these security-sensitive values: challenge IDs include secrets.token_hex(16) entropy and nonces are produced directly with secrets.token_hex(8), preserving the existing 16-hex-character nonce contract. The added regressions cover both the no-NumPy path and direct token_hex usage.

Validation run:

  • PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 timeout 180 uv run --no-project --with pytest --with numpy python -m pytest issue2307_boot_chime/tests/test_boot_chime.py::TestProofOfIron -q -> 12 passed
  • python3 -m py_compile issue2307_boot_chime/src/proof_of_iron.py issue2307_boot_chime/tests/test_boot_chime.py -> passed
  • python3 tools/bcos_spdx_check.py --base-ref origin/main -> BCOS SPDX check OK
  • git diff --check origin/main...HEAD -- issue2307_boot_chime/src/proof_of_iron.py issue2307_boot_chime/tests/test_boot_chime.py -> clean

Copy link
Copy Markdown

@8npyvz5bd8-lang 8npyvz5bd8-lang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the Proof-of-Iron nonce/challenge entropy change.

The patch removes the use of NumPy's PRNG from both challenge ID and nonce generation and switches to secrets.token_hex(...), so challenge material no longer depends on Mersenne Twister state. The regression coverage is good: one test patches np.random.random to raise if the path regresses, and another pins secrets.token_hex(8) to verify nonce output comes directly from the CSPRNG helper.

Verification I ran locally:

  • git diff --check origin/main...HEAD
  • python -m pytest issue2307_boot_chime/tests/test_boot_chime.py -q -> 32 passed

No blocking findings.

Copy link
Copy Markdown

@TJCurnutte TJCurnutte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RustChain bounty review — APPROVED

PR: #5099 — fix: use CSPRNG for Proof-of-Iron nonces
Scope: Reviewed issue2307_boot_chime/src/proof_of_iron.py, issue2307_boot_chime/tests/test_boot_chime.py; diff covers secret/token handling, regression test coverage, bugfix logic.

Local validation

  • git diff --check origin/main...HEAD — PASS
  • python3 tools/bcos_spdx_check.py --base-ref origin/main — PASS
  • python3 -B -m py_compile issue2307_boot_chime/src/proof_of_iron.py issue2307_boot_chime/tests/test_boot_chime.py — PASS
  • python3 -B -m pytest issue2307_boot_chime/tests/test_boot_chime.py -q — PASS
  • Added-line secret-pattern scan — PASS

I did not find a blocking correctness, security, or packaging issue in this focused diff. The changed files line up with the PR's stated security/bugfix scope, and the focused local gates above passed.

Boundary: this approval covers the reviewed PR diff and focused local checks; it is not a payout or production-deploy assertion.

Copy link
Copy Markdown
Contributor

@508704820 508704820 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review — #5099

1. CRITICAL — replaces numpy PRNG with CSPRNG

Old code used np.random.random() for:

  • Challenge ID generation
  • Nonce generation

numpy.random is NOT cryptographically secure — it uses Mersenne Twister, which is predictable if an observer can see enough outputs. This means:

  • Challenge IDs could be predicted
  • Nonces could be guessed
  • An attacker could pre-compute valid challenges

2. New code uses secrets module

  • secrets.token_hex(16) for challenge IDs (128 bits of entropy)
  • secrets.token_hex(8) for nonces (64 bits of entropy)
  • Both are cryptographically secure (os.urandom under the hood)

3. Why this matters

In a Proof-of-Iron system, predictable nonces allow:

  • Challenge pre-computation attacks
  • Replay attacks (if nonce space is small enough to collide)
  • Undermining the entire attestation protocol

4. Test coverage added

Tests verify the new CSPRNG generates unique values across multiple calls.

5. Removed numpy dependency for crypto

Using secrets instead of numpy for randomness is correct — numpy is for statistical/ML randomness, not cryptographic security.

— Xeophon (security review)

Copy link
Copy Markdown
Contributor

@himanalot himanalot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. I verified the nonce generation behavior from 8e8c4c3f0e7d98043ca429b26f4acea5f4406a46 in a temporary package with stubs for missing local dependencies/NumPy.

The check confirmed _generate_challenge_id() and _generate_nonce() no longer call np.random.random, _generate_nonce() returns a 16-character value from secrets.token_hex(8), and the challenge ID path uses CSPRNG material as part of the hash input.

Copy link
Copy Markdown
Contributor

@jaxint jaxint left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review - Standard Quality ✓

Reviewed: Review submitted via GitHub API
Bounty: #73 - PR Reviews Bounty
Wallet: AhqbFaPBPLMMiaLDzA9WhQcyvv4hMxiteLhPk3NhG1iG

This PR has been reviewed as part of the RustChain bounty program. All standard review criteria met.


🤖 Automated review via RustChain RTC bounty bot

@Scottcjn Scottcjn merged commit a593fa1 into Scottcjn:main May 14, 2026
3 checks passed
Copy link
Copy Markdown

@HCIE2054 HCIE2054 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for contributing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: proof_of_iron uses numpy.random for nonce generation — predictable nonces

9 participants