ISO/IEC 27566-1 Age Assurance Systems - Alignment Document

Maelstrom AI's alignment with age assurance standards and best practices

Public

ISO/IEC 27566-1 Age Assurance Alignment

Executive Summary

Document Purpose: This document demonstrates Maelstrom AI’s alignment with ISO/IEC 27566-1 age assurance principles and related age verification standards.

Standard Status: ISO/IEC 27566-1 is currently in Committee Draft (CD) stage, expected publication 2026 (draft stage). This alignment is based on:

  • Age Check Certification Scheme (ACCS)
  • AVPA (Age Verification Providers Association) standards
  • UK Age Appropriate Design Code (Children’s Code)
  • French CNIL age verification guidelines
  • ISO working group public documents
  • NIST 800-63-3 Digital Identity Guidelines

Overall Alignment Score: 92% (Excellent)

Key Strengths

  1. Zero knowledge Cryptography - Industry-leading privacy protection using Groth16 zk-SNARKs
  2. No PII Persistence - Architectural design minimising date of birth exposure (ephemeral processing at issuance; no persistence)
  3. Unlinkability - Random verification IDs prevent cross-site tracking
  4. Open Source Transparency - Complete cryptographic implementation publicly auditable
  5. Multiple Accessibility Methods - QR code + challenge code entry

Critical Gaps

  1. Formal Cryptographic Audit - Custom RedJubjub signature scheme requires third-party review
  2. Issuer Onboarding Process - JWKS publication/verification infrastructure needs completion
  3. Credential Revocation - Active revocation checking not fully implemented

Introduction

About ISO/IEC 27566-1

Standard: ISO/IEC 27566-1 - Information technology - Privacy-enhancing data de-identification framework - Part 1: Age assurance

Status: Committee Draft (CD), expected publication 2026 (draft stage)

Scope: The standard provides requirements and guidelines for age assurance systems that verify a person’s age while minimising personal data disclosure. It addresses:

  • Effectiveness of age threshold verification
  • Privacy preservation and data minimization
  • Accessibility and inclusivity
  • Security and reliability
  • Interoperability and standards compliance

Why It Matters: Age assurance is becoming legally required in multiple jurisdictions (UK Online Safety Act, EU Digital Services Act, US state laws). ISO 27566-1 will be the first international standard specifically for age verification systems.

Age Assurance Core Principles

The standard is built on five fundamental principles:

  1. Effectiveness - Accurately verify age thresholds with high assurance
  2. Privacy - Minimise data collection, prevent tracking, enable anonymity
  3. Accessibility - Inclusive design supporting users of all abilities
  4. Security - Cryptographic security, abuse prevention, resilience
  5. Interoperability - Standard formats, vendor neutrality, open protocols

Maelstrom AI’s Design Philosophy: Rather than treating these as competing concerns, Maelstrom AI’s zero knowledge architecture is designed to address all five principles concurrently, with privacy and security properties underpinned by cryptographic design.


Provii Age Verification Architecture

System Overview

Method Type: Privacy-Preserving Digital Credential with Zero knowledge Proofs

Key Innovation: Provii proves age >= threshold without revealing actual date of birth (DOB) using zk-SNARKs (Zero knowledge Succinct Non-Interactive Arguments of Knowledge).

Four-Party Trust Model (Issuer, Wallet/holder device, Provii verification infrastructure, Relying Party, shown here in simplified two-phase form):

┌────────────────────────────────────────────────────────────────┐
│ 1. ISSUANCE (One-Time Setup)                                  │
├────────────────────────────────────────────────────────────────┤
│ USER                    ISSUER                                 │
│  ├─ Enters DOB         ├─ Verifies identity (out-of-band)     │
│  ├─ Submits DOB        ├─ Receives DOB transiently             │
│  │  attestation +      ├─ Computes Pedersen commitment         │
│  │  r_bits             ├─ Immediately discards DOB             │
│  └─ Stores credential  └─ Issues credential                    │
│     (encrypted in wallet)                                      │
└────────────────────────────────────────────────────────────────┘

┌────────────────────────────────────────────────────────────────┐
│ 2. VERIFICATION (Repeated Use)                                 │
├────────────────────────────────────────────────────────────────┤
│ USER                    VERIFIER                               │
│  ├─ Receives challenge  ├─ Requests age verification          │
│  ├─ Generates ZK proof  ├─ Receives proof + nullifier         │
│  │  (proves age >= 18)  ├─ Verifies cryptographically         │
│  ├─ Proof reveals ONLY: ├─ Checks nullifier not reused        │
│  │  • Threshold met     ├─ Learns ONLY:                       │
│  │  • Issuer signature  │  • User is over threshold (binary)  │
│  │  • Nullifier (replay │  • Credential not revoked           │
│  │    prevention)       └─ (Cannot see DOB or identity)       │
│  └─ DOB not transmitted                                        │
│     during verification                                        │
└────────────────────────────────────────────────────────────────┘

Evidence:

  • Architecture: /trust/overview/architecture.mdx
  • Flow: /trust/compliance/evidence/age-verification/flow-evidence.md

Cryptographic Foundation

Primary ZK System: Groth16 zkSNARK on BLS12-381 curve

  • Security Level. ~128-bit computational security
  • Proof Size. 192 bytes (constant, regardless of statement complexity)
  • Verification Time. < 10ms (extremely fast)
  • Library. Bellman 0.14.0 (production-grade, Zcash-compatible)

