An iOS example app that integrates Taiwan's Citizen Digital Certificate (TW FidO) with openac-rsa-x509-swift to generate a zero-knowledge proof from the certificate signature and send it to a server for verification.
| Download Circuits | Sign with MOICA | Generate Proof |
|---|---|---|
![]() |
![]() |
![]() |
| ~10 seconds | ~11 seconds | prove ~5 s | verify ~13 s |
Always visible. Shows download progress for the files below (shown only when not yet present); the MOICA and ZK Pipeline sections are hidden until all three are ready.
- Download Circuit — fetches and decompresses
cert_chain_rs4096_proving.key,user_sig_rs2048_proving.key(zkID releases), andg3-tree-snapshot.json.gz(moica-revocation-smt releases)
Enter your ID Number (身分證字號), then follow the steps:
- TBS — to-be-signed challenge bytes; tap the refresh button to call
POST /challengeon the server and receive achallenge_bytes - Get SP Ticket — calls
POST /fido/sp-ticketwith the ID number and TBS; returns a signedsp_ticket - Verify with MOICA — deep-links to
mobilemoica://moica.moi.gov.tw/a2a/verifySignso the MOICA app performs the signature; returns toopenac://callback - Auth Result — calls
POST /fido/ath-result, polling until the signed response and signer certificate are available - Generate Input — calls
generateCertChainRs4096Inputfromopenac-rsa-x509-swiftto build the circuit input JSON from the MOICA response, issuer certificate, TBS, and SMT snapshot
- Generate Proof — runs
proveCertChainRs4096andproveUserSigRs2048(Groth16 provers); reports time in ms - Verify — submits proofs to
POST /link-verifywith the challenge ID and cert chain type (rs4096) - Run All Steps — convenience button in the toolbar that runs prove + verify in sequence
{
"cert_chain_type": "rs4096",
"cert_chain_proof": "<base64-encoded bytes>",
"user_sig_proof": "<base64-encoded bytes>"
}Clone the repo and open it in Xcode.
git clone https://github.com/privacy-ethereum/openac-taiwan-citizen-digital-certificate-ios-exampleClone and run go-zkid-verifier, then expose it via ngrok:
# In the go-zkid-verifier directory
make download-keys
make build
make serve# In a separate terminal
ngrok http 8080ngrok will print a public URL like https://b33f-54-237-15-198.ngrok-free.app. Copy it.
Open OpenACExampleApp/ProofViewModel.swift and replace the two URL constants near the top of the file with your ngrok URL:
private let serverURL = URL(string: "https://<your-subdomain>.ngrok-free.app/challenge")!
private let linkVerifyURL = URL(string: "https://<your-subdomain>.ngrok-free.app/link-verify")!The app requires TW FidO SP service credentials. Apply for these as an SP (Service Provider) at https://fido.moi.gov.tw/pt/, then create or update the file below before building (it is git-ignored):
OpenACExampleApp/Secrets.swift
enum Secrets {
static let fidoSpServiceID = "your-sp-service-id"
static let fidoAESKey = "your-32-byte-aes-key-base64"
}| Constant | Description |
|---|---|
fidoSpServiceID |
SP service ID issued by MOICA for TW FidO |
fidoAESKey |
32-byte AES-256 key (base64-encoded) used to compute sp_checksum via AES-256-GCM |
Credentials can also be supplied at test time via environment variables FIDO_SP_SERVICE_ID and FIDO_AES_KEY; the app falls back to Secrets.swift if those are absent.
- Open
OpenACExampleApp.xcodeprojin Xcode (open . -a Xcode). - Select a physical iPhone and ensure the TW FidO app (行動自然人憑證) is installed.
- Build and run.
- On first launch, tap Download Circuit in the Setup section and wait for all three files to download.
- Tap the refresh button next to TBS to fetch a challenge from the server.
- Enter your ID number (身分證字號), then follow the TW FidO / MOICA steps in order.
- Tap Run All Steps (or individual play buttons) to generate and verify the ZK proofs.
- iOS 16+
- Xcode 15+
- MOICA app installed on device for the authentication flow
- A running server exposing
/challengeand/link-verifyendpoints
- openac-rsa-x509-swift — Swift bindings for
proveCertChainRs4096,proveUserSigRs2048,verifyCertChainRs4096,verifyUserSigRs2048,generateCertChainRs4096Input - CryptoKit (system) — AES-256-GCM for the sp_checksum required by the TW FidO API
- zlib (system) — decompresses
.gzkey files on-device
- openac-rsa-x509-swift — API, installation, and prebuilt binaries
- zkID releases — circuit and key files
- moica-revocation-smt — SMT snapshot releases
It is currently incubated by PSE.
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.


