Skip to Content
ArchitectureVerification Model

Verification Model

A clear breakdown of every piece of data Solidarity actually verifies, the mechanism used, and what is not verified.


Trust Levels at a Glance

LevelBadgeSourceVerified by
L3 Government🟢Passport NFC chipCSCA signature chain + ZK proof (mopro)
L2 Institution🔵Institution-issued VC (v2 roadmap)VC JWT signature + JWK trust anchor
L1 Self-issuedSelf-filled card / Graph credentialECDSA P-256 sender signature (no third-party)

What Is Verified Today

Passport Identity (L3)

What is verified:

  • Active Authentication / BAC/PACE handshake (NFC chip is genuine)
  • SOD integrity: Document Signer Certificate signature over data groups
  • CSCA chain: SOD’s Document Signer Certificate traces back to a trusted CSCA root
  • Passport expiry: expiryDate extracted from DG1 MRZ; VC expires accordingly

What is NOT verified:

  • Online revocation of the passport (no CRL/OCSP call)
  • Whether the person holding the device is the passport holder (biometric comparison not implemented)
  • Liveness of the NFC chip against a reference database

Code: solidarity/Services/Identity/PassportPipelineService.swift, solidarity/Services/Identity/IssuerTrustAnchorStore.swift


ZK Proof Output (L3)

After CSCA verification passes, the Noir circuit produces a zkSNARK proof. When this proof is later presented (VP token), the verifier checks:

CheckMechanismCode
Proof structure validmopro verifier (Noir circuit)ProofVerifierService.swift
Nonce matches verifier-issued nonceJWT nonce claim comparisonOID4VPPresentationService.swift
Token not expiredJWT exp — 45 second validity windowProofVerifierService+VPToken.swift
aud matches verifier domainJWT aud claimProofVerifierService+VPToken.swift
No replayNonce consumed after first useNonceStore.swift

The 45-second VP token window means the proof must be freshly generated for each presentation — no stockpiling old proofs.


P2P Contact Card (L1)

During face-to-face exchange, the received payload is verified before saving:

// solidarity/Services/Sharing/ProximityManager+SessionDelegate.swift // Step 1: Verify ECDSA P-256 payload signature verify(payloadSignature, over: canonical(cardFields, senderDID, timestamp), using: senderDID.publicKey) // Step 2: If issuerProof present → verify Semaphore proof if let issuerProof = payload.issuerProof { verify(issuerProof, root: payload.groupRoot, signal: payload.signal, scope: payload.scope) } // Step 3: If sdProof present → verify field commitments and signature if let sdProof = payload.sdProof { verify(sdProof.signature, over: sdProof.canonicalPayload) // Verify each committed field: SHA256(committed_value) == commitment_hash }

Code: solidarity/Services/Sharing/ProximityManager+SessionDelegate.swift

What this confirms: the sender controls the private key corresponding to their DID. It does not confirm that the name/email/phone values are true.


Semaphore Group Membership (L2 Peer Group)

When a payload includes a Semaphore issuer proof, the verifier checks:

CheckValue
Merkle root matches expected group rootgroupRoot == expectedRoot
Signal matches application contextsignal == expectedSignal
Scope matches proof purposescope == expectedScope
Minimum group sizememberCount ≥ 2
Computed root matches provided rootRebuilds Merkle tree from commitments

Code: solidarity/Services/ZK/SemaphoreIdentityManager.swift


Institution Credentials (L2 — v2 Roadmap)

Framework exists (CredentialIssuanceService.swift, OIDCTokenService.swift) but is not yet integrated into the main flow. When complete, verification will include:

  • VC JWT signature using institution’s JWK
  • exp / iat claim checking
  • Issuer DID resolution (via issuer’s well-known endpoint)
  • Revocation status (endpoint TBD)

What Is NOT Verified

DataWhy Not
Raw name / email / phone in cardSignature proves sender identity, not data truthfulness
Device model or OSNo hardware attestation in current architecture
NFC chip liveness vs a revocation databaseNo online check — fully offline
Apple Wallet pass integrity on receiver sidePass QR is scanned to import, not cryptographically validated end-to-end
Ephemeral message contentDelivered over MCSession TLS only; not signed

Verification Summary

Passport NFC → CSCA chain + ZK proof = strongest guarantee (L3 Government) P2P Card → ECDSA P-256 sender signature = identity confirmed, values unverified (L1) Group membership → Semaphore ZKP = member of group without identity reveal (L2 Peer) QR code scan → syntax validation only; no signature if plain card format (L1 or unverified) VP token → nonce + exp + aud + ZK proof = replay-resistant proof presentation
Last updated on