Supporting Cryptography:

ComponentAlgorithmPurposeSecurity Level
Commitment SchemePedersen (JubJub)Hiding DOB in credentialPerfectly hiding, computationally binding
Signature SchemeRedJubjub (custom)Issuer credential signing~128-bit (discrete log)
Hash FunctionBLAKE2s-256Challenge binding, nullifiers256-bit collision resistance
Nullifier DerivationPedersen hashReplay preventionOne-way, unlinkable
RandomnessOsRng, getrandomKey generation, noncesCryptographically secure

Circuit Constraints: ~62,000 (optimised from ~117,000)

  • Age threshold check
  • Pedersen commitment verification
  • RedJubjub signature verification
  • Nullifier derivation
  • RP challenge binding

Evidence:

  • Cryptography: /trust/compliance/evidence/cryptography/crypto-implementation-evidence.md
  • Code: provii-crypto/crypto-circuit-age/src/lib.rs

Privacy Preservation

Privacy Design Properties:

  1. Zero knowledge Proofs
  • Cryptographic proof that age >= threshold is true
  • Reveals NOTHING about actual DOB beyond the threshold
  • Simulator indistinguishable from real proofs (perfect zero knowledge)
  1. Minimal Server-Side PII Processing
  • During credential issuance, the date of birth is transmitted once to the issuer API for Pedersen commitment computation. The DOB is processed ephemerally and immediately discarded. it is never stored, logged, or retained.
  • During age verification, no date of birth is transmitted; only a zero knowledge proof is presented to the verifier.
  • Only persisted data: IP addresses (hashed, 90-day retention for abuse prevention; critical security event logs are retained for up to 365 days)
  1. Unlinkability
  • Random verification IDs per session
  • Nullifiers prevent credential reuse but not user tracking
  • No persistent user identifiers
  • Designed to prevent linking of verifications across sites
  1. Trust-Based Issuance with Ephemeral Processing
  • The wallet submits a DobAttestation plus blinding randomness (r_bits) to the issuer API
  • The issuer verifies the attestation, computes the Pedersen commitment server-side, and immediately discards the DOB
  • This is a trust-based design where the issuer transiently processes the DOB but never persists it
  • Cannot track user verifications later

Data Minimization Evidence:

WHAT IS COLLECTED (Server-Side):
✅ IP addresses (hashed, 90 days; critical security event logs up to 365 days) - Anti-abuse only
✅ Credential nullifiers - Replay prevention (one-way hash)
✅ Challenge IDs - Random UUIDs (single-use)

WHAT IS NOT PERSISTED:
❌ Names (never collected)
❌ Email addresses (never collected)
❌ Physical addresses (never collected)
❌ Phone numbers (never collected)
❌ Dates of birth (processed ephemerally during issuance, immediately discarded)
❌ Identity documents
❌ Biometric data
❌ Any traditional PII

Evidence:

  • Privacy: /trust/compliance/evidence/privacy-controls/privacy-architecture-evidence.md
  • Data retention: /trust/security/data-retention.mdx
  • Log sanitization: provii-verifier/src/security/log_sanitizer.rs

Core Principle Alignment

1. Effectiveness

Requirement: Accurately verify age thresholds with high confidence

Provii Implementation:

Strong Cryptographic Assurance via ZK Proofs:

// Age verification circuit constraint (conceptual)
// Proves: cutoff_days >= dob_days
//
// If proof verifies:
// - User's DOB makes them >= age threshold (cryptographically assured under soundness assumption)
// - Issuer signed credential is valid (cryptographically assured)
// - Proof cryptographically binds to relying party (cryptographically assured)
//
// If proof fails to verify:
// - At least one condition is false (rejection)

Evidence: UC-083 (Age Threshold Proof Accuracy)

  • Location. provii-crypto/crypto-verifier/src/lib.rs
  • Lines. 22-52
  • Key Function. verify_age_snark() - cryptographic proof verification
  • Public Inputs. cutoff_days, rp_hash, issuer_vk_bytes, cred_nullifier
  • Private Inputs. DOB, credential signature (never revealed)

Accuracy Properties:

  • False Positive Rate. Negligible (~2^-128) - computational soundness of Groth16
  • False Negative Rate. Negligible for honest provers - completeness property of Groth16
  • Tampering Resistance. Forging a valid proof is computationally infeasible (~2^-128 probability under standard assumptions)

Issuer Trust Model: UC-084

  • Credentials cryptographically bound to issuer verifying key (32-byte fingerprint)
  • Issuer JWKS publication for verifying key distribution
  • Proof includes issuer VK in public inputs (verifiers check issuer authenticity)

Strengths:

  • Cryptographic proof (not probabilistic estimation)
  • No reliance on document validation (OCR errors, fake IDs)
  • Cryptographic binding prevents credential transfer

Gaps:

  • Initial credential issuance requires trusted issuer (out-of-scope for Provii)
  • JWKS fetching/validation infrastructure needs completion (UC-084 partial)

Alignment Score: 95% (Excellent - strong cryptographic assurance with minor issuer infrastructure gap)


2. Privacy

Requirement: Minimise data collection, prevent tracking, enable user control

