Security Architecture Whitepaper
Version: Draft 1.0 · Scope: the security architecture, threat model and verifiability guarantees of the zero-knowledge Turkish digital identity verification platform.
1. Summary
VerifyBlind is a verification system that proves a person holds a real, live, NFC-chip-verified identity without disclosing their identity data to any integrating partner — or to the VerifyBlind infrastructure itself.
The principle at the heart of the design is this: sensitive identity data never leaves the path between the user's device and the AWS Nitro Enclave (a hardware-isolated, verifiable compute environment). The partner receives only the minimum verification result (e.g. age: 18+, a pseudonymous code).
This document describes the cryptographic design, the hardware root of trust (Nitro attestation + PCR0 version verification), NFC identity authentication, biometric liveness checking, session/ticket security, client integrity and build verifiability.
2. Design Principles
- Data minimisation / zero-knowledge: the partner learns not "who you are", but only whether the specific verification proposition it asked is true. Identity data is never transmitted to the partner.
- Isolation: all cryptographic decryption and identity-processing steps happen only inside the Nitro Enclave. The network-facing relay service (API) cannot see or store plaintext identity data.
- Verifiability: which enclave code is running is cryptographically proven by the PCR0 measurement in the attestation document; the integrity of the client apps is tested via platform attestation.
- No retention: VerifyBlind does not persistently store raw identity/biometric data; it keeps only the identity-non-revealing records needed for auditing (see §12).
3. System Architecture
Mobile App Relay (API) Enclave (Nitro)
(Android / iOS) :5102, network-facing isolated, /dev/nsm
─────────────── ───────────── ────────────────
NFC ID read ──TLS──► routing/ decryption,
liveness (face) rate limiting, NFC verification,
encryption (on device) nonce/state (Redis), biometrics, liveness,
audit/log ticket signing (MAC)
│ │
└── PostgreSQL 15 ───────────┘
└── Redis 7 (nonce/state)
Partner Website ──► verifyblind.js widget ──► Relay (result channel)- Relay (ASP.NET 9): the only network-facing component. A bridge between mobile, partner and enclave; rate limiting, nonce/state management (Redis), audit logging and webhook delivery. It never sees plaintext identity data — the payload sent to the enclave is already encrypted on the device.
- Enclave (ASP.NET 9, ARM64/Graviton): runs inside an AWS Nitro Enclave. In production it is connected to the outside world only over vsock; its RAM is hardware-isolated from the host machine (parent EC2). All sensitive cryptography happens here.
- Data layer: PostgreSQL 15 (audit, consent, verification logs, nonce ledger) + Redis 7 (short-lived nonce/state, atomic replay protection).
- Clients: Android (
com.verifyblind.mobile) and iOS (app.verifyblind.ios) mobile apps; a browser widget for partners (verifyblind.js) and mobile/iOS SDKs.
4. Threat Model
VerifyBlind rejects the assumption that "the partner is honest and the infrastructure is secure". The principal attacker profiles it defends against:
| # | Attacker | Goal | Defence |
|---|---|---|---|
| T1 | Malicious/curious partner | Learn the user's national ID number (TCKN) | Data minimisation; TCKN never reaches the partner (§2, §12) |
| T2 | Network eavesdropper / MITM | Read data in transit | TLS + end-to-end hybrid encryption (§5) |
| T3 | Attacker who seizes the relay/parent EC2 shell | Harvest plaintext identity / forge tickets | Nitro isolation + attestation; in-enclave HMAC; attestation-bound KMS trust (§6, §8, §10) |
| T4 | Fake/cloned ID card | Pass verification with an invalid identity | Passive Authentication (CSCA+CRL+DG hash) + mandatory Active Authentication (§7) |
| T5 | Presentation attack (photo/mask/screen) | Bypass the liveness check | Passive anti-spoof + biometric match (§7) |
| T6 | Holder of a leaked/stolen ticket | Pass verification with someone else's ticket | Holder-of-key signature (§8) |
| T7 | Replay attacker | Replay a valid request | Single-use nonce + atomic Redis Lua + nonce ledger (§8) |
| T8 | Fake/modified client app | A forged flow from an emulated device | Play Integrity / App Attest (§9) |
| T9 | Supply chain / malicious enclave version | Run a backdoored enclave | PCR0 version verification + version-based revocation (§6) |
5. Cryptographic Design
5.1 Hybrid encryption (device → enclave)
The mobile app encrypts the sensitive enrolment payload (NFC data groups, selfie, etc.) on the device:
- Content: AES-256-GCM (confidentiality + integrity/AEAD).
- Key wrapping: the one-time AES key is wrapped with the enclave's public key using RSA-OAEP-SHA256 (MGF1-SHA256).
- Decryption happens only inside the enclave; the relay cannot unwrap the wrapped key.
5.2 Signing
Signatures are produced with RSA-PSS (SHA-256, MGF1-SHA256, 32-byte salt length). This is used in the holder-of-key proof (§8) and the related signature paths.
5.3 Partner result channel (browser widget)
The browser-side verifyblind.js generates a one-time (ephemeral) RSA-OAEP key pair via the Web Crypto API. Its public key is relayed to VerifyBlind through the partner backend; the result comes back encrypted with this ephemeral public key and can be opened only with the private key held in that browser session. The partner's API key never reaches the browser (it stays at the server-side "nonce" end).
6. Hardware Root of Trust: AWS Nitro Enclave + PCR0
6.1 Isolation
The enclave runs in a hardware-isolated memory region, separate from the host machine (parent EC2). The parent machine's operating system (and any attacker who seizes it) cannot read the enclave's RAM. The enclave speaks to the outside world only over a narrow vsock channel.
6.2 Attestation and PCR0 version verification
The Nitro Security Module (NSM) produces an attestation document containing measurements of the running enclave image. This document is signed by AWS Nitro hardware, and its certificate chain roots in AWS's root authority — meaning it can be cryptographically verified that the document truly came from a Nitro enclave. VerifyBlind verifies the PCR0 (enclave image measurement) value in the document against a signed list of permitted versions:
- Only known and approved enclave versions are accepted (sliding window: current + previous).
- An enclave version can be revoked per version by dropping its PCR0 from the list (T9).
7. Identity Proof: NFC + Biometrics + Liveness
7.1 NFC Passive Authentication
The ID card's data groups (DGs) and its signed security object (SOD) are verified inside the enclave:
- CSCA + CRL verification: the country signing certificate authority chain that signed the card is verified; revocation lists (CRLs) are checked. The relevant root certificates and revocation lists are embedded in the enclave.
- DG hash binding (DG1 + DG2 + DG15): the hashes of the read data groups are verified against the signed
LDSSecurityObjectin the SOD. DG2 (the face) is mandatory and is bound slot-wise against the SOD — that is, the verified face is an inseparable part of the card's signed content.
7.2 NFC Active Authentication
The card signs a challenge with its internal private key; this proves that the chip is a genuine, un-cloned physical card. In VerifyBlind this check is mandatory: if DG15 or the active signature is missing/incorrect, verification is rejected.
7.3 Biometric match
The face embedding vector extracted from the user's live selfie (an ArcFace-based face embedding model) is compared against the DG2 face on the card via cosine similarity. The real security gate is inside the enclave (the threshold is enforced on the enclave side); the threshold on the phone side is only a pre-check for user experience and, even if bypassed by an attacker, does not break security.
7.4 Passive liveness (anti-spoof)
A passive presentation-attack (anti-spoof) detection runs on the selfie inside the enclave; if the liveness probability is below the threshold, verification is rejected. This is the security gate enforced on the enclave side against presentation attacks such as photo/screen/mask.
7.5 Active liveness (motion-based challenge)
During enrolment, the mobile app asks the user for random movements (turning left/right, blinking, smiling). This is a complementary, device-side liveness layer that deters static photo/screen replay; the final security decision rests on the enclave checks in §7.3–§7.4.
8. Session / Ticket Security
After a successful enrolment, the enclave issues a signed Ticket stored on the user's device. Subsequent verifications (login) rely on this ticket. Three independent mechanisms stop the ticket from being a "bearer token":
8.1 Ticket-MAC (in-enclave HMAC) — against ticket forgery
The ticket's integrity is verified with a symmetric HMAC key held only inside the enclave. This key is encrypted with a KMS wrapping key (CMK) and stored in wrapped form; at every enclave startup it is unwrapped via an attestation-bound KMS decrypt operation — meaning only an enclave with the correct PCR0 measurement can decrypt the key. Thus the secret that verifies ticket integrity never leaves the enclave.
8.2 Holder-of-key — against stolen tickets
The owner's public key is carried inside the ticket, within the MAC scope. At login the device signs a login-specific canonical message (nonce + key fingerprint + timestamp) with the hardware-backed private counterpart of that key, using RSA-PSS/SHA-256; the enclave verifies this signature against the MAC-verified public key, within a narrow time window. Result: a leaked ticket cannot be used by anyone who does not also hold its corresponding private key (T6).
8.3 Nonce / replay protection
Every flow is bound to a single-use nonce. Spending the nonce is done as an atomic operation, so two requests racing for the same nonce (TOCTOU) are prevented. A separate nonce ledger is kept for durable auditing (T7).
9. Client Integrity: Play Integrity / App Attest
The enrolment flow carries a platform attestation that the request comes from the genuine, untampered VerifyBlind mobile app:
- Android: app and device integrity are verified via the Google Play Integrity API.
- iOS: Apple App Attest (challenge → enroll → assertion; the CBOR + X.509 chain is verified to the Apple Root CA, with an ECDSA assertion and a strictly increasing counter for replay resistance).
- Routing is done per platform (iOS → Apple App Attest, other → Play Integrity).
10. Parent Isolation and KMS Key Trust
Nitro isolates the enclave's RAM from the parent; however, the enclave obtains its AWS credentials from the parent's IMDS vsock-proxy → at the IAM level, the enclave and the parent are indistinguishable. The only distinguishing factor is attestation. KMS usage is designed to preserve security even if the parent is compromised:
- KMS connection: on the enclave↔KMS connection, the TLS certificate chain and hostname match are strictly verified. Even if the parent is seized and network traffic is redirected to the attacker, a rogue endpoint cannot present a valid KMS certificate, so the sensitive data being processed cannot be exfiltrated.
- Ticket integrity: the ticket is signed and verified with an in-enclave symmetric HMAC (signer = verifier = enclave). The wrapping key is unwrapped only via an attestation-bound decrypt operation; the production role holds only minimal, key-scoped permissions — it has no authority to sign tickets, create keys or change key policy. The pseudonymisation key for user identities stays inside KMS → even an attacker who seizes the partner database cannot reverse
user_idback to a TCKN.
11. Operational Security
- Audit logging: every verification operation is written to the audit log and event stream without revealing identity.
- Monitoring and incident response: infrastructure and administrative events are logged centrally and raise alerts on anomalies. A ready incident process exists to cut off access, rotate secrets and collect immutable evidence during a security event.
- Backup / recovery: database backups are stored encrypted and version-protected; restore is drilled regularly.
12. KVKK / Data Minimisation
- No identity data reaches the partner and none is stored by VerifyBlind.
- The partner receives only the result of the proposition it asked and, if requested, pseudonymous codes:
user_id— a TCKN-derived pseudonymous code (to recognise a returning person without storing them);nsbd_id— a biographic person bucket (stable even across card renewal);doc_id— a document-based fixed code.
- KVKK infrastructure: explicit consent records, data-subject requests (access/erasure/portability/objection/rectification), breach log, table-based retention rules, a stolen/blocked-card list.
- Outcome: because the most sensitive personal data (TCKN, ID photo) is never transmitted to the partner and never persistently stored anywhere, the partner's data-processing burden and risk surface under KVKK are markedly reduced. (Final compliance depends on the partner's processing purpose; this document is not legal advice.)
13. Verifiability
VerifyBlind's core stance is not "trust us" but "verify the math": which code the system runs can be independently tested.
- Enclave — reproducible build + attestation (the core guarantee): the enclave source code is open (
github.com/VerifyBlind/VerifyBlind-Enclave). The enclave image compiled from this source produces a deterministicPCR0fingerprint — if even a single character in the code changes, PCR0 changes entirely. An independent auditor can: (1) clone the source, compile it and note the resulting PCR0; (2) obtain the live attestation document, signed by AWS Nitro hardware, from the running system (§6); (3) compare the two PCR0s. If they match, the enclave running in production is exactly that published code. Thus the claim "VerifyBlind cannot see/store raw data" rests not on a promise but on a measurement anyone can reproduce. In addition, the enclave "seals" the fresh key it generates each session into the attestation document → a document belonging to an old/other enclave cannot be replayed. - Android — reproducible build: the released APK is shown to be bit-for-bit reproducible from the open-source commit (
github.com/VerifyBlind/VerifyBlind-Android); the binary on the device is compared against the expected hash (public verification scripts). It can also be tested via Play "code transparency" (bundletool check-transparency). - iOS — build provenance: the FairPlay encryption in App Store distribution prevents the binary from being verified by bit-for-bit reproduction from the device. Instead, the link between the version downloaded from the App Store and its release source (
github.com/VerifyBlind/VerifyBlind-iOS) can be tested with a public verification script that runs on a Mac (downloading the app with ipatool and checking its Sigstore/cosign attestation).
These mechanisms are explained step by step, in plain language for end users, on the transparency and zero-knowledge pages.
14. Glossary
- TCKN
- Turkish national identity number.
- Enclave / Nitro Enclave
- A verifiable compute environment, hardware-isolated from the host machine.
- Attestation
- A hardware-signed document containing measurements of the running code.
- PCR0
- The enclave image measurement; the cryptographic answer to "which code is running".
- NFC Passive Authentication
- Verifying the card's data against the country CA's signature.
- NFC Active Authentication
- The chip proving it is not a clone by signing a challenge with its private key.
- Holder-of-key
- The presenter of a ticket proving, by signature, that they also hold the private key bound to the ticket.
- Ticket-MAC
- Verifying ticket integrity with a symmetric HMAC known only to the enclave.
- Nonce
- A single-use random value that prevents replay.
This document is a draft and will be updated as the product evolves.