(上のアイキャッチ画像の無断転載・流用を禁止します。)
こんにちは。GMOグローバルサイン・ホールディングスCTO室で分散型IDの研究開発をしている神沼@t_kanumaです。
この記事では、あるSSIのユースケースを想定し、私(Issuer&Verifier担当)とringo(Holder担当)で開発したプロトタイプについて発信します。開発基盤にはHyperledger Indy/Ariesを使用しており、以下の記事群の内容を前提にしています。ご了承ください。
なお、このプロトタイプはSSIについて理解してもらうためのデモとして作っており、実際にユーザーの利用を想定していません。
ユースケース
保険会社に対し生命保険や医療保険に申し込みの際に、病院で受診した健康診断結果を提出するケースを想定します。
- Issuer: ABC病院
- Verifier: GMO保険会社
- Holder: GMO保険会社の生命保険に加入希望で、ABC病院で健康診断を受診済みの人
- 発行するVC: 健康診断証明書
- VC内の各Claim群: 血圧、視力、中性脂肪など
- Proof検証条件: 各Claimに対し適当な基準値を用意し、それをZKPにおける閾値とする。
なぜこのユースケースを想定したのか?
一般的にSSIに向いているユースケース
Trinsicの記事“What’s the Difference Between an NFT and a Verifiable Credential?”にてSSI(DID/VC)とNFTの対比が述べられています。それによると、NFTは個人の評判、名声を公開する形で証明することに向いているとあります。一方、SSIは個人の属性を非公開でプライバシーに配慮する形で証明することに向いているとあります。
健康診断結果の数値は、一般的に個人の属性として非公開にしたいものであり、このユースケースはまさにSSI向きであると考えます。
Issuer/Holder/Verifierが授受するメリット
以下、紙モデル、もしくは従来の集中型のDX手法と比較して、Issuer/Holder/Verifierそれぞれが授受するとメリットです。中でも重要視したのが、“HolderがZKPにより、自身の健康診断数値を明かさずに、基準値を満たすかどうかを証明できることによるプライバシーの向上”です。これはHyperledger Indy/Ariesを使うことで発生する固有のメリットで、健康診断結果を紙で提出するモデルに対し勝る点です。このVCの各Claimが数値で構成されるという点が、このユースケースを想定した大きな理由です。
Issuer
- (紙モデルと比較して)ペーパーレス、郵送不要になる。
- (従来の集中型のDX手法と比較して)Issuerの過負荷を小さくできると考える。集中型の場合、VerifierはHolderの健康診断結果をIssuerに問い合わせることになる。Verifierが増えれば増えるほどIssuerに負荷がかかる。SSIでは、IssuerはHolderにVCを1度発行するだけでよく、後のことはHolderとVerifierの間で執り行われる。
Holder
- (紙モデルと比較して)ペーパーレス
- プライバシーの向上
- (従来の集中型のDX手法と比較して)HolderはVCの提示をIssuerにトレースされない。つまり、どの保険会社に入ろうとしているのかをIssuerに知られることがなくなる。
- (紙モデルと比較して)ZKPにより、自身の健康診断数値を明かさずに、基準値を満たすかどうかを証明できる。
- (紙モデルと比較して)Selective Disclosureにより、 Verifierへの提示内容がAll or Nothingではなくなる。Verifierが要求したClaimのみを提示できるようになる。(余計な情報まで提示しない。)
- (従来の集中型のDX手法と比較して)Issuerが廃業してもHolderは引き続き手元のVCを利用することができる。
- (従来の集中型のDX手法と比較して)Holder中心のサービスが生まれる可能性を持つ。例えば、過去から現在のデータを分析して健康リスクを評価するなど。
Verifier
- (紙モデルと比較して)ペーパーレス
- (紙モデルと比較して) Holderの個人情報管理の負荷を小さくできる。ZKPを用いた証明により、Holderから健康診断結果の数値を取得しなくなり、基準値より上か下かという結果しか取得しない。
成果物とシナリオ
ここから、実際に作成したモノを動画で記載し、シナリオをなぞります。
VCオファー、要求、および発行
1. Issuerからのオファー
以下、Issuerの管理画面です。この画面は健康診断を受診済みのHolderの一覧を表示します。Issuerの担当者が各Holderの診断結果のデータ入力を終えた時点からスタートします。Issuerの担当者がHolderにVC発行のオファーを出します。
2. Holderからの発行要求と発行
Holderが端末にアプリをインストールした状態からスタートします。
HolderがIssuerから届いたオファーメールのリンクをクリックすることで、アプリが起動します。そこからバックグランドでIssuerアプリからVCが発行されます。(Issuer側でもHolder同様、人が介在することなくバックグランドでVCを発行します。このあたりの技術的な流れは後述します。)
3. 発行後のIssuer
VC発行後に、Issuerアプリは発行状態と発行日を更新します。
Proof要求、提示および検証
1. Holderからの保険加入の申請
まずHolderが、Verifier側で用意したWebフォームから保険加入の申請をします。
2. VerifierからのProof提示要求
以下の画面はVerifierの管理画面です。この画面は上記の申請を完了したHolderの一覧を表示します。Verifierの担当者がHolderにProof提示の要求を出します。
3. Holderからの提示と検証
正常ケース(提示するケース)
HolderがVerifierから届いた要求メールのリンクをクリックすることで、アプリが起動します。そこからバックグランドでVerifierに対しProofを提示します。(Verifier側でもHolder同様、人が介在することなくバックグランドでProofを検証します。このあたりの技術的な流れは後述します。)
例外ケース(提示しないケース)
提示しないケースが2通りあります。
- VerifierからのProof要求に対し、Holderが拒否する場合
- VerifierからのProof要求に際し、Holderが要求条件に合致するVCを持たない場合
どちらの場合でも、HolderはVerifierに、提示を辞退した旨のメッセージを付けてAries RFCにおけるProblem Reportを送出する設計にしています。送出した後のHolderの画面は以下の通りです。
4.検証後のVerifier
正常ケース
Proof検証後に、Verifierアプリは検証状態と検証日を更新します。
例外ケース
シナリオは以上です。
技術面
ここからは技術面について説明していきます。
システム全体像
ポイント
- Issuer、Verifier、MediatorおよびIndy Ledgerについては、AWSを使っています。
- EC2 Instanceを1つ建てて、Dockerをインストールし、Issuer、Verifier、MediatorそれぞれのACA-Pyコンテナを建てました。またIndy Ledgerとしてvon-networkコンテナを建てました。
- IssuerとVerifierのControllerについては、各々にSPAを用意しました。Vue.js+Vuetifyで作ったフロントエンドをホストし、バックエンドにはサーバレスなAPIを作りました。詳細は後述します。
- Holderについては、この拙著と同様にAFJを利用し、React Native環境でAndroidアプリを作りました。
技術的に新しいポイント
これまでの記事と比較した技術的に新しいポイントは、以下の3つです。
- InvitationをDeep Link方式により読み込む。
これまでは、手動でAgent同士を繋ぐInvitationをコピーして、Swagger UIや画面にペーストしてConnectionを生成していました。今回は、上記の動画の通り、メール内のDeep LinkをクリックするとHolderのアプリが自動で起動してInvitationを読み込む、という実運用を意識した作りにしました。 -
Mediatorで1つのInvitationを使い回す。
各HolderがHolderアプリのインストール後の起動時に、Mediatorとのコネクションを自動で張れるよう、HolderアプリのコードにMediator側で作った固定のInvitationを埋め込んでいます。
ポイントは、MediatorのACA-Py Admin APIのPOST /connections/create-invitation
を呼んでInvitationを作成する際、クエリパラメータにてmulti_use=true
を設定することです。こうすることでMediatorは、1つのInvitationで、複数のHolderに対するコネクションを作ることが可能です。 -
AFJとACA-Py間にてZKPによるProof検証(証明)を行う。
Holder(AFJ)からVerifier(ACA-Py)にProof提示する際の提示方式には以下の2つがあります。これまでHolder(AFJ) – Verifier(ACA-Py)の組み合わせでは、前者の提示方式でしか技術検証していませんでしたが、今回は後者で取り行います。- Claim値を隠さず提示する。
- ZKPによりClaim値を隠し、閾値以上/以下の条件に合致しているかどうかを提示(証明)する。
SSIに関するOSSのバージョン
- Issuer/Verifier/Mediator
- ACA-Py: 0.7.4
- Holder
- AFJ
- @aries-framework/core: 0.3.3
- @aries-framework/react-native: 0.3.3
- AFJ Extensions
- @aries-framework/react-hooks: 0.4.0
- AFJ
- Indy Ledger
- von-network: 1.7.2
ToIP Technology StackのLayerごとに、使っている仕様
Layer 1
- did:sov
Layer 2
- Aries DIDComm v1
- Aries Connection Protocol
Layer 3
- Aries Issue Credential Protocol 1.0
- Aries Proof Present Protocol 1.0
- Indy AnonCreds
各Entityの詳細
ここからは各Entityごとに環境や実装におけるポイントを示します。
Issuer
詳細な環境図
ポイント
- 図中の黒い線はIssuerのUI操作をトリガーにする動線です。青い線は、Mediator経由でHolderからのDIDCommメッセージ受信した際のWebhook起動の動線です。
- アプリの実装方針として、Amplify CLIの守備範囲(フロントエンド環境、API Gateway、Lambda、DynamoDB)はAmplifyで、守備範囲の外(SQS、SES)はAWS CLI/Consoleで対応しています。
- 本格的な開発であれば、 いくつかのLambda(例えばSQSの背後にあるモノ)は別のSAMプロジェクトとして管理するところですが、今回はデモ用であるため、便宜的に全てのLambdaを1つのAmplifyプロジェクト内で管理しています。
- ACA-Pyの起動パラメーターにて、auto_issue=trueにしています。これにより、HolderからのVC発行要求受信後に、ACA-Pyが自動でVCを発行します。(これまでの記事では、明示的にIssuerのACA-Py APIの発行エンドポイントを叩いていました。)
Verifier
詳細な環境図
ポイント
- Issuerの記載事項と同様です。
- ACA-Pyの起動パラメーターにて、auto_verify=trueにしています。これにより、HolderからのProof提示直後に、ACA-Pyが自動でProofを検証します。(これまでの記事では、明示的にVerifierのACA-Py APIの検証エンドポイントを叩いていました。)
Holder
- Deep Link読み込み後はConnection状態、VC発行状態、Proof提出状態を監視することで画面の表示を変更しています。(詳細は後述のソースコードをご参照ください。)
- IssuerへのVC発行要求はバックグラウンドで行いますが、VerifierへのProof提示では、Holder(ユーザー)に提示確認のUIを出し、Holderがボタンを押すことがトリガーになる実装にしています。(詳細は後述のソースコードをご参照ください。)
- この拙著にある通り、Wallet Master KeyについてはPINコードからパスフレーズを生成する等の処理をするべきですが、今回の実装ではハードコードしています。
Mediator
“技術的に新しいポイント”にて前述した通りです。
Ledger
これまでと同様、von-networkを利用しています。
処理シーケンス図
上記の環境を踏まえて、VC発行とProof検証のおおよそのシーケンス図を示します。
(API GatewayやSQS、DynamoDBなど一部の要素は省略しています。)
図内の点線はDIDCommによる通信を意味します。
VC発行
Proof検証(正常系)
学び
- 学び: Issuerはある程度、共通化した方が良い。
今回のケースで言えば、健康診断を行う各病院がIssuerになるのではなく、健康診断結果を取りまとめてVCとして発行する組合があった方が良いと考えます。なぜかというと、Issuerが増えるたびに、つまりIndy Ledgerに検証対象となるPublic DIDが増えるたびに、Verifierが対応しないといけなくなるからです。 -
学び: ZKPによるProof提示/検証は、整数のみに対応している。
AFJのこのGitHubイシューによれば、Indy SDKの仕様で、ZKPできるClaimは整数のみであるようです。実際、Claimを小数点を含む値にして発行してもProof提示時にHolderでエラーが出ること、またVerifier側で設定する閾値に小数点を含む値を設定すると、HolderへのProof要求でエラーが出ることを確認しました。
ソースコード
Issuer/Holder/Verifierの各コードは以下で公開しています。
ご興味がありましたらご参照ください。
どなたかのお役に立てたならば幸いです。