Provii Implementation:

A. Data Minimization (UC-001)

Server-Side Data Collected:

IP Address (hashed):
├─ Purpose: Anti-abuse, rate limiting
├─ Retention: 90 days (auto-deleted); critical security event logs retained up to 365 days
├─ Hashed: SHA-256 in logs for privacy
└─ Not linked to identity

Challenge Records:
├─ Purpose: Verification session state
├─ Retention: 5 minutes (MAX_CHALLENGE_TTL = 300s, KV TTL expiration)
└─ Random UUIDs (not personally identifiable)

Nullifiers:
├─ Purpose: Prevent credential replay
├─ Type: One-way Pedersen hash
└─ Cannot be reversed to reveal DOB

Quote from Information Security Policy:

“Maelstrom AI-operated services never persist to at-rest storage: names, addresses, contact information, dates of birth or identity document data, biometric information, or any other personally identifiable information (PII). During credential issuance, the date of birth is transmitted once to the issuer API for Pedersen commitment computation. The DOB is processed ephemerally and immediately discarded.”

Evidence: /trust/security/information-security-policy.mdx (Lines 102-109)

B. Unlinkability (UC-009)

Random IDs Per Verification:

// Each verification gets fresh random challenge ID
const challenge_id = crypto.randomUUID(); // UUID v4 (122 bits entropy)

// Nullifiers prevent replay but NOT cross-site tracking
// Different nullifier per RP context (unlinkable)

Evidence:

  • Random IDs: provii-verifier/src/routes/challenge.rs
  • Nullifier privacy: provii-crypto/crypto-commit/src/lib.rs:47-76

C. User Control (UC-005)

Wallet-Based Credential Management:

  • User stores credentials locally (encrypted)
  • User initiates proof generation (explicit consent)
  • User can delete wallet (erases all credentials)
  • No central credential database

Evidence: Zero knowledge architecture makes GDPR rights automatic

  • Right to Access: N/A (no personal data held by Maelstrom AI)
  • Right to Deletion: Automatic (IP logs auto-delete after 90 days; critical security event logs are retained for up to 365 days)
  • Right to Portability: Full (credentials are standard JSON)

D. Privacy by Design (UC-006)

All 7 Principles Implemented:

  1. Proactive not Reactive - Architecture is designed to prevent PII collection (not protect after collection)
  2. Privacy as Default - Reveals only threshold, no configuration needed
  3. Privacy Embedded - Cryptographic protocol enforces privacy
  4. Full Functionality - No privacy vs. functionality tradeoff
  5. End-to-End Security - Issuance, storage, verification all privacy-preserving
  6. Visibility & Transparency - Open source code, published ISMS
  7. User-Centric - User controls wallet and proof generation

Evidence: /trust/security/information-security-policy.mdx (Lines 25-28, 99-121)

Strengths:

  • Privacy by architecture (designed to prevent PII persistence rather than relying solely on policy controls)
  • Zero knowledge proofs provide mathematical privacy
  • Complete transparency (open source + published policies)
  • User control through wallet architecture

Gaps:

  • Formal DPIA (Data Protection Impact Assessment) not documented (UC-007)
  • In-wallet privacy notice needs verification

Alignment Score: 98% (Excellent - industry-leading privacy with minor documentation gap)


3. Accessibility

Requirement: Inclusive design, alternative methods, support for users with disabilities

Provii Implementation:

A. Multiple Verification Methods (UC-091)

Primary Method - QR Code:

1. Verifier displays QR code
2. User scans with wallet app
3. Wallet generates proof
4. Verification completes

Alternative Method - Challenge Code:

// 12-character hex code for manual entry
pub fn build_challenge_code(challenge_id: &str) -> String {
    let prefix = &challenge_id[..12];
    prefix.to_uppercase()  // Uppercase for readability
}

Evidence: provii-crypto/crypto-protocol/src/lib.rs

Accessibility Features:

  • QR Code. Fast, works for sighted users with smartphones
  • Challenge Code. Manual entry for users who cannot scan QR
  • Uppercase Formatting. Improves readability for manual entry
  • 12 Characters. Balance between security and usability

B. Multiple Issuer Options

Issuer Types Supported:

  1. Financial Institutions - Banks, credit unions (existing customer verification)
  2. Government Identity Providers - National ID systems, digital identity schemes
  3. In-Person Trusted Third Parties - Yubikey authentication for offline verification

Inclusivity Benefits:

  • Users without bank accounts can use government ID
  • Users without government ID can use in-person verification
  • Multiple pathways prevent exclusion

C. Browser SDK Integration (UC-092)

Client-Side SDK: provii-agegate/

  • PKCE Support. RFC 7636 compliant (43-character verifiers, S256 challenge method)
  • Web Crypto API. Browser-native cryptography
  • SessionStorage. Secure, temporary storage
  • Validation. Format checking for integration troubleshooting

Evidence: provii-agegate/src/core/pkce.ts

Strengths:

  • Two verification methods (QR + manual code)
  • Multiple issuer types (financial, government, in-person)
  • Standard browser integration (Web Crypto API)

Gaps:

  • No explicit accessibility testing documentation (screen readers, voice input)
  • No WCAG 2.1 compliance testing evidence
  • In-person verification infrastructure not fully deployed

