Skip to content

Web ZKP verification: post the private age proof to verifier.mashbean.net/zkp and time it against SD-JWT-VC - #59

Merged
mashbean merged 14 commits into
mainfrom
feat/zkp-web-verification
Sep 5, 2026
Merged

Web ZKP verification: post the private age proof to verifier.mashbean.net/zkp and time it against SD-JWT-VC#59
mashbean merged 14 commits into
mainfrom
feat/zkp-web-verification

Conversation

@mashbean

@mashbean mashbean commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

這個 PR 做什麼

codex/711-pickup-qr 的年齡述詞零知識證明(OpenAC jwt_2k+show)與驗證矩陣自動計時併進設計系統主線,再加上網頁查驗路徑:查驗方的請求 QR 可以帶回應網址(u),手機把完成的證明包 POST 到 verifier.mashbean.net/zkp,顯示網站的判定並把網站的驗證秒數寫進計時紀錄。

  • 只接受允許清單上的 HTTPS 網站(verifier.mashbean.net;DEBUG 另加 workers.dev 別名),decode 與開 socket 前各檢查一次;證明包不含任何欄位,但含發卡者 DID(自發卡=持卡人每卡金鑰)。
  • 同意畫面明說「完成的證明會送到 」。
  • 新矩陣格 W1(政府卡)/W2(自發)對照同一網站的 SD-JWT-VC 出示 A2/G1;診斷頁新增「網頁查驗:零知識證明 vs SD-JWT-VC」;summarize-verification-runs.py 加比較表。
  • HTTPS 客戶端獨立成 AgePredicateProofWebClient.swift 並列入 OfflineVerifierTests 的網路允許清單;離線驗證器沒有改動。
  • 合併細節(xcstrings key 聯集、Use 分頁、DiscloseFields alert 不帶秒數)寫在 merge commit。

驗證

  • xcodebuild test(backupTWTests,iPhone 17 / iOS 26.5 模擬器)全綠,含新增的請求/允許清單/網站判定/矩陣格/比較測試。
  • 尚未實機端到端:需要 iPhone 14 接線裝機,並且 Worker /zkp 與原生驗證服務(twdiw-vp-verifier-lite/native/openac-age-verifier)上線。第一次真證明同時是原生服務的第一個正向向量。

對照文件

docs/zkp-web-verification-2026-09-04.md

🤖 Generated with Claude Code

mashbean and others added 14 commits September 1, 2026 13:04
Brings the age-predicate zero-knowledge proof, the verification matrix
timings and the OpenACAge native binding onto the design-system app so
the next phase (web ZKP verification) builds on one line.

Resolutions worth knowing:
- Localizable.xcstrings: key union of both sides (no key changed on both).
- UseViewController: the age-proof rows join main's 「Zero-knowledge proofs」
  section with single-tint icons instead of the retired experimental section.
- DiscloseFieldsViewController: keeps the credential-kind inference and
  correlation token; the result alert stays timing-free per design system
  §8.2 (timings live in Diagnostics), and main's delivered haptic is kept.
- ScanToPresent: main's continueOnline already carries the request timing.
- PresentCredential: empty-wallet check combines both conditions; the
  frame progress keeps the tint colour.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
CopyGuideTests.theAppNamesItselfOneWay caught the one 「本 App」 that the
verification-timing line had added before the design-system rule existed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The age-predicate zero-knowledge proof so far travelled only to an iPad
over Bluetooth. A checker's request may now carry a response URL (`u`);
the phone posts the finished package there instead, shows the website's
verdict, and keeps the website's own verification figure in its timing
record. Only allow-listed HTTPS hosts are accepted (verifier.mashbean.net,
plus the workers.dev alias in DEBUG), checked on decode and again at the
socket, because the package carries the issuer DID — for a self-issued
card, the holder's own per-card key.

The web submission is its own matrix cell (W1 government, W2 self-issued)
so the report and Diagnostics can put it beside the same website's
SD-JWT-VC presentation (A2 / G1): Diagnostics gains a 「ZKP vs SD-JWT-VC」
group and summarize-verification-runs.py a comparison table.

The HTTPS client lives in its own file named on the network allow-list;
nothing in the offline verifier changed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Two changes the wallet's zero-knowledge section needed.

The 「使用」 tab listed two ZK-proof families — the age-predicate proof
and the older MOICA holding proof — which read as a duplicate. The age
proof is the one the web verifier and this whole line are built around,
so the two MOICA rows (建立/查驗零知識證明) are removed from the menu and
the two age-proof rows are translated to 建立/查驗隱私年齡證明. The MOICA
proof code stays for now; only its menu entries and their routing go.

And the expensive half of an age proof is now cached. OpenAC is designed
for it: Prepare checks the issuer signature and commits the witness — it
depends on the card, not the verifier — so it is built once per credential
and stored, and each presentation only reblinds that state and runs the
cheap Show circuit. The paper's iPhone 17 numbers put a repeat proof near
one second instead of ten. Fresh shared blinds are still generated and
both proofs reblinded every presentation, so unlinkability across verifiers
is unchanged; the on-device self-check still runs and now also drops and
rebuilds a cached base it cannot verify.

The cached prepare_witness.bin carries the device key and birth date, so
it is stored at credential protection, excluded from backup, evicted
oldest-first, purged when its card is deleted, and removed by
LocalDataEraser.eraseEverything — a birth date must not outlive its card.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mashbean
mashbean merged commit 14981bb into main Sep 5, 2026
1 check 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.

1 participant