ZERO-KNOWLEDGE AGE PROOF · EXPERIMENTAL

零知識證明年齡查驗

只證明「已滿 N 歲」,不揭露出生日期

皮夾在手機上證明「出生日期不晚於 截止日」(即已滿 18 歲),來源是政府卡片或有備而來自發的 MyData 國民身分證。本頁只會知道「是」或「否」,不會收到出生日期或任何欄位。

TRY THE AGE PROOF

建立一筆零知識年齡查驗

查驗方只決定「至少幾歲」;皮夾用電路證明出生日期在截止日之前,不透露實際日期。

1

選擇證明來源

兩種來源用同一套電路,但簽署出生日期的人不同,信任關係也不同。

2

年齡門檻與目的

截止日以臺北時間的今天往前推 N 年計算;目的會顯示在皮夾的同意畫面。

PRIVACY BY DESIGN

個人資料蒐集、處理及利用告知

只收到證明與是非結果

完整告知事項與個資法依據

TIMING

與 SD-JWT-VC 出示比較

同一個分頁內最近一次的兩種流程並排;紀錄只含毫秒數與來源,不含任何欄位值,關閉分頁即消失。目前來源:政府卡片(TWDIW)

查驗的證據nonce 綁定、述詞 public input、Prepare/Show 證明連結、issuer 金鑰(政府卡另查官方 DID API)
資料保存證明只在單次請求記憶體中轉送給原生後端;Worker 與 Durable Object 不保存證明,也不記錄持卡人資料
後端邊界原生後端以 Cloudflare Container 執行,只收到證明與述詞,不收到任何欄位;它只記錄是非、耗時與 nonce 的雜湊前綴

Q&A

關於這個實驗

這和首頁的「已滿 18 歲」情境有什麼不同?

首頁的成年情境是選擇性揭露:卡片本身要有已簽署的年齡述詞,或直接揭露生日再由 verifier 計算。這一頁是零知識證明:皮夾用電路證明「隱藏的出生日期不晚於截止日」,verifier 只拿到證明與是非。

自發身分證的結果算政府背書嗎?

不算。MyData 自發身分證由持卡人以自然人憑證派生的每卡金鑰簽署,證明只說明「持卡人自己簽署的出生日期」符合述詞。結果頁會標示為自發、非政府背書。

為什麼要等幾秒,而且還需要另一個後端?

手機要為 ES256 簽章與日期比較各建一個證明並互相連結。第一次約 8 到 12 秒;之後同一張卡重用 Prepare 的預運算,只重新遮罩再跑較便宜的 Show 電路,約 3 秒。驗證端需要 Prepare 電路 432 MB 的 verifying key,超出 Cloudflare Worker 的 128 MiB 限制,因此由 Rust 原生服務載入金鑰驗證。這個服務以 Cloudflare Container 執行,目前規格 1/4 vCPU,實測驗證約 5 秒,容器剛從休眠喚醒時較久。

重用 Prepare 預運算,會讓兩次出示被關聯嗎?

不會。每次出示都重新產生隨機遮罩並重新遮罩兩個證明,查驗方收到的證明物件因此互不相同。被重用的是手機端的機密中間狀態,不是送出去的證明。那份中間狀態含裝置金鑰與出生日期,以憑證同等的保護存在手機上,刪卡或清除本機資料時一併移除。

驗證方會拿到什麼?

兩個證明物件、發卡者 did:key、述詞 metadata 與是非結果。沒有出生日期、姓名、統一編號或其他欄位;本頁也不顯示 did:key。