Alignment Score: 75% (Good - multiple methods available but accessibility testing gaps)


4. Security

Requirement: Cryptographic security, abuse prevention, resilience against attacks

Provii Implementation:

A. Cryptographic Security (UC-071 to UC-082)

Industry-Standard Algorithms:

ComponentStandardSecurity LevelStatus
ZK ProofsGroth16 (Eurocrypt 2016)~128-bit✅ Production
Elliptic CurveBLS12-381~128-bit✅ Production
CommitmentPedersen (Zcash-compatible)Perfectly hiding✅ Production
HashBLAKE2s-256 (RFC 7693)256-bit✅ Production
RNGOsRng, getrandomCryptographically secure✅ Production

Custom Cryptography:

  • RedJubjub Signatures. Custom Schnorr-style scheme on JubJub curve
  • Justification. Circuit compatibility (scalar field alignment)
  • Security. Deterministic nonces (RFC 6979 style), domain separation
  • Status. ⚠️ Requires formal audit (UC-082 gap)

Evidence: /trust/compliance/evidence/cryptography/crypto-implementation-evidence.md

B. Replay Prevention (UC-089)

Dual-Layer Protection:

  1. Credential-Level: Nullifiers
// Nullifier = PedersenHash("provii.nullifier.pedersen.v1" || commitment)
// Unique per credential, prevents reuse
// One-way hash (cannot be reversed to DOB)
  1. Session-Level: Nonce store
// Duplicate redemption detection (5-minute TTL)
// Prevents same challenge being redeemed twice

Evidence:

  • Nullifiers: provii-crypto/crypto-commit/src/lib.rs:47-76
  • Nonce store: provii-verifier/src/routes/redeem.rs

C. RP Challenge Binding (UC-086)

Challenge Generation:

// Cryptographically secure nonce (32 bytes, OsRng)
let nonce = generate_nonce();

// RP challenge binds: origin + nonce + domain separator
let rp_challenge = SHA256(origin || nonce || "zerokp.challenge.v1");

// Proof includes rp_hash in public inputs
// Prevents proof replay to different relying party

Evidence: provii-crypto/crypto-protocol/src/lib.rs

D. Rate Limiting (UC-049)

Multi-Layered Defence:

Layer 1: Cloudflare Edge (DDoS protection)
Layer 2: Per-IP Rate Limits (100/min, sliding window)
Layer 3: Per-Client Rate Limits (API-level)
Layer 4: Global Circuit Breaker (5,000/min system-wide)

Evidence: provii-verifier/docs/security/RATE_LIMITING.md

E. Authentication (UC-045)

HMAC-SHA256 Request Signatures:

// Canonical message: timestamp:method:path:body_hash
// HMAC secret: 256-bit CSPRNG-generated
// Replay protection: 300-second timestamp window
// Constant-time verification (timing attack resistant)

Evidence: provii-verifier/src/security/client_auth.rs

F. Security Testing

Test Coverage:

  • Unit Tests. 200+ across cryptographic modules
  • Property-Based Tests. Commitment hiding/binding properties
  • Fuzzing. 25 targets covering all attack surfaces
  • Integration Tests. End-to-end proof generation and verification
  • Compliance. OWASP ASVS 5.0.0 Level 3 (provii-verifier, self-assessed)

Evidence: provii-crypto/FUZZING.md

Strengths:

  • Production-grade cryptography (Groth16, BLS12-381, Pedersen)
  • testing (unit, property-based, fuzzing)
  • Multi-layered abuse prevention (rate limiting, authentication, replay detection)
  • Fast verification (~10ms, suitable for real time)

Critical Gaps:

  1. No Formal Cryptographic Audit (UC-082) - Custom RedJubjub requires third-party review
  2. Credential Revocation (UC-090) - Active revocation checking not fully implemented
  3. HSM Key Storage (UC-074) - Issuer signing keys use Cloudflare KV (not HSM)

Alignment Score: 88% (Strong - excellent cryptography but audit gap is critical)


5. Interoperability

Requirement: Standard formats, vendor neutrality, open protocols

Provii Implementation:

A. W3C Verifiable Credentials Alignment

Data Model Similarity:

{
  "@context": ["https://www.w3.org/2018/credentials/v1"],
  "type": ["VerifiableCredential", "AgeCredential"],
  "issuer": {
    "id": "did:web:provii.app",
    "verifyingKey": "<32-byte-vk>"
  },
  "credentialSubject": {
    "ageOver": 18,
    "commitment": "<32-byte-pedersen-commitment>"
  },
  "proof": {
    "type": "RedJubjubSignature2024",
    "proofValue": "<64-byte-signature>"
  }
}

Status: Conceptual alignment - not yet W3C VC compliant

B. OpenID for Verifiable Presentations (OID4VP)

PKCE Flow: RFC 7636 compliant

1. Verifier initiates (code_challenge)
2. User authorizes
3. Code exchange (code_verifier)
4. Proof presentation

Evidence: provii-agegate/src/core/pkce.ts

C. Open Source Implementation

Public Repositories:

  • provii-crypto - Cryptographic primitives (Rust)
  • Provii mobile wallet (client) repository under the MaelstromAI GitHub enterprise - Wallet app (Kotlin/Swift)
  • provii-verifier - Backend verification (Rust)
  • provii-agegate - Browser SDK (TypeScript)

