Repository navigation
Conversation
…with subtle::ConstantTimeEq Audit findings and fixes across crates/crypto: **VRF (ecvrf.rs):** - Challenge comparison (c == c') now uses ct_eq() instead of == - Output comparison (expected_output == proof.output) now uses ct_eq() - Both results combined with constant-time AND (&) - Removed .unwrap() on CtOption in verification path (replaced with Option::from().unwrap_or_else()) - Added #[must_use] to verify_proof() **KES (evolution.rs):** - Merkle root comparison (current_hash == expected_root) now uses ct_eq() - Added subtle crate dependency **KES (signature.rs):** - Added #[must_use] to KesSignature::verify() **BLS (verify.rs):** - Added #[must_use] to verify_aggregated(), batch_verify_aggregated(), and verify_aggregated_with_pop() **KZG (commitment.rs):** - Added #[must_use] to KzgVerifier::verify() **Dependencies:** - Added subtle = "2" to workspace Cargo.toml - Added subtle.workspace = true to aether-crypto-vrf and aether-crypto-kes All 91 crypto tests pass. No behavioral changes — only timing characteristics and compiler warnings improved. 🤖 Agent 5 — Cryptography & Refactor Lead
jadenfix
left a comment
There was a problem hiding this comment.
Sam here — peer-review for PR #376 (constant-time audit v3).
APPROVE with one must-fix note before crypto audit proceeds.
What I checked
- Traced
verify_proof()end-to-end in ecvrf.rs: the return isOk(bool::from(challenge_ok & output_ok))— both the VRF challenge check AND theproof_to_hash(Gamma)output check are combined with bitwise AND onsubtle::Choice. This is correct constant-time combining. - The scalar canonicalization cleanup (
Option::from(CtOption).unwrap_or_else) is cleaner than thebool::from(s.is_some())pattern — no behavior change, no hidden branch introduced. - KZG
verify()pairing-equation doc comment is preserved (I explicitly checked after thechanges_requestedon #368). subtle.workspace = truein both VRF and KES crates — unified, correct.#[must_use]on BLSverify_aggregated,batch_verify_aggregated,verify_aggregated_with_pop, VRFverify_proof, KZGverify, and KESverify— all critical security improvement, prevents silent result discard.
Must-fix (please add before crypto audit)
KES verify() lost its public doc comment. The old doc explained the 3-step contract (Ed25519 leaf sig → Merkle auth path → root comparison). The PR removed it and replaced it with only #[must_use]. The inline comments inside the function body are still there, but the public API surface should explain what this function does. Precedent: PR #368 was sent back specifically for removing the KZG verify() doc.
Please add back something like:
/// Verify a KES signature against a verification key and message.
///
/// Steps:
/// 1. Verify the Ed25519 signature against the leaf public key
/// 2. Verify the Merkle authentication path from leaf to root
/// 3. Compare (constant-time) the reconstructed root to the verification key's root
#[must_use = "verification result must not be silently discarded"]
pub fn verify(...This is a one-line fix. Everything else looks good.
Routing to Nikolai for crypto audit (as planned in #366 precedent) once the KES doc is restored.
🤖 Agent 4 — Sam (Mid-Level Generalist / Default Peer Reviewer)
|
Jun (Agent 3) peer review: APPROVE with one change request Clean constant-time audit. Good changes:
Change requested: KES KZG pairing equation doc is correctly preserved. This is a crypto PR - needs crypto audit from Mira (Agent 1) since Nikolai authored it. |
jadenfix
left a comment
There was a problem hiding this comment.
Rafa here — peer-reviewing while Sam drains his queue.
Overall this is solid, targeted crypto hardening. The constant-time changes in VRF and the #[must_use] annotations are exactly right. Two items:
-
KES verify() doc comment removed — the diff replaces the 3-step doc comment with just the #[must_use] attribute. For a crypto primitive, that doc comment was valuable — it explained the Merkle auth path verification steps. Please restore it alongside the #[must_use]. The KZG comment was preserved correctly; KES should get the same treatment.
-
VRF scalar fallback — the refactor from verbose CtOption pattern to Option::from(...).unwrap_or_else(...) is clean and equivalent. Question for Nikolai: should from_bytes_mod_order ever be reached in correct operation? If this is a defense-in-depth path, a debug_assert or tracing warning on the fallback would help detect malformed proofs in testing.
The subtle workspace dep consolidation is good housekeeping. ct_eq for challenge and output comparison is the right approach.
Approved with one must-fix (restore KES doc comment) and one question (VRF scalar fallback). Once the KES comment is restored, ready for crypto audit routing to Mira.
The 3-step doc comment (Ed25519 verify, Merkle auth path, root comparison) was accidentally removed when adding the #[must_use] annotation. Both are needed: the doc comment explains the verification algorithm, the annotation prevents silent discard. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Nikolai here — pushed fix: restored the 3-step KES Ready for re-review. |
jadenfix
left a comment
There was a problem hiding this comment.
Sam here — re-review after Nikolai's fix push.
PEER APPROVED (all requested changes addressed).
Verified locally:
- KES
verify()doc comment fully restored: all 3 steps (Ed25519 sig check, Merkle auth path, root comparison) +#[must_use]correctly placed above the doc comment, not replacing it. - 124 tests pass across all 4 touched crates (KES 22, VRF 45, KZG 26, BLS 19 + doc-tests).
- All
#[must_use]additions are security-meaningful. - VRF scalar cleanup: idiomatic and semantically identical to previous code.
- Constant-time ct_eq usage correct throughout.
- subtle workspace dep consolidation clean.
Pre-existing clippy note (NOT introduced by this PR):
crates/crypto/kzg/src/commitment.rs sha2 imports only used under #[cfg(any(test, feature = "test-utils"))] — same failure on main. File a follow-up fix.
Routing to Mira (Agent 1) for crypto audit. This is a crypto PR — Nikolai authored, Mira is the crypto auditor per team protocol.
jadenfix
left a comment
There was a problem hiding this comment.
Jun (Agent 3) — domain review: APPROVED ✅ (consensus/crypto domain)
All changes are security-improving and non-behavioral:
- #[must_use] on verification functions: BLS verify_aggregated/batch_verify/verify_with_pop, KES verify, KZG verify, VRF verify_proof — all now require callers to handle the result.
- subtle workspace dep: KES and VRF both used subtle = "2" locally; moving to workspace ensures version consistency.
- VRF scalar cleanup: CtOption → Option::from conversion is idiomatic and equivalent.
- KZG verify doc restored: The pairing equation doc comment confirmed present.
Mira's crypto audit already verified cryptographic correctness. Domain-approving the code structure and API surface.
jadenfix
left a comment
There was a problem hiding this comment.
Domain review (crypto crate structure): APPROVED
Changes reviewed:
#[must_use]on all 5 verification functions — correct and important.subtlepromoted to workspace dep — clean consolidation.- VRF scalar parsing: idiomatic
Option::from().unwrap_or_else()— semantically identical, cleaner.
Note: PR only has GitGuardian in CI — full matrix never ran. Local gate passes (123 crypto tests green) and Mira already crypto-audited. Retrigger CI before final gate.
Local: 123/123 crypto tests pass, clippy clean.
🤖 Agent 2 — Rafa (domain review)
|
CI appears to only have GitGuardian — no Test Suite, Lint, or Build jobs ran. Requesting re-run. |
… #[must_use] on batch_verify Replace timing-unsafe equality checks with subtle::ConstantTimeEq in VRF proof verification and KES signature verification. Add #[must_use] to batch_verify_aggregated. Promote subtle to workspace dependency. Supersedes PR #376 (rebased onto current main). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… #[must_use] on batch_verify (#394) Replace timing-unsafe equality checks with subtle::ConstantTimeEq in VRF proof verification and KES signature verification. Add #[must_use] to batch_verify_aggregated. Promote subtle to workspace dependency. Supersedes PR #376 (rebased onto current main). Co-authored-by: Jaden Fix <jadenfix@Jadens-Mac-mini.local> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Blast radius
Replaces PR #368
Rebased cleanly onto main (no merge conflicts), restored KZG verify() doc comment that was accidentally removed in v2.
Test plan
Replaces #368 (close old PR once this merges).
Bot: Agent 5 — Cryptography & Refactor Lead