SSI向きのユースケースを想定したプロトタイプ開発

(上のアイキャッチ画像の無断転載・流用を禁止します。)


こんにちは。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通りあります。

  1. VerifierからのProof要求に対し、Holderが拒否する場合
  2. 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つです。

  1. InvitationをDeep Link方式により読み込む。
    これまでは、手動でAgent同士を繋ぐInvitationをコピーして、Swagger UIや画面にペーストしてConnectionを生成していました。今回は、上記の動画の通り、メール内のDeep LinkをクリックするとHolderのアプリが自動で起動してInvitationを読み込む、という実運用を意識した作りにしました。

  2. 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に対するコネクションを作ることが可能です。

  3. AFJとACA-Py間にてZKPによるProof検証(証明)を行う。
    Holder(AFJ)からVerifier(ACA-Py)にProof提示する際の提示方式には以下の2つがあります。これまでHolder(AFJ) – Verifier(ACA-Py)の組み合わせでは、前者の提示方式でしか技術検証していませんでしたが、今回は後者で取り行います。

    • Claim値を隠さず提示する。
    • ZKPによりClaim値を隠し、閾値以上/以下の条件に合致しているかどうかを提示(証明)する。

SSIに関するOSSのバージョン

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検証(正常系)

学び

  1. 学び: Issuerはある程度、共通化した方が良い。
    今回のケースで言えば、健康診断を行う各病院がIssuerになるのではなく、健康診断結果を取りまとめてVCとして発行する組合があった方が良いと考えます。なぜかというと、Issuerが増えるたびに、つまりIndy Ledgerに検証対象となるPublic DIDが増えるたびに、Verifierが対応しないといけなくなるからです。

  2. 学び: ZKPによるProof提示/検証は、整数のみに対応している。
    AFJのこのGitHubイシューによれば、Indy SDKの仕様で、ZKPできるClaimは整数のみであるようです。実際、Claimを小数点を含む値にして発行してもProof提示時にHolderでエラーが出ること、またVerifier側で設定する閾値に小数点を含む値を設定すると、HolderへのProof要求でエラーが出ることを確認しました。

ソースコード

Issuer/Holder/Verifierの各コードは以下で公開しています。
ご興味がありましたらご参照ください。

どなたかのお役に立てたならば幸いです。