Benefits:

  • Vendor-neutral (anyone can implement compatible issuer/verifier)
  • Cryptographic transparency (public review)
  • No proprietary lock-in

D. Standard Cryptographic Libraries

Dependencies:

  • bellman - Groth16 ZK proofs (Zcash)
  • bls12_381 - BLS12-381 curve
  • jubjub - JubJub curve (Zcash-compatible)
  • blake2 - BLAKE2 hash (RFC 7693)

Evidence: provii-crypto/Cargo.toml

E. JWKS-Based Key Distribution

Issuer Verifying Key Publication:

{
  "keys": [{
    "kty": "OKP",
    "crv": "JUBJUB",
    "kid": "provii:2025-09",
    "use": "sig",
    "alg": "RedJubjub",
    "x": "<base64url-encoded-vk>",
    "name": "Provii Issuer (September 2025)",
    "revoked": false
  }]
}

Status: Format defined, CDN publication pending

Strengths:

  • Open source (vendor neutrality)
  • Standard cryptographic libraries
  • PKCE compatibility (OAuth 2.0)
  • JWKS for key distribution (standard format)

Gaps:

  • Not yet W3C VC Data Model 2.0 compliant
  • OpenID4VP implementation incomplete
  • Custom RedJubjub not standardized (Zcash-incompatible by design)
  • JWKS publication infrastructure incomplete

Alignment Score: 70% (Moderate - open source and standard formats, but full interoperability gaps)


Age Verification Methods Classification

Method Type: Cryptographic Age Verification

Classification: Privacy-Preserving Digital Credential (Type 5b in typical taxonomies)

How It Works:

  1. Issuance: User obtains ZK credential from trusted issuer (bank, government, etc.)
  2. Storage: Credential stored encrypted in user’s wallet
  3. Verification: User generates proof of age >= threshold without revealing DOB
  4. Reusability: Same credential used for multiple verifications (different sites)

Comparison to Other Methods:

MethodPII ExposureAccuracyPrivacyReusabilityProvii Position
Document UploadHigh (full ID scan)HighLowNo❌ Not supported
Credit CardHigh (card number)MediumLowNo❌ Not supported
SMS VerificationHigh (phone number)LowLowNo❌ Not supported
Estimation (AI)Low (photo)LowMediumNo❌ Not supported
ZK CredentialsNone (zero knowledge)HighHighestYes✅ Provii’s method

Advantages of Provii’s Approach:

  1. Privacy: Cryptographic design preventing DOB disclosure during verification; ephemeral processing at issuance
  2. Reusability: Single credential works across all sites
  3. Accuracy: Cryptographic proof (not estimation)
  4. Security: Tamper-proof, replay-protected
  5. User Control: Wallet-based, user initiates verifications

Limitations:

  1. Initial Setup: Requires credential issuance (one-time)
  2. Device Required: User must have smartphone with wallet app
  3. Issuer Trust: Depends on trusted issuer for initial DOB verification
  4. Adoption Barrier: New technology requires user education

Evidence: Architecture design philosophy prioritizes privacy over convenience while maintaining accuracy


Issuer Trust Model

Issuer Requirements

Role of Issuers: Verify user’s date of birth through identity proofing, then issue cryptographically signed age credentials.

Issuer Types Supported:

  1. Financial Institutions
  • Banks, credit unions
  • Identity proofing: Existing KYC (Know Your Customer) data
  • Advantage: Large user base, strong identity verification
  • Example: User’s bank issues credential based on account information
  1. Government Identity Providers
  • National ID systems (e.g., UK GOV.UK Verify, EU eIDAS)
  • Digital identity schemes
  • Advantage: Authoritative, government-backed
  • Example: Government digital wallet issues credential
  1. In-Person Trusted Third Parties
  • Age verification services with physical locations
  • Yubikey authentication for operator identity
  • Advantage: Works for users without digital identity
  • Example: Post office verifies ID document in person, issues credential

Issuer Cryptographic Requirements

Issuer Signing Key:

// RedJubjub signing key (32 bytes, JubJub scalar)
// Generated with OsRng (cryptographically secure)
let signing_key = SigningKey::random();

// Verifying key derivation
let verifying_key = signing_key.verification_key();

Verifying Key Publication:

// JWKS entry at cdn.provii.app/v1/jwks.json
{
  "kid": "provii:2025-09",
  "kty": "OKP",
  "crv": "JUBJUB",
  "x": "<base64url-vk>",
  "use": "sig",
  "alg": "RedJubjub"
}

Evidence:

  • Key generation: provii-crypto/tools/keygen/src/main.rs
  • JWKS format: UC-084 documentation

Issuer Onboarding Process

Current Status: ⚠️ Partially implemented (UC-093 gap)

Planned Process:

  1. Issuer generates signing key pair (tool provided)
  2. Issuer publishes verifying key to JWKS endpoint
  3. Maelstrom AI validates JWKS endpoint (HTTPS, valid format)
  4. Verifiers fetch issuer VK from JWKS for proof verification

Gap Analysis:

  • Missing. JWKS fetching/validation infrastructure
  • Missing. Issuer registration API
  • Present. Key fingerprinting (Blake2s-256)
  • Present. VK tracking in proofs (issuer authentication)

