Skip to content

fix(core): use crypto/rand for packet preambles - #1642

Draft
justin-layerv wants to merge 1 commit into
OpenNHP:mainfrom
justin-layerv:justin/upstream-crypto-rand-preamble
Draft

fix(core): use crypto/rand for packet preambles#1642
justin-layerv wants to merge 1 commit into
OpenNHP:mainfrom
justin-layerv:justin/upstream-crypto-rand-preamble

Conversation

@justin-layerv

Copy link
Copy Markdown
Contributor

What changed

  • Replaced GetRandomUint32's per-call math/rand seed with crypto/rand.
  • Preserved the existing non-zero return contract and public signature.
  • Added a regression test covering non-zero output and basic source variation.

Why

GetRandomUint32 is an exported helper used for packet header preambles. Its previous implementation seeded a new pseudo-random generator from time.Now().UnixNano on every call, which could collide under closely timed calls and left a weak-random API available for future nonce or identifier use.

The header preamble itself is transmitted in cleartext, so this is not claiming new confidentiality. It removes the per-call seed collision and makes the exported default safe for security-sensitive future callers. This ports the generally applicable core of layervai/nhp#2333 to current OpenNHP.

Validation

  • go test -race -count=1 ./... in nhp
  • go test -race -count=1 ./ac ./agent ./db in endpoints
  • race-enabled server test-binary compilation
  • go vet ./... in both Go modules

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Looks Good - Code looks good

Clean, well-scoped port that swaps the per-call math/rand seed for crypto/rand. I reviewed correctness, the import change, the callers, and the test.

Verified

  • Import cleanup is safemath/rand was only referenced by the replaced line; time is still used elsewhere (utils.go:59), so keeping it is correct.
  • Contract preserved — public signature stays GetRandomUint32() uint32, and the rejection loop keeps the non-zero guarantee. Both callers (nhp/core/scheme/curve/header.go:40, nhp/core/scheme/gmsm/header.go:40) use the value as an XOR mask, so behavior is unchanged.
  • Correct rejection sampling — uniform over [1, 2³²-1]; binary.BigEndian.Uint32 reading of 4 fresh bytes each iteration is right, and the retry-on-zero avoids reusing a partially consumed buffer.
  • Test is not flaky — 1000 draws from a 2³² space give ~1.16e-4 probability of any collision; the test tolerates one collision (fails only on ≥2, P ≈ 7e-9). Good balance between flake-safety and detecting a stuck/low-entropy source. The zero-check also guards the contract.

Minor suggestions (non-blocking)

  • Panic on rand.Read error: previously this function could never fail; it now panics if the system CSPRNG errors. This is standard Go practice and such failures are essentially catastrophic anyway, so it's acceptable — just noting the behavior change. Callers running under utils.CatchPanic() will recover; a call outside a recovered goroutine would crash the daemon.
  • Per-packet cost: crypto/rand.Read is now invoked once per header write. On Linux this is the buffered getrandom path and is fast, so no practical concern — flagging only for awareness on high-throughput paths.

Nice improvement: removes the closely-timed-seed collision risk and makes the exported helper safe for future security-sensitive callers.

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.66667% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
nhp/utils/utils.go 66.66% 1 Missing and 1 partial ⚠️

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1642      +/-   ##
==========================================
- Coverage   12.54%   12.52%   -0.02%     
==========================================
  Files          96       96              
  Lines       14526    14526              
==========================================
- Hits         1822     1820       -2     
  Misses      12526    12526              
- Partials      178      180       +2     
Flag Coverage Δ
unittests 12.52% <66.66%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
nhp/utils/utils.go 23.86% <66.66%> (-2.28%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant