Skip to content

Implement Falcon-512 verifier: hint + direct variants, on-chain BLAKE2s hash-to-point#2

Merged
ericnordelo merged 1 commit into
mainfrom
feat/falcon-512-blake2s
Jul 3, 2026
Merged

Implement Falcon-512 verifier: hint + direct variants, on-chain BLAKE2s hash-to-point#2
ericnordelo merged 1 commit into
mainfrom
feat/falcon-512-blake2s

Conversation

@0xAdriaTorralba

Copy link
Copy Markdown
Collaborator

Replaces the falcon_512 stub with a real, working Falcon-512 (FN-DSA) verifier — in two registered variants — with the message hashed to a point on-chain via BLAKE2s.

Builds directly on the findings of #1 (direct-NTT measurement, honest over-budget reporting): the key change here is storing the public key in the NTT domain, which removes the NTT(h) transform that put the direct method over budget there, plus an on-chain hash-to-point so the signature is bound to message_hash.

What

Two schemes in schemes.json, sharing one crate, one 29-felt NTT-domain public key, and one fixture:

Scheme Verify Signature L2 gas Steps Fits caps
falcon_512 (hint) 2 forward NTTs check signer-supplied mul_hint = s1*h 60 felts 76,248,400 668,947 yes
falcon_512_direct s1*h = INTT(NTT(s1) ∘ h_ntt), no hint 31 felts 76,153,420 667,762 yes

The variants cost the same (each needs exactly two 512-point transforms with an NTT-domain key), so the direct variant dominates: half the signature calldata and no signer-supplied hint in the trust surface.

  • hash_to_point (src/hash_to_point.cairo): the spec's rejection sampling with the XOF instantiated as BLAKE2s in counter mode (core::blake builtin) instead of SHAKE-256 — NON-standard, labeled as such everywhere; the profiler shows it is cost-noise next to the NTTs (~80% of steps). Computed on-chain so verify actually uses message_hash (an off-chain msg_point carried in the signature admits (s1, msg_point = s1*h + small) forgeries for arbitrary messages — reasoning recorded in PORTING.md).
  • Looped NTT (src/ntt.cairo, src/ntt_constants.cairo, src/zq.cairo): ported from s2morrow (StarkWare, MIT; SPDX headers preserved), ~33M gas per transform. Root tables verified from first principles by scripts/verify_ntt_constants.py (inverse pairing, root-chain, bijection, and an exact cross-check against tprest/falcon.py that pins the interop convention).
  • Validating unpack (src/packing.cairo): s2morrow's base-Q layout with the canonical-encoding check the reference lacked — accepted felts are in bijection with coefficient vectors in [0, Q)^512.

Correctness gate

  • scripts/gen_falcon_fixture.py generates a genuine signature (tprest/falcon.py NTRU keygen + ffSampling sampler, BLAKE2s hash-to-point, norm 27,616,781 vs bound 34,034,726) and re-checks the full verification equation independently in Python before emitting src/bench_fixture.cairo.
  • bench_verify_falcon_512 / bench_verify_falcon_512_direct accept it; tampered s1 (canonical swap and non-canonical encoding), hint, salt, public key, message, and input lengths are all rejected in tests.
  • Cairo hash-to-point is pinned to the Python construction by known-answer tests.
  • 49 tests pass workspace-wide; make all regenerates results/ (committed).

Caveats

  • The BLAKE2s XOF swap breaks FIPS-206 interoperability: signers must hash with the same construction (the fixture script is the reference). Implement Falcon-512 verifier (direct-NTT, validated by a real fixture) #1's standard-SHAKE fixture keeps real-world interop instead, at the cost of the off-chain msg_point binding issue above.
  • Bare-verify numbers only; the __validate__ scenario (account mock in bench_targets) is future work, as is NTT optimization (~80% of cost).

🤖 Generated with Claude Code

…oint)

Replaces the falcon_512 stub with two working, measured Falcon-512 (FN-DSA)
verifiers sharing an NTT-domain public key and an on-chain BLAKE2s
hash-to-point: hint-based (2 forward NTTs, 60-felt signature) and direct
(INTT(NTT(s1) . h_ntt), 31-felt signature, no hint). Both fit the Starknet
validation caps at ~76.2M L2 gas / ~669k steps.

Validated by a genuine falcon.py-signed fixture (accepted) plus tamper
rejection tests; NTT root tables verified from first principles against
tprest/falcon.py. Packed inputs are validated canonical on unpack.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 3, 2026 09:35

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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.

3 participants