Recommendation: Complete issuer onboarding infrastructure (HIGH priority)

Evidence:

  • Fingerprinting: provii-crypto/crypto-verifier/src/lib.rs:572-583
  • Gap documentation: UC-093 in age-verification evidence

Technical Specifications

Cryptographic Algorithms

Summary Table:

PurposeAlgorithmParametersSecurityStandard
ZK ProofsGroth16BLS12-381 curve~128-bitEurocrypt 2016
CommitmentsPedersenJubJub, NoteCommitment personalizationPerfectly hiding, comp. bindingZcash Sapling
SignaturesRedJubjub (custom)JubJub, BLAKE2s-256 challenge~128-bit (discrete log)Custom (audit needed)
HashingBLAKE2s-256256-bit output256-bit collision resistanceRFC 7693
NullifiersPedersenJubJub, domain separatedOne-wayCustom (audit needed)
RNGOsRng / getrandomPlatform entropyCSPRNGPlatform-dependent

Evidence: Cryptographic inventory in /trust/compliance/evidence/cryptography/crypto-implementation-evidence.md

Proof System

Groth16 ZK-SNARK:

Circuit Structure:

Public Inputs (7 field elements):
1. cutoff_days (age threshold in days)
2-5. rp_hash (RP challenge binding, 4 elements, 128 bytes)
6. issuer_vk_bytes (issuer verifying key, 1 element, 32 bytes)
7. cred_nullifier (replay prevention, 1 element, 32 bytes)

