Skip to content

Add ECVRF (RFC 9381) token support with FullKeyHash identifier#27

Merged
sweis merged 5 commits intomainfrom
claude/symmetric-key-proofs-lgsxG
Feb 26, 2026
Merged

Add ECVRF (RFC 9381) token support with FullKeyHash identifier#27
sweis merged 5 commits intomainfrom
claude/symmetric-key-proofs-lgsxG

Conversation

@sweis
Copy link
Copy Markdown
Owner

@sweis sweis commented Feb 25, 2026

Summary

This PR adds support for ECVRF (Elliptic Curve Verifiable Random Function) tokens as a new algorithm option, implementing RFC 9381 (ECVRF-RISTRETTO255-SHA512). ECVRF enables a "public verification" model where verifiers only need a key hash rather than the full key material, while the token issuer proves knowledge of the corresponding secret key through a cryptographic proof.

Key Changes

  • New Algorithm: Added Algorithm::EcVrf = 4 to support ECVRF token signing and verification
  • New Key Identifier Type: Introduced KeyIdType::FullKeyHash = 3 for full 32-byte SHA-256 hashes of key material, enabling collision-resistant key identification without embedding full public keys
  • Token Structure Updates:
    • Added proof field to SignedToken (80 bytes for ECVRF, empty for other algorithms)
    • ECVRF tokens store the VRF output (64 bytes) in the signature field and the VRF proof (80 bytes) in the proof field
  • Signing Functions (src/sign.rs):
    • generate_ecvrf_key(): Generates 32-byte secret/public key pairs
    • sign_ecvrf(): Creates ECVRF tokens with deterministic VRF proofs
    • compute_full_key_hash(): Computes full 32-byte SHA-256 hashes for key identification
  • Verification Functions (src/verify.rs):
    • verify_ecvrf(): Verifies ECVRF tokens by validating the VRF proof against the payload
    • Updated existing verifiers to reject FullKeyHash identifiers (only valid for ECVRF)
    • Updated HMAC verifier to accept only KeyHash identifiers
  • Serialization (src/serialize.rs):
    • Updated proto3 encoding/decoding to handle the new proof field (field 3 in SignedToken)
    • Added support for FullKeyHash key identifier type in payload serialization
  • Type System (src/types.rs):
    • Added EcVrf algorithm variant with correct signature length (64 bytes)
    • Added FullKeyHash key identifier variant
  • Key Management (src/keys.rs):
    • Added validation for ECVRF key sizes (32 bytes each for secret and public keys)
    • Updated key serialization/deserialization to handle ECVRF keys
  • CLI (src/main.rs):
    • Added "ecvrf" as a supported algorithm option in key generation and signing commands
  • Documentation (CLAUDE.md):
    • Updated proto3 schema documentation to reflect new algorithm and key identifier types
    • Added ECVRF to design guidelines and dependency notes
  • Research Notes (notes/research-symmetric-key-proofs.md):
    • Added comprehensive analysis of approaches considered (SNARKs, VRFs, ZK-friendly hashes, Sigma protocols)
    • Documented rationale for choosing ECVRF over SNARK-based approaches

Implementation Details

  • Uses the vrf-r255 crate (str4d/Zcash), which implements RFC 9381 with RISTRETTO255-SHA512
  • ECVRF tokens require FullKeyHash identifiers; other algorithms reject this type
  • Verification is constant-time for key matching and proof validation
  • All existing algorithms (HMAC, Ed25519, ML-DSA-44) continue to work unchanged with empty proof fields
  • Comprehensive test coverage including determinism, expiry, key mismatch, and corruption scenarios

https://claude.ai/code/session_01LJyL1uYXD1JHMq8Q3v7shM

claude and others added 5 commits February 25, 2026 23:40
Implement ECVRF-RISTRETTO255-SHA512 via the vrf-r255 crate, enabling
tokens where anyone with the public key can verify, without possessing
the secret key. This turns symmetric verification into public verification.

Key changes:
- Algorithm::EcVrf (4) with 64-byte VRF output as signature
- KeyIdentifier::FullKeyHash: 32-byte SHA-256 for full collision resistance
- New `proof` field (80 bytes) in SignedToken wire format (field 3)
- VRF signing, verification, and key generation
- CLI support: generate-key/sign/verify/inspect with --algorithm ecvrf
- 20 new tests (126 total), all passing

Research notes in notes/research-symmetric-key-proofs.md comparing
SNARKs, VRFs, Poseidon, and other approaches.

https://claude.ai/code/session_01LJyL1uYXD1JHMq8Q3v7shM
- Run cargo fmt to fix line-wrapping in serialize.rs, sign.rs, verify.rs
- Replace JSON indexing with safe as_object_mut().insert() in main.rs
  to satisfy clippy::indexing_slicing lint

https://claude.ai/code/session_01LJyL1uYXD1JHMq8Q3v7shM
Add ECVRF (RFC 9381) to supported algorithms list, CLI examples,
wire format schema, token sizes table, and security considerations.

https://claude.ai/code/session_01LJyL1uYXD1JHMq8Q3v7shM
Replace `panic!()` with `assert!(matches!(...))` in the
test_ecvrf_uses_full_key_hash test to satisfy the clippy::panic
lint which CI promotes to an error via -D warnings.

https://claude.ai/code/session_01LJyL1uYXD1JHMq8Q3v7shM
@sweis sweis merged commit 9a5dd33 into main Feb 26, 2026
4 of 5 checks passed
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.

2 participants