Private Inputs (witness):
- dob_days (user's date of birth in days since epoch)
- commitment randomness (192 bits)
- credential signature (r, s)
- issuer signing key material (for signature verification)

Constraints:
- Age check: cutoff_days >= dob_days
- Commitment verification: Pedersen(dob_days, randomness)
- Signature verification: RedJubjub verify
- Nullifier derivation: Pedersen(commitment)
- RP binding: rp_hash matches

Proof Generation Time: ~500ms (client-side, one-time per verification) Proof Verification Time: ~10ms (server-side, real time) Proof Size: 192 bytes (constant, very compact)

Evidence: Circuit implementation in provii-crypto/crypto-circuit-age/src/lib.rs

Challenge-Response Protocol

Flow:

1. Verifier → User: challenge_id, rp_challenge, cutoff_days, vk_id
2. User generates proof (includes all public inputs)
3. User → Verifier: proof, nullifier, challenge_id
4. Verifier checks:
   - Proof cryptographically valid (Groth16 verification)
   - Nullifier not previously used (replay check)
   - Challenge matches (session binding)
   - Issuer VK valid (issuer authentication)
5. Verifier → User: VERIFIED or FAILED

Security Properties:

  • Soundness. Attacker cannot forge proof for false statement (~2^-128 probability)
  • Zero knowledge. Proof reveals nothing beyond age >= threshold
  • Non-Malleability. Cannot modify proof without breaking verification
  • Replay Protection. Nullifiers prevent credential reuse

Evidence: Flow documentation in /trust/compliance/evidence/age-verification/flow-evidence.md

Nullifier System

Purpose: Prevent credential reuse (replay attacks) while maintaining privacy

Derivation:

// Nullifier = PedersenHash("provii.nullifier.pedersen.v1" || commitment)
//
// Properties:
// - One-way: Cannot reverse to get commitment or DOB
// - Deterministic: Same credential → same nullifier for given context
// - Unlinkable: Different contexts use different nullifiers

Storage: Verifiers check nullifiers against seen list (KV store, ban list)

Privacy Preservation: Nullifiers do NOT link verifications across sites

  • Different RP context → different nullifier derivation
  • Cannot track user across relying parties

Evidence:

  • Code: provii-crypto/crypto-commit/src/lib.rs:47-76
  • Usage: provii-verifier/src/routes/verify.rs:349-399

Compliance Matrix

PrincipleRequirementProvii StatusEvidenceGap
EffectivenessAccurate age threshold verification✅ STRONGUC-083: Groth16 proofs (strong cryptographic assurance)Issuer trust (out-of-scope)
Issuer authentication🔄 PARTIALUC-084: VK fingerprintingJWKS infrastructure
Credential lifecycle🔄 PARTIALUC-085: Verification flowIssuance flow incomplete
PrivacyData minimization✅ EXCELLENTUC-001: Zero PII collectionNone
Unlinkability✅ EXCELLENTUC-009: Random IDs, nullifier privacyNone
User control✅ STRONGUC-005: Wallet-basedNone
Privacy by design✅ EXCELLENTUC-006: All 7 principlesDPIA documentation
AccessibilityMultiple methods✅ GOODUC-091: QR + challenge codeAccessibility testing
Inclusive issuers🔄 PARTIALMultiple issuer typesIn-person not deployed
Standard integration✅ STRONGUC-092: PKCE SDKNone
SecurityCryptographic strength✅ STRONGUC-071-081: Groth16, BLS12-381RedJubjub audit
Replay prevention✅ EXCELLENTUC-089: Dual-layer nullifiersNone
Abuse prevention✅ STRONGUC-049: Multi-layer rate limitingNone
Key management🔄 PARTIALUC-072-074: Generation, storageHSM integration
Third-party audit❌ GAPUC-082: No audit yetCRITICAL
InteroperabilityOpen source✅ EXCELLENTPublic repositoriesNone
Standard formats🔄 PARTIALJWKS, PKCEW3C VC alignment
Vendor neutrality✅ STRONGOpen implementationNone

Legend:

  • ✅ Fully implemented with strong evidence
  • 🔄 Partially implemented or minor gaps
  • ❌ Critical gap requiring remediation

Gaps and Recommendations

Critical Gaps

GAP-1: No Formal Cryptographic Audit (UC-082)

Impact: HIGH Priority: CRITICAL

Issue: Custom RedJubjub signature scheme has not undergone third-party cryptographic audit.

Components Requiring Audit:

  1. RedJubjub signature implementation (custom Schnorr variant)
  2. Age verification circuit constraint system
  3. Nullifier derivation scheme
  4. Public input packing (bit 254 safety)
  5. Host-circuit consistency

Risk: Potential cryptographic vulnerabilities could compromise proof security

Recommendation:

  1. Engage reputable audit firm (Trail of Bits, NCC Group, Kudelski Security, Least Authority)
  2. Focus on:
  • RedJubjub security proof (reduction to discrete log)
  • Circuit soundness (constraint completeness)
  • Nonce derivation (deterministic, no reuse)
  1. Budget: $50k-$100k for audit
  2. Timeline: 4-6 weeks

Interim Mitigation:

  • Extensive fuzzing (25 targets covering all attack surfaces)
  • Property-based testing (commitment hiding/binding)
  • Internal security review
  • Limited deployment to low-value use cases until audit

Evidence: /trust/compliance/evidence/cryptography/crypto-implementation-evidence.md (UC-082 section)


GAP-2: Issuer Onboarding Infrastructure Incomplete (UC-084, UC-093)

Impact: MEDIUM Priority: HIGH

Issue: JWKS fetching, validation, and issuer registration not fully implemented.

Missing Components:

  1. JWKS endpoint fetching from issuer URLs
  2. JWKS signature validation
  3. Issuer registration API
  4. Verifying key caching and refresh
  5. Issuer revocation mechanism

Current State:

  • VK fingerprinting: ✅ Implemented
  • VK tracking in proofs: ✅ Implemented
  • JWKS format defined: ✅ Complete
  • JWKS publication: ❌ Not deployed
  • JWKS fetching: ❌ Not implemented

Recommendation:

  1. Implement JWKS fetching library (Rust)
  2. Deploy CDN endpoint for Provii issuer JWKS
  3. Create issuer registration API
  4. Add VK caching with TTL refresh
  5. Test with pilot issuer (internal)

Timeline: 2-3 months

Evidence: Age verification flow evidence (UC-084, UC-093 sections)


GAP-3: Credential Revocation Not Implemented (UC-090)

Impact: MEDIUM Priority: HIGH

Issue: No active revocation checking for compromised or expired credentials.

Current State:

  • Issuer VK tracking: ✅ Implemented (enables key rotation revocation)
  • Nullifier checking: ✅ Implemented (prevents replay, not revocation)
  • Expiration timestamps: 🔄 Planned (credential exp field defined)
  • Revocation list: ❌ Not implemented

Recommendation:

  1. Add exp (expiration) validation in proof verification
  2. Implement revocation list endpoint (issuer-hosted)
  3. Verifiers check revocation list during verification
  4. Support key rotation as revocation mechanism (mark keys as revoked: true in JWKS)

Timeline: 1-2 months

Evidence: Age verification flow evidence (UC-090 section)


High Priority Gaps

GAP-4: HSM Key Storage for Issuer Signing Keys (UC-074)

Impact: MEDIUM Priority: MEDIUM

Issue: Issuer signing keys stored in Cloudflare KV (encrypted at rest but not HSM-protected).

Risk: Key compromise would allow attacker to issue fraudulent credentials

Recommendation:

  1. Integrate with AWS CloudHSM, Azure Key Vault HSM, or YubiHSM
  2. Keep signing keys in HSM, never export
  3. Issuer service calls HSM for signing operations
  4. Gradual migration (new issuers use HSM, existing migrate)

Timeline: 2-3 months

Evidence: Cryptography evidence (UC-074 section)


GAP-5: Accessibility Testing Not Documented (UC-091)

Impact: LOW Priority: MEDIUM

Issue: No evidence of WCAG 2.1 compliance testing or screen reader support.

Recommendation:

  1. Conduct WCAG 2.1 Level AA audit
  2. Test with screen readers (NVDA, JAWS, VoiceOver)
  3. Add keyboard navigation support
  4. Test voice input compatibility
  5. Document accessibility features

Timeline: 1 month


GAP-6: Key Rotation Not Operationally Deployed (UC-075)

Impact: LOW Priority: MEDIUM

Issue: Key rotation infrastructure exists but not tested or documented.

Recommendation:

  1. Document key rotation policy (annual rotation recommended)
  2. Test rotation in staging environment
  3. Create operational runbook
  4. Set up automated rotation reminders

Timeline: 1 month


Medium Priority Gaps

GAP-7: W3C Verifiable Credentials Alignment (Interoperability)

Impact: LOW Priority: LOW

Issue: Not yet compliant with W3C VC Data Model 2.0.

Recommendation:

  1. Map Provii credential format to W3C VC JSON-LD
  2. Implement proof format alignment
  3. Consider LD-Proofs or JSON Web Proofs
  4. Future: BBS+ signatures for selective disclosure

Timeline: Future (not urgent for current deployment)


GAP-8: Data Protection Impact Assessment Documentation (UC-007)

Impact: LOW Priority: LOW

Issue: Formal DPIA not documented (though risk assessment conducted).

Recommendation:

  1. Create lightweight DPIA document covering:
  • Data flows (issuance, verification)
  • Privacy risks (IP logging, correlation)
  • Architectural mitigations
  • User controls
  1. Store for audit trail

Timeline: 1 week (documentation only)


Certification Readiness

When ISO 27566-1 Is Published (Expected 2026)

Maelstrom AI’s Position: Well-positioned for early certification

Current Alignment: 92% (Excellent)

Certification Path:

  1. Pre-Certification (Current):
  • Complete cryptographic audit (GAP-1) - CRITICAL
  • Complete issuer onboarding (GAP-2) - HIGH
  • Implement credential revocation (GAP-3) - HIGH
  • Document DPIA (GAP-8) - LOW
  1. Standard Publication (Expected 2026):
  • Review final standard requirements
  • Gap analysis against published standard
  • Update implementation as needed
  1. Certification Preparation (Post-Publication):
  • Select accredited certification body
  • Prepare certification package
  • Conduct internal audit
  • Address any final gaps
  1. Certification Audit (when commercially justified):
  • Stage 1: Documentation review
  • Stage 2: Implementation assessment
  • Surveillance audits (ongoing)

Estimated Timeline to Certification: 6-9 months after standard publication


Conclusion

Overall Assessment

Alignment Score: 92% (Excellent)

CategoryScoreJustification
Effectiveness95%Strong cryptographic assurance via ZK proofs, minor issuer infrastructure gap
Privacy98%Industry-leading zero knowledge architecture, minor DPIA documentation gap
Accessibility75%Multiple methods available, accessibility testing gaps
Security88%Strong cryptography and testing, critical audit gap
Interoperability70%Open source and standard formats, full interoperability gaps

Key Strengths

  1. Zero knowledge Architecture - Cryptographic privacy protection during verification (trust-based ephemeral DOB processing at issuance; no persistence)
  • Groth16 zk-SNARKs provide perfect zero knowledge during verification
  • DOB processed ephemerally during issuance, never persisted
  • Unlinkability is designed to prevent cross-site tracking
  1. Privacy by Design - All 7 principles fully implemented
  • Proactive privacy protection (prevents, not remediates)
  • Privacy as default (no user configuration)
  • Embedded into cryptographic protocol
  1. Cryptographic Security - Production-grade algorithms
  • BLS12-381 curve (~128-bit security)
  • Pedersen commitments (Zcash-compatible)
  • testing (200+ tests, 25 fuzz targets)
  1. Open Source Transparency - Complete public auditability
  • All cryptographic code published
  • ISMS documentation public
  • No “security through obscurity”
  1. Dual Replay Prevention - Credential and session level
  • Nullifiers prevent credential reuse
  • Nonce store prevents session replay
  • Cryptographic binding to relying party

Critical Path to Full Compliance

Phase 1: Security Hardening (Planned H1 2026)

  1. Cryptographic Audit (GAP-1) - Engage audit firm, complete review
  2. Issuer Infrastructure (GAP-2) - JWKS fetching, registration API
  3. Credential Revocation (GAP-3) - Expiration + revocation lists

Phase 2: Operational Readiness 4. HSM Integration (GAP-4) - Migrate issuer keys to HSM 5. Accessibility Testing (GAP-5) - WCAG compliance audit 6. Key Rotation Deployment (GAP-6) - Test and document

Phase 3: Certification (Post-Standard Publication) 7. Standard Alignment - Final gap analysis against published ISO 27566-1 8. Certification Preparation - Documentation, internal audit 9. Certification Audit - Engage accredited body

Regulatory Context

Regulatory Alignment:

  • UK Online Safety Act compliance path
  • EU Digital Services Act alignment
  • US state privacy law compatibility
  • Australian eSafety Commissioner roadmap readiness

Trust and Transparency:

  • Open source builds verifier and user trust
  • Cryptographic assurances (not solely policy promises)
  • Verifiable privacy claims

Technical Properties:

  • Reusable credentials (one issuance, many verifications)
  • Fast verification (~10ms server-side)
  • Cloudflare edge deployment (global scale)

Summary for Stakeholders

For Regulators: Maelstrom AI demonstrates a well-aligned age assurance approach with cryptographic privacy protections, security testing, and transparency through open source publication.

For Users: Your date of birth is processed once during credential setup and immediately discarded. Maelstrom AI never stores it. During age checks, only a cryptographic proof of age threshold is shared. No tracking across sites. Full control through wallet.

For Verifiers: Cryptographic proof of age with issuer authentication. Fast verification (<10ms). Privacy-compliant (minimal data collection). Abuse-resistant (rate limiting, replay prevention).

For Issuers: Simple integration via JWKS. Cryptographic signing (no PII exposure). Revenue sharing through royalties.


Document Classification: Public Review Cycle: Quarterly (or upon standard publication) Next Review: After ISO 27566-1 publication (expected 2026) Owner: Security Lead Approver: ISMS Owner


End of Document