eIDAS 2.0でサポート必須のSD-JWT VCフォーマットとmdoc/mDLフォーマットのVerifiable Credentialを同時に発行してみた (たぶん世界初)

# はじめに

デジタルアイデンティティ業界は **<font color="red">Verifiable Credential</font>** (**検証可能な資格証明**) の話題で持ちきりです。特にヨーロッパでは、Verifiable Credential を管理するための **EU Digital Identity Wallet** (**EUDIW**) の整備が **eIDAS 2.0** という枠組み (法規制と技術仕様のセット) により要求されるため、技術仕様策定と実装が急ピッチで進んでいます。

そんな中、先日 (2024 年 1 月 19 日) 開催された『[OpenID Summit Tokyo 2024](https://www.openid.or.jp/summit/2024/)』では、ドイツ政府機関 [SPRIND](https://www.sprind.org/en/) から [Torsten Lodderstedt](https://www.linkedin.com/in/dr-torsten-lodderstedt/) 氏、イタリア研究機関 [FBK](https://www.fbk.eu/en/) から [Amir Sharif](https://www.linkedin.com/in/amir-sharif-341a2b37/) 氏、[OpenWallet Foundation](https://openwallet.foundation/) から [Joseph Heenan](https://www.linkedin.com/in/josephheenan/) 氏が来日し、デジタルアイデンティティウォレットに関連する講演を行いました。

同イベントでは私も登壇し、eIDAS 2.0 でサポート必須の Verifiable Credential フォーマットとして指定されている **<font color="red">SD-JWT VC</font>** フォーマットと **<font color="red">mdoc</font>/<font color="red">mDL</font>** フォーマットの Verifiable Credential を二つ同時に発行するデモを行いました。

![openid_summit_tokyo_2024_taka_session.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/6f6ea1b0-a465-7bc4-cb9e-7c7ebf62aaa8.png)

本記事では私の発表内容を振り返りたいと思います。

# VC/VP 関連仕様

Verifiable Credential / Verifiable Presentation 関連仕様は大きく二つのカテゴリに分類されます。一つは VC/VP のフォーマットに関する仕様群、もう一つは VC/VP の伝送に関する仕様群です。

![vc_vp_specifications.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/013deb7e-14e9-8fe5-4053-e0798ce4d57d.png)

関連仕様は他にもあるものの、フォーマットに関する仕様として次の三つを紹介しました。

- [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) (W3C VCDM)
- [SD-JWT-based Verifiable Credentials](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/) (SD-JWT VC)
- [ISO/IEC 18013-5:2021](https://www.iso.org/standard/69084.html) (mdoc/mDL)

**W3C VCDM** は Issuer-Wallet-Verifier モデルの定義の一次情報源とされています。

![third-party-model.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/f22520d3-7a8e-ec59-ae83-70e453f73810.png)

**SD-JWT VC** は、**選択的開示** (**Selective Disclosure**) を実現する **[SD-JWT](https://datatracker.ietf.org/doc/draft-ietf-oauth-selective-disclosure-jwt/)** というフォーマットに基づく Verifiable Credential フォーマットです。

**mdoc** は、**[ISO/IEC 18013-5:2021](https://www.iso.org/standard/69084.html)** Personal identification, ISO-compliant driving licence, Part 5: Mobile driving licence (mDL) application という ISO 文書で定義されているデータ構造で、**CBOR** ([RFC 8949](https://www.rfc-editor.org/rfc/rfc8949)) というバイナリフォーマットに基づいています。**mDL** は mdoc の一種で、同 ISO 文書内で定義されており、モバイル運転免許証を表しています。mDL には、氏名などの情報に加え、`driving_privileges` といった運転免許に特有の情報も含まれています。

VC/VP の伝送に関しては次の三つが中心となる仕様となっています。

- OpenID for Verifiable Credential Issuance (OID4VCI)
- OpenID for Verifiable Presentations (OID4VP)
- Self-Issued OpenID Provider version 2 (SIOPv2)

**<font color="red">OID4VCI</font>** は Verifiable Credential の発行手順を定義する技術仕様です。私のデモでは、この仕様の最新の[ワーキンググループドラフト](https://openid.github.io/OpenID4VCI/openid-4-verifiable-credential-issuance-wg-draft.html)に基づいて SD-JWT VC と mdoc/mDL の発行を行いました。

:::note warn
OID4VCI 仕様は破壊的変更の頻度が高いため、[openid.net 上で公開されているバージョン](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html)は実装者が参照する文書としては適切ではありません。実装者は、openid/[OpenID4VCI](https://github.com/openid/OpenID4VCI) レポジトリの main ブランチの更新に自動的に追随する[ワーキンググループドラフト](https://openid.github.io/OpenID4VCI/openid-4-verifiable-credential-issuance-wg-draft.html)を参照したほうがよいでしょう。
:::

# SD-JWT

## 選択的開示

SD-JWT VC がベースとしている SD-JWT について簡単に紹介しました。(過去記事: [SD-JWT (選択開示のためのデータフォーマット)](https://qiita.com/TakahikoKawasaki/items/cd2fbbb0bfcfab729d73))

Verifiable Credential を発行する**クレデンシャルイシュア**は、Verifiable Credential に埋め込む情報を用意します。この例では、氏名、生年月日、住所、を用意しています。

![selective_disclosure_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/c3044f86-a592-743d-ad96-1b3c5824dcd4.png)

それから、非対称鍵アルゴリズムの鍵ペアを用意し、

![selective_disclosure_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/01ad04fd-e245-1b71-c69f-ff7e6dd62573.png)

用意した情報を入力とし、秘密鍵を用いて署名を作成します。

![selective_disclosure_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/b5fab6b7-2f27-2485-3b72-2a3ba1017513.png)

クレデンシャルイシュアは、それらの情報と署名を含む Verifiable Credential を生成します。

![selective_disclosure_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/c999d8b3-dfc5-1931-8eda-8e4d20bae8e9.png)

クレデンシャルイシュアは、生成した Verifiable Credential を**ウォレット**に発行します。

![selective_disclosure_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/fc10bf2a-221d-963c-8bcb-f63ebc3683f4.png)

ウォレットは、開示する情報を取捨選択し (選択的開示)、Verifiable Presentation を作成します。この例では、氏名と生年月日を開示し、住所は非開示としています。

![selective_disclosure_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/aa788319-3086-7974-f2c1-2fd100c82686.png)

ウォレットは、生成した Verifiable Presentation を**ベリファイア**に提示します。

![selective_disclosure_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/bf463c6f-c281-daf9-e6f7-302355a5d44f.png)

ベリファイアは何らかの方法で、クレデンシャルイシュアが署名に使用した秘密鍵に対応する公開鍵を取得します。

![selective_disclosure_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/41218176-eac7-a328-5823-7021cdcfd9ef.png)

ベリファイアは、取得した公開鍵を用いて、VP に含まれる署名を検証します。

![selective_disclosure_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/3f0f3416-5dfc-ea24-94e0-d573ade7d6b4.png)

しかし、この署名検証は失敗します。

![selective_disclosure_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/5fe023c9-5bb1-911c-4b37-8496178103ff.png)

なぜなら、署名は「氏名、生年月日、住所」を入力として生成されたにもかかわらず、ベリファイアは氏名と生年月日しか受け取っておらず、「氏名、生年月日」を入力として署名を再計算しても、受け取った署名と再計算した署名の値が一致しないからです。

署名を有効なままに保ちつつ選択的開示を実現するには工夫が必要です。BBS+ (Boneh-Lynn-Shacham signature plus) や CL Signatures (Camenisch-Lysyanskaya Signatures) などは選択的開示を実現するための既存の手法ではありますが、幾つかの理由により、新たに SD-JWT というフォーマットが開発されることになりました。

## SD-JWT フォーマット

通常の JWT ではペイロード部にクレーム名とクレーム値がそのまま埋め込まれます。

![sd-jwt_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/15d450e1-1082-ea30-7608-16d14d08382f.png)

SD-JWT を生成するには、まず、クレーム名とクレーム値の組を取り出します。

![sd-jwt_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/f5e19ee8-6217-04c8-82cb-95ea254ef264.png)

そこに、十分なエントロピーを持つ任意のソルトを添え、

![sd-jwt_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/7cf03b4e-d28d-e0a3-ef79-7d49e65a6bef.png)

JSON 配列を作成します。

![sd-jwt_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/a13adf43-4948-2b62-baf8-e75d7228f1d7.png)

この JSON 配列を base64url でエンコードします。このようにして生成した
文字列を、SD-JWT 仕様では**ディスクロージャ** (**Disclosure**) と呼んでいます。

![sd-jwt_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/92d3bddf-da5d-6e9a-f1e0-e2d18f6d7cf3.png)

そして、元々クレームが置かれていた場所に `_sd` という名前の配列を作り、

![sd-jwt_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/ac012ecf-8a88-f4a0-0635-f943dbeba0c8.png)

その配列にディスクロージャのダイジェスト値を追加します。

![sd-jwt_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/18615078-64b6-6bf4-febd-987f56f60e91.png)

同じ処理を、選択的開示を可能にしたいクレーム群に対して繰り返します。

![sd-jwt_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/91fc7e17-95b5-02af-8b33-6af276eeb8f9.png)

上記のような手順で用意したペイロードを持つ JWT を作成します。仕様はこの JWT を **Issuer-signed JWT** と呼びます。

![sd-jwt_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/1c1512f3-d845-d71d-daca-710664599597.png)

そして、ディスクロージャ群を後ろに並べ、

![sd-jwt_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/218e551f-dce6-c65f-b271-f75de8147b79.png)

チルダ (`~`) で連結します。

![sd-jwt_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/29825651-b374-6747-8838-2ae8578ab40e.png)

こうして出来上がった文字列が SD-JWT です。

![sd-jwt_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/8c04161d-e9d8-b475-b400-047dad4c6030.png)

詳細説明は省きますが、**キーバインディング** (**Key Binding**) という仕組みのため、公開鍵を Issuer-signed JWT のペイロード部に埋め込み、SD-JWT の末尾に Key Binding JWT を追加する場合もあります。

![sd-jwt_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/b3db972a-325a-dc70-f435-64e7e979cde7.png)

SD-JWT 生成手順の全体像は次のようになります。

![sd-jwt.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/d207c026-fe58-fea0-83ee-72da0a3a6d4b.png)

<br>

さて、全てのディスクロージャを含む SD-JWT を受け取ったとしましょう。この場合、ディスクロージャ群を base64url でデコードすることにより、全てのクレーム名とクレーム値の組を得ることができます。

![sd-jwt-vp_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/8d1e7bcf-3adc-6423-b744-4da38ed466de.png)

一方で、ディスクロージャ群の一部しか含まれていない場合、含まれているディスクロージャに対応するクレーム名とクレーム値の組しか得ることができません。

![sd-jwt-vp_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/2249ed15-72c6-4f0e-dacb-29c68a905008.png)

ここで何が嬉しいのかというと、ディスクロージャ群が一部しか含まれていなくても、Issuer-signed JWT の署名は有効のまま、という点です。つまり、Issuer-signed JWT のヘッダ部と `_sd` 配列を含むペイロード部を入力として署名を再計算すると、Issuer-signed JWT についている署名と一致するのです。

# OID4VCI

OID4VCI は Verifiable Credential の発行手順を定義する技術仕様です。

## コンセプト

コンセプト自体は比較的単純です。まず、認可サーバがウォレットにアクセストークンを発行します。

![oid4vci_concept_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/0ab1eb09-7a49-be23-26ad-2974807249c2.png)

ウォレットはそのアクセストークンをクレデンシャルイシュアに提示します。

![oid4vci_concept_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/3acf097b-7d57-08e8-7ee1-81495d3ba180.png)

クレデンシャルイシュアはウォレットに Verifiable Credential を発行します。

![oid4vci_concept_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/c074f391-9c13-d80d-94a5-3ce85f859540.png)

## アクセストークン発行

コンセプトは単純なのですが、Verifiable Credential 発行に使えるアクセストークンを発行するための手順が複数定義されています。

まず、**クレデンシャルオファー**というものがクレデンシャルイシュアから発行済みで、それが**事前認可コード** (**pre-authorized code**) を含んでいる場合、

![access_token_issuance_1.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/8a9b213e-b3d6-ec48-6ee1-4e1d0fcd7823.png)

ウォレットはその事前認可コードをトークンエンドポイントに提示することでアクセストークンを取得することができます。

![access_token_issuance_2.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/f3407627-b8d9-8f98-ef48-474324294a82.png)

一方、クレデンシャルオファーに**イシュアステート** (**issuer state**) が含まれている場合、

![access_token_issuance_3.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/26fdc323-895c-b286-01c1-d6aa8f47271a.png)

そのイシュアステートを含む認可リクエストを認可エンドポイントに投げて認可コードを受け取り、

![access_token_issuance_4.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/885aa8dd-d076-f7c9-6af4-6862c3443946.png)

あとはいつもの認可コードフローでトークンエンドポイントからアクセストークンを受け取ります。

![access_token_issuance_5.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/b37c6f98-46a7-bc48-3b62-903a8f2a06c4.png)

クレデンシャルオファーを使わず、[RFC 9396 OAuth 2.0 Rich Authorization Requests](https://www.rfc-editor.org/rfc/rfc9396.html) で定義されている RAR オブジェクトを使う方法も定義されています。

![access_token_issuance_6.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/6dd40a80-c878-899e-bc81-29581179b826.png)

クレデンシャルイシュアの設定によっては、`scope` パラメーターの値として使えるショートカットが提供されていることがあり、その場合、`scope` パラメーターを使うこともできます。

![access_token_issuance_7.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/afaf9069-483a-42e8-b954-922fa80d14b1.png)

そういうわけで、OID4VCI 仕様ではアクセストークンを取得する方法が 4 つ定義されています。

![access_token_issuance.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/270ec2d8-8113-3a49-4072-b91c870844d4.png)

## Verifiable Credential 発行

アクセストークンをクレデンシャルイシュアの**クレデンシャルエンドポイント** (**credential endpoint**) に提示することで、ウォレットは Verifiable Credential を取得することができます。

![verifiable_credential_issuance_1.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/3cefc711-0570-79c3-044d-21cb296dafdd.png)

しかし、クレデンシャルエンドポイントは、アクセストークンを提示されたときに、すぐに Verifiable Credential を生成できないかもしれません。その場合、クレデンシャルエンドポイントは Verifiable Credential のかわりに**トランザクション ID** (**transaction ID**) を発行します。

![verifiable_credential_issuance_2.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/efc512c5-79eb-5f72-1eb9-6204830b2cf9.png)

トランザクション ID を受け取ったウォレットは、後ほど、クレデンシャルイシュアの**遅延クレデンシャルエンドポイント** (**deferred credential endpoint**) にアクセストークンと共にトランザクション ID を提示します。このとき、Verifiable Credential が用意できていれば、Verifiable Credential が得られます。まだ用意できていなければ、`issuance_pending` エラーが返されます。

![verifiable_credential_issuance_3.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/f7b7ec2d-cc7b-e23d-a869-6a2e625d1c1f.png)

一度に複数の Verifiable Credential を取得したい場合は、クレデンシャルエンドポイントのかわりに**一括クレデンシャルエンドポイント** (**batch credential endpoint**) を利用します。

![verifiable_credential_issuance_4.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/66d01670-c027-a0e9-5354-74c81af9cb7e.png)

クレデンシャルエンドポイントと同様、一括クレデンシャルエンドポイントでも Verifiable Credential をすぐに生成できないことがありえます。この場合、すぐに発行できない Verifiable Credential ごとに一つのトランザクション ID が返されます。

![verifiable_credential_issuance_5.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/464974c6-e045-baa6-4b20-58ae4ba084fc.png)

先ほどと同様に、発行されたトランザクション ID を遅延クレデンシャルエンドポイントに提示することで、対応する Verifiable Credential を取得することができます。

![verifiable_credential_issuance_6.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/79b4c6c3-74e9-1932-403f-0b4f0c500d8f.png)

これまでに紹介した Verifiable Credential 発行フローを一つの図にまとめると次のようになります。

![verifiable_credential_issuance.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/6a381399-23c8-6209-da48-ac10c27a4fb9.png)

# デモ

デモでは、事前認可コードを用いる**事前認可コードフロー** (**pre-authorized code flow**) でアクセストークンを取得し、そのアクセストークンを一括クレデンシャルエンドポイントに提示し、SD-JWT VC フォーマットと mdoc/mDL フォーマットの Verifiable Credential を生成しました。

![demo_flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/32697af1-191a-2d1c-d0d9-1b78ac2f6a4c.png)

:::note warn
手順が単純なのでデモでは事前認可コードフローを用いましたが、セキュリティ上の懸念からイタリアでは事前認可コードフローをサポートしません。
:::

## 事前準備

デモ用に幾つかシェル変数を設定しておきます。

```shell-session
CLIENT_ID=218232426
TOKEN_ENDPOINT=https://trial.authlete.net/api/token
BATCH_CREDENTIAL_ENDPOINT=https://trial.authlete.net/api/batch_credential
```

変数値の中に現れる `trial.authlete.net` はデモ用の認可サーバ兼クレデンシャルイシュアで、その実装は authlete/[java-oauth-server](https://github.com/authlete/java-oauth-server) です。

## クレデンシャルオファー取得

デモ用のクレデンシャルオファーを生成する https://trial.authlete.net/api/offer/issue にアクセスし、事前認可コードを含むクレデンシャルオファーを取得します。詳細については『[4.1.2. 事前認可コード](https://www.authlete.com/ja/developers/oid4vci/#412-%E4%BA%8B%E5%89%8D%E8%AA%8D%E5%8F%AF%E3%82%B3%E3%83%BC%E3%83%89)』を参照してください。

取得した事前認可コードをシェル変数に設定します。

```shell-session
PRE_AUTHORIZED_CODE=${取得した事前認可コード}
```

## アクセストークン取得

事前認可コードフローでアクセストークンを取得します。

```shell-session:トークンリクエスト
curl -s $TOKEN_ENDPOINT \
     -d client_id=$CLIENT_ID \
     -d grant_type=urn:ietf:params:oauth:grant-type:pre-authorized_code \
     -d pre-authorized_code=$PRE_AUTHORIZED_CODE
```

取得したアクセストークンをシェル変数に設定します。

```shell-session
ACCESS_TOKEN=${取得したアクセストークン}
```

## Verifiable Credential 取得

一括クレデンシャルエンドポイントに一括クレデンシャルリクエストを投げます。

```shell-session:一括クレデンシャルリクエスト
curl -s $BATCH_CREDENTIAL_ENDPOINT \
     -H "Authorization: Bearer $ACCESS_TOKEN" \
     -H "Content-Type: application/json" \
     --data '{
  "credential_requests": [
    {
      "format": "vc+sd-jwt",
      "vct": "https://credentials.example.com/identity_credential"
    },
    {
      "format": "mso_mdoc",
      "doctype": "org.iso.18013.5.1.mDL",
      "claims": {
        "org.iso.18013.5.1": {
          "family_name": {}, "given_name": {}, "birth_date": {},
          "issue_date": {}, "expiry_date": {}, "issuing_country": {},
          "document_number": {}, "driving_privileges": {}
        }
      }
    }
  ]
}'
```

リクエストのメッセージボディは JSON です。その JSON には `credential_requests` という配列があり、その配列の要素は JSON オブジェクトです。それぞれの JSON オブジェクトは、取得したい Verifiable Credential を指定する情報を含んでいます。この例では、一つ目の JSON オブジェクトで SD-JWT VC を、二つ目の JSON オブジェクトで mdoc を指定しています。

エンドポイントからは次のような JSON が返されます。

```json:一括クレデンシャルレスポンス
{
  "credential_responses": [
    {
      "format": "vc+sd-jwt",
      "credential": "eyJraWQiOiJKMUZ3SlA4N0M2LVFOX1dTSU9tSkFRYzZuNUNRX2JaZGFGSjVHRG5XMVJrIiwidHlwIjoidmMrc2Qtand0IiwiYWxnIjoiRVMyNTYifQ.eyJpc3MiOiJodHRwczovL3RyaWFsLmF1dGhsZXRlLm5ldCIsIl9zZCI6WyIwczNiazZYcC02ZW1rV3cxTFd2OWthaGk5YjNUV0c2NDJLV3dpZEZKeHlvIiwiM3BSUGNUUjItSkJySjhVRjVkZGhtcDhwbDA3MEpheWpoMWEzZVVWRDZNZyIsIjZ6UEtKS2pzc2Y0Q1JNNmhUeDZZVUdQdzRBbm1ZWHZocnFuZDlmdTZMcUkiLCJBVnFKdDdkcWNEVWZLNmJPSEg0UTFEODVfMVNmLXRwM0d0QlM1Mk1Bb3FVIiwiQldydzdVV2YzdjF4cjdOOXFoSFpXMHMwa0FERDVGbFgtUmNQV2dCZEFJOCIsIkhtcHVfdVo4dWo4b2ViMXIyaGg2YmdUY3dNbEJoVHNrUjIxR2tZZVd4TW8iLCJNQ1JpVkRYc3I3MTJ1WW9NRUtWeEJfMmFxX0oweENfa08yNTdwQ3N0RlB3IiwiTUc3WElRV1Y5RFE2dC12WDdmZERUblZ6bnpTZUwwY2gtX0NtNkkyM3ZDWSIsIlB5VEVrajdFdUhScGljdFk5Z1ZpQTVhcTBrYTd2SzJZdDRrX04wbzlTb3ciXSwiaWF0IjoxNzA1MDE4MjA1LCJ2Y3QiOiJodHRwczovL2NyZWRlbnRpYWxzLmV4YW1wbGUuY29tL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJfc2RfYWxnIjoic2hhLTI1NiJ9.ll4JdW-ksNDyVGx-OTueQYojpUYXhUZ6J31fFKGall2SsT5LQt-I5w24AiYhDvxYWRGRCmJF5UI-_3SpNE83wQ~WyJJZEJuZ2xIcF9URGRyeUwycGJLZVNBIiwic3ViIiwiMTAwNCJd~WyJDd0lYNU11clBMZ1VFRnA2U2JhM0dnIiwiZ2l2ZW5fbmFtZSIsIkluZ2EiXQ~WyJveUYtR3Q5LXVwa1FkU0ZMX0pTekNnIiwiZmFtaWx5X25hbWUiLCJTaWx2ZXJzdG9uZSJd~WyJMZG9oSjQ5d2gwcTBubWNJUG92SVhnIiwiYmlydGhkYXRlIiwiMTk5MS0xMS0wNiJd~"
    },
    {
      "format": "mso_mdoc",
      "credential": "omdkb2NUeXBldW9yZy5pc28uMTgwMTMuNS4xLm1ETGxpc3N1ZXJTaWduZWSiam5hbWVTcGFjZXOhcW9yZy5pc28uMTgwMTMuNS4xiNgYWFukaGRpZ2VzdElEAWZyYW5kb21QcbnmTIHt0_17t-AcHkKZbHFlbGVtZW50SWRlbnRpZmllcmppc3N1ZV9kYXRlbGVsZW1lbnRWYWx1ZdkD7GoyMDI0LTAxLTEy2BhYXKRoZGlnZXN0SUQCZnJhbmRvbVBRwvzBVJYBc2plhd7vXZwTcWVsZW1lbnRJZGVudGlmaWVya2V4cGlyeV9kYXRlbGVsZW1lbnRWYWx1ZdkD7GoyMDI1LTAxLTEy2BhYWqRoZGlnZXN0SUQDZnJhbmRvbVDcuBh2xE6SqxDDECOY9H3CcWVsZW1lbnRJZGVudGlmaWVya2ZhbWlseV9uYW1lbGVsZW1lbnRWYWx1ZWtTaWx2ZXJzdG9uZdgYWFKkaGRpZ2VzdElEBGZyYW5kb21QHu5Fe96gJQH-NeOAvSuJdHFlbGVtZW50SWRlbnRpZmllcmpnaXZlbl9uYW1lbGVsZW1lbnRWYWx1ZWRJbmdh2BhYW6RoZGlnZXN0SUQFZnJhbmRvbVDI-4b03R-29ljFhUoZMHP0cWVsZW1lbnRJZGVudGlmaWVyamJpcnRoX2RhdGVsZWxlbWVudFZhbHVl2QPsajE5OTEtMTEtMDbYGFhVpGhkaWdlc3RJRAZmcmFuZG9tUCJlXpl0UAxhiiN9BwSnLeBxZWxlbWVudElkZW50aWZpZXJvaXNzdWluZ19jb3VudHJ5bGVsZW1lbnRWYWx1ZWJVU9gYWFukaGRpZ2VzdElEB2ZyYW5kb21QbWz_ggUxytSax7_FqCzoEHFlbGVtZW50SWRlbnRpZmllcm9kb2N1bWVudF9udW1iZXJsZWxlbWVudFZhbHVlaDEyMzQ1Njc42BhYoqRoZGlnZXN0SUQIZnJhbmRvbVBbSwOg91lMspu_ctBa2uqgcWVsZW1lbnRJZGVudGlmaWVycmRyaXZpbmdfcHJpdmlsZWdlc2xlbGVtZW50VmFsdWWBo3V2ZWhpY2xlX2NhdGVnb3J5X2NvZGVhQWppc3N1ZV9kYXRl2QPsajIwMjMtMDEtMDFrZXhwaXJ5X2RhdGXZA-xqMjA0My0wMS0wMWppc3N1ZXJBdXRohEOhASahGCFZAWEwggFdMIIBBKADAgECAgYBjJHZwhkwCgYIKoZIzj0EAwIwNjE0MDIGA1UEAwwrSjFGd0pQODdDNi1RTl9XU0lPbUpBUWM2bjVDUV9iWmRhRko1R0RuVzFSazAeFw0yMzEyMjIxNDA2NTZaFw0yNDEwMTcxNDA2NTZaMDYxNDAyBgNVBAMMK0oxRndKUDg3QzYtUU5fV1NJT21KQVFjNm41Q1FfYlpkYUZKNUdEblcxUmswWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQCilV5ugmlhHJzDVgqSRE5d8KkoQqX1jVg8WE4aPjFODZQ66fFPFIhWRP3ioVUi67WGQSgTY3F6Vmjf7JMVQ4MMAoGCCqGSM49BAMCA0cAMEQCIGcWNJwFy8RGV4uMwK7k1vEkqQ2xr-BCGRdN8OZur5PeAiBVrNuxV1C9mCW5z2clhDFaXNdP2Lp_7CBQrHQoJhuPcNgYWQHopWd2ZXJzaW9uYzEuMG9kaWdlc3RBbGdvcml0aG1nU0hBLTI1Nmx2YWx1ZURpZ2VzdHOhcW9yZy5pc28uMTgwMTMuNS4xqAFYIKuS8FCeCcvDMwZgEezuuVv-DYsUpdypJp9abJrqHAmXAlggu7D-3vr-NrLg3zigunUzEKFqYAyG5sA-ffvmDjRxZ24DWCC2OBnhoZFhqE7s8PRfdej8t5frp-HgF_2X4qMtzvEY6ARYIBF_rl93VR21umkIdSMiWqFmT5Jxs0n3H5SWonWrJoDrBVggKDvVyMU358Le0n6TkVb2c0BbhbSMJwpswtPLNiZrTR8GWCAFZzJwAmnC7QcMQwq72FDQlmPxk0434cZbh6_rt1VagQdYIHwBHQ3-sVPtco-RcUhuYYq6iivujjYyJmQBbQ_OdhFDCFggcjT2HYgkoxnwWP-9jqO_6-D-d69H9UW2xjpDWrknlvBnZG9jVHlwZXVvcmcuaXNvLjE4MDEzLjUuMS5tRExsdmFsaWRpdHlJbmZvo2ZzaWduZWTAdDIwMjQtMDEtMTJUMDA6MTA6MDVaaXZhbGlkRnJvbcB0MjAyNC0wMS0xMlQwMDoxMDowNVpqdmFsaWRVbnRpbMB0MjAyNS0wMS0xMlQwMDoxMDowNVpYQHFzEb09NFyFlj533FE_1B9I2rku90K52ar64Id1CyOUXWXzhINeVfoJU1cfxgCT2CX1369cGd_TQxSjhVx8bpY"
    }
  ],
  "c_nonce": "BvPJWhd3jvBCeooQTzSBNk0TCU4BHq150odu_vpAvSY",
  "c_nonce_expires_in": 86052
}
```

レスポンスには `credential_responses` という配列が含まれており、配列内の要素は、リクエストの `credential_requests` 配列の各要素に対応しています。

各要素は JSON オブジェクトで、そのオブジェクトに `credential` プロパティが含まれていれば、その値が発行された Verifiable Credential です。

### SD-JWT VC

この例では、一番目の JSON オブジェクト内の `credential` プロパティの値は SD-JWT VC フォーマットの Verifiable Credential です。

```:SD-JWT VC
eyJraWQiOiJKMUZ3SlA4N0M2LVFOX1dTSU9tSkFRYzZuNUNRX2JaZGFGSjVHRG5XMVJrIiwidHlwIjoidmMrc2Qtand0IiwiYWxnIjoiRVMyNTYifQ.eyJpc3MiOiJodHRwczovL3RyaWFsLmF1dGhsZXRlLm5ldCIsIl9zZCI6WyIwczNiazZYcC02ZW1rV3cxTFd2OWthaGk5YjNUV0c2NDJLV3dpZEZKeHlvIiwiM3BSUGNUUjItSkJySjhVRjVkZGhtcDhwbDA3MEpheWpoMWEzZVVWRDZNZyIsIjZ6UEtKS2pzc2Y0Q1JNNmhUeDZZVUdQdzRBbm1ZWHZocnFuZDlmdTZMcUkiLCJBVnFKdDdkcWNEVWZLNmJPSEg0UTFEODVfMVNmLXRwM0d0QlM1Mk1Bb3FVIiwiQldydzdVV2YzdjF4cjdOOXFoSFpXMHMwa0FERDVGbFgtUmNQV2dCZEFJOCIsIkhtcHVfdVo4dWo4b2ViMXIyaGg2YmdUY3dNbEJoVHNrUjIxR2tZZVd4TW8iLCJNQ1JpVkRYc3I3MTJ1WW9NRUtWeEJfMmFxX0oweENfa08yNTdwQ3N0RlB3IiwiTUc3WElRV1Y5RFE2dC12WDdmZERUblZ6bnpTZUwwY2gtX0NtNkkyM3ZDWSIsIlB5VEVrajdFdUhScGljdFk5Z1ZpQTVhcTBrYTd2SzJZdDRrX04wbzlTb3ciXSwiaWF0IjoxNzA1MDE4MjA1LCJ2Y3QiOiJodHRwczovL2NyZWRlbnRpYWxzLmV4YW1wbGUuY29tL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJfc2RfYWxnIjoic2hhLTI1NiJ9.ll4JdW-ksNDyVGx-OTueQYojpUYXhUZ6J31fFKGall2SsT5LQt-I5w24AiYhDvxYWRGRCmJF5UI-_3SpNE83wQ~WyJJZEJuZ2xIcF9URGRyeUwycGJLZVNBIiwic3ViIiwiMTAwNCJd~WyJDd0lYNU11clBMZ1VFRnA2U2JhM0dnIiwiZ2l2ZW5fbmFtZSIsIkluZ2EiXQ~WyJveUYtR3Q5LXVwa1FkU0ZMX0pTekNnIiwiZmFtaWx5X25hbWUiLCJTaWx2ZXJzdG9uZSJd~WyJMZG9oSjQ5d2gwcTBubWNJUG92SVhnIiwiYmlydGhkYXRlIiwiMTk5MS0xMS0wNiJd~
```

SD-JWT VC は、各所 base64url でエンコードされているだけなので、デコードはさほど難しい処理ではありません。authlete/[oid4vci-demo](https://github.com/authlete/oid4vci-demo) レポジトリ内にある [decode-sd-jwt](https://github.com/authlete/oid4vci-demo/blob/main/decode-sd-jwt) スクリプトを使うと、次のようなデコード結果が得られます。

```json
{
  "kid": "J1FwJP87C6-QN_WSIOmJAQc6n5CQ_bZdaFJ5GDnW1Rk",
  "typ": "vc+sd-jwt",
  "alg": "ES256"
}
{
  "iss": "https://trial.authlete.net",
  "_sd": [
    "0s3bk6Xp-6emkWw1LWv9kahi9b3TWG642KWwidFJxyo",
    "3pRPcTR2-JBrJ8UF5ddhmp8pl070Jayjh1a3eUVD6Mg",
    "6zPKJKjssf4CRM6hTx6YUGPw4AnmYXvhrqnd9fu6LqI",
    "AVqJt7dqcDUfK6bOHH4Q1D85_1Sf-tp3GtBS52MAoqU",
    "BWrw7UWf3v1xr7N9qhHZW0s0kADD5FlX-RcPWgBdAI8",
    "Hmpu_uZ8uj8oeb1r2hh6bgTcwMlBhTskR21GkYeWxMo",
    "MCRiVDXsr712uYoMEKVxB_2aq_J0xC_kO257pCstFPw",
    "MG7XIQWV9DQ6t-vX7fdDTnVznzSeL0ch-_Cm6I23vCY",
    "PyTEkj7EuHRpictY9gViA5aq0ka7vK2Yt4k_N0o9Sow"
  ],
  "iat": 1705018205,
  "vct": "https://credentials.example.com/identity_credential",
  "_sd_alg": "sha-256"
}
{
  "digest": "6zPKJKjssf4CRM6hTx6YUGPw4AnmYXvhrqnd9fu6LqI",
  "WyJJZEJuZ2xIcF9URGRyeUwycGJLZVNBIiwic3ViIiwiMTAwNCJd": [
    "IdBnglHp_TDdryL2pbKeSA",
    "sub",
    "1004"
  ]
}
{
  "digest": "MG7XIQWV9DQ6t-vX7fdDTnVznzSeL0ch-_Cm6I23vCY",
  "WyJDd0lYNU11clBMZ1VFRnA2U2JhM0dnIiwiZ2l2ZW5fbmFtZSIsIkluZ2EiXQ": [
    "CwIX5MurPLgUEFp6Sba3Gg",
    "given_name",
    "Inga"
  ]
}
{
  "digest": "3pRPcTR2-JBrJ8UF5ddhmp8pl070Jayjh1a3eUVD6Mg",
  "WyJveUYtR3Q5LXVwa1FkU0ZMX0pTekNnIiwiZmFtaWx5X25hbWUiLCJTaWx2ZXJzdG9uZSJd": [
    "oyF-Gt9-upkQdSFL_JSzCg",
    "family_name",
    "Silverstone"
  ]
}
{
  "digest": "Hmpu_uZ8uj8oeb1r2hh6bgTcwMlBhTskR21GkYeWxMo",
  "WyJMZG9oSjQ5d2gwcTBubWNJUG92SVhnIiwiYmlydGhkYXRlIiwiMTk5MS0xMS0wNiJd": [
    "LdohJ49wh0q0nmcIPovIXg",
    "birthdate",
    "1991-11-06"
  ]
}
```

図解すると次のようになります。

![sd-jwt_vc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/fa3c866c-ca7b-af4e-c997-d73b89abfbde.png)

### mdoc/mDL

二番目の JSON オブジェクト内の `credential` プロパティの値は mdoc/mDL フォーマットの Verifiable Credential です。

```:mdoc/mDL
omdkb2NUeXBldW9yZy5pc28uMTgwMTMuNS4xLm1ETGxpc3N1ZXJTaWduZWSiam5hbWVTcGFjZXOhcW9yZy5pc28uMTgwMTMuNS4xiNgYWFukaGRpZ2VzdElEAWZyYW5kb21QcbnmTIHt0_17t-AcHkKZbHFlbGVtZW50SWRlbnRpZmllcmppc3N1ZV9kYXRlbGVsZW1lbnRWYWx1ZdkD7GoyMDI0LTAxLTEy2BhYXKRoZGlnZXN0SUQCZnJhbmRvbVBRwvzBVJYBc2plhd7vXZwTcWVsZW1lbnRJZGVudGlmaWVya2V4cGlyeV9kYXRlbGVsZW1lbnRWYWx1ZdkD7GoyMDI1LTAxLTEy2BhYWqRoZGlnZXN0SUQDZnJhbmRvbVDcuBh2xE6SqxDDECOY9H3CcWVsZW1lbnRJZGVudGlmaWVya2ZhbWlseV9uYW1lbGVsZW1lbnRWYWx1ZWtTaWx2ZXJzdG9uZdgYWFKkaGRpZ2VzdElEBGZyYW5kb21QHu5Fe96gJQH-NeOAvSuJdHFlbGVtZW50SWRlbnRpZmllcmpnaXZlbl9uYW1lbGVsZW1lbnRWYWx1ZWRJbmdh2BhYW6RoZGlnZXN0SUQFZnJhbmRvbVDI-4b03R-29ljFhUoZMHP0cWVsZW1lbnRJZGVudGlmaWVyamJpcnRoX2RhdGVsZWxlbWVudFZhbHVl2QPsajE5OTEtMTEtMDbYGFhVpGhkaWdlc3RJRAZmcmFuZG9tUCJlXpl0UAxhiiN9BwSnLeBxZWxlbWVudElkZW50aWZpZXJvaXNzdWluZ19jb3VudHJ5bGVsZW1lbnRWYWx1ZWJVU9gYWFukaGRpZ2VzdElEB2ZyYW5kb21QbWz_ggUxytSax7_FqCzoEHFlbGVtZW50SWRlbnRpZmllcm9kb2N1bWVudF9udW1iZXJsZWxlbWVudFZhbHVlaDEyMzQ1Njc42BhYoqRoZGlnZXN0SUQIZnJhbmRvbVBbSwOg91lMspu_ctBa2uqgcWVsZW1lbnRJZGVudGlmaWVycmRyaXZpbmdfcHJpdmlsZWdlc2xlbGVtZW50VmFsdWWBo3V2ZWhpY2xlX2NhdGVnb3J5X2NvZGVhQWppc3N1ZV9kYXRl2QPsajIwMjMtMDEtMDFrZXhwaXJ5X2RhdGXZA-xqMjA0My0wMS0wMWppc3N1ZXJBdXRohEOhASahGCFZAWEwggFdMIIBBKADAgECAgYBjJHZwhkwCgYIKoZIzj0EAwIwNjE0MDIGA1UEAwwrSjFGd0pQODdDNi1RTl9XU0lPbUpBUWM2bjVDUV9iWmRhRko1R0RuVzFSazAeFw0yMzEyMjIxNDA2NTZaFw0yNDEwMTcxNDA2NTZaMDYxNDAyBgNVBAMMK0oxRndKUDg3QzYtUU5fV1NJT21KQVFjNm41Q1FfYlpkYUZKNUdEblcxUmswWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQCilV5ugmlhHJzDVgqSRE5d8KkoQqX1jVg8WE4aPjFODZQ66fFPFIhWRP3ioVUi67WGQSgTY3F6Vmjf7JMVQ4MMAoGCCqGSM49BAMCA0cAMEQCIGcWNJwFy8RGV4uMwK7k1vEkqQ2xr-BCGRdN8OZur5PeAiBVrNuxV1C9mCW5z2clhDFaXNdP2Lp_7CBQrHQoJhuPcNgYWQHopWd2ZXJzaW9uYzEuMG9kaWdlc3RBbGdvcml0aG1nU0hBLTI1Nmx2YWx1ZURpZ2VzdHOhcW9yZy5pc28uMTgwMTMuNS4xqAFYIKuS8FCeCcvDMwZgEezuuVv-DYsUpdypJp9abJrqHAmXAlggu7D-3vr-NrLg3zigunUzEKFqYAyG5sA-ffvmDjRxZ24DWCC2OBnhoZFhqE7s8PRfdej8t5frp-HgF_2X4qMtzvEY6ARYIBF_rl93VR21umkIdSMiWqFmT5Jxs0n3H5SWonWrJoDrBVggKDvVyMU358Le0n6TkVb2c0BbhbSMJwpswtPLNiZrTR8GWCAFZzJwAmnC7QcMQwq72FDQlmPxk0434cZbh6_rt1VagQdYIHwBHQ3-sVPtco-RcUhuYYq6iivujjYyJmQBbQ_OdhFDCFggcjT2HYgkoxnwWP-9jqO_6-D-d69H9UW2xjpDWrknlvBnZG9jVHlwZXVvcmcuaXNvLjE4MDEzLjUuMS5tRExsdmFsaWRpdHlJbmZvo2ZzaWduZWTAdDIwMjQtMDEtMTJUMDA6MTA6MDVaaXZhbGlkRnJvbcB0MjAyNC0wMS0xMlQwMDoxMDowNVpqdmFsaWRVbnRpbMB0MjAyNS0wMS0xMlQwMDoxMDowNVpYQHFzEb09NFyFlj533FE_1B9I2rku90K52ar64Id1CyOUXWXzhINeVfoJU1cfxgCT2CX1369cGd_TQxSjhVx8bpY
```

この値は、CBOR データを base64url でエンコードしたものです。そのため、デコードするとバイナリデータになるので、人が読んでも分かりません。そこで、CBOR データを解析するオンラインツール『**[CBOR Zone](https://cbor.zone/)**』を用意しましたので、是非活用してください。

例えば、上記の mdoc を入力として CBOR Zone に渡し、CBOR 診断記法 ([RFC 8949, 8. Diagnostic Notation](https://www.rfc-editor.org/rfc/rfc8949#section-8), [RFC 8610, Appendix G. Extended Diagnostic Notation](https://www.rfc-editor.org/rfc/rfc8610#appendix-G)) を出力フォーマットとして指定して "Generate" ボタンを押すと、次の情報が得られます。

```:CBOR診断記法で表現されたmdoc
{
  "docType": "org.iso.18013.5.1.mDL",
  "issuerSigned": {
    "nameSpaces": {
      "org.iso.18013.5.1": [
        24(<<
          {
            "digestID": 1,
            "random": h'71b9e64c81edd3fd7bb7e01c1e42996c',
            "elementIdentifier": "issue_date",
            "elementValue": 1004("2024-01-12")
          }
        >>),
        24(<<
          {
            "digestID": 2,
            "random": h'51c2fcc1549601736a6585deef5d9c13',
            "elementIdentifier": "expiry_date",
            "elementValue": 1004("2025-01-12")
          }
        >>),
        24(<<
          {
            "digestID": 3,
            "random": h'dcb81876c44e92ab10c3102398f47dc2',
            "elementIdentifier": "family_name",
            "elementValue": "Silverstone"
          }
        >>),
        24(<<
          {
            "digestID": 4,
            "random": h'1eee457bdea02501fe35e380bd2b8974',
            "elementIdentifier": "given_name",
            "elementValue": "Inga"
          }
        >>),
        24(<<
          {
            "digestID": 5,
            "random": h'c8fb86f4dd1fb6f658c5854a193073f4',
            "elementIdentifier": "birth_date",
            "elementValue": 1004("1991-11-06")
          }
        >>),
        24(<<
          {
            "digestID": 6,
            "random": h'22655e9974500c618a237d0704a72de0',
            "elementIdentifier": "issuing_country",
            "elementValue": "US"
          }
        >>),
        24(<<
          {
            "digestID": 7,
            "random": h'6d6cff820531cad49ac7bfc5a82ce810',
            "elementIdentifier": "document_number",
            "elementValue": "12345678"
          }
        >>),
        24(<<
          {
            "digestID": 8,
            "random": h'5b4b03a0f7594cb29bbf72d05adaeaa0',
            "elementIdentifier": "driving_privileges",
            "elementValue": [
              {
                "vehicle_category_code": "A",
                "issue_date": 1004("2023-01-01"),
                "expiry_date": 1004("2043-01-01")
              }
            ]
          }
        >>)
      ]
    },
    "issuerAuth": [
      h'a10126',
      {
        33: h'3082015d30820104a0030201020206018c91d9c219300a06082a8648ce3d04030230363134303206035504030c2b4a3146774a50383743362d514e5f5753494f6d4a415163366e3543515f625a6461464a3547446e5731526b301e170d3233313232323134303635365a170d3234313031373134303635365a30363134303206035504030c2b4a3146774a50383743362d514e5f5753494f6d4a415163366e3543515f625a6461464a3547446e5731526b3059301306072a8648ce3d020106082a8648ce3d03010703420004028a5579ba09a58472730d582a49113977c2a4a10a97d63560f1613868f8c5383650eba7c53c52215913f78a85548baed61904a04d8dc5e959a37fb24c550e0c300a06082a8648ce3d040302034700304402206716349c05cbc446578b8cc0aee4d6f124a90db1afe04219174df0e66eaf93de022055acdbb15750bd9825b9cf672584315a5cd74fd8ba7fec2050ac7428261b8f70'
      },
      24(<<
        {
          "version": "1.0",
          "digestAlgorithm": "SHA-256",
          "valueDigests": {
            "org.iso.18013.5.1": {
              1: h'ab92f0509e09cbc333066011eceeb95bfe0d8b14a5dca9269f5a6c9aea1c0997',
              2: h'bbb0fedefafe36b2e0df38a0ba753310a16a600c86e6c03e7dfbe60e3471676e',
              3: h'b63819e1a19161a84eecf0f45f75e8fcb797eba7e1e017fd97e2a32dcef118e8',
              4: h'117fae5f77551db5ba69087523225aa1664f9271b349f71f9496a275ab2680eb',
              5: h'283bd5c8c537e7c2ded27e939156f673405b85b48c270a6cc2d3cb36266b4d1f',
              6: h'056732700269c2ed070c430abbd850d09663f1934e37e1c65b87afebb7555a81',
              7: h'7c011d0dfeb153ed728f9171486e618aba8a2bee8e36322664016d0fce761143',
              8: h'7234f61d8824a319f058ffbd8ea3bfebe0fe77af47f545b6c63a435ab92796f0'
            }
          },
          "docType": "org.iso.18013.5.1.mDL",
          "validityInfo": {
            "signed": 0("2024-01-12T00:10:05Z"),
            "validFrom": 0("2024-01-12T00:10:05Z"),
            "validUntil": 0("2025-01-12T00:10:05Z")
          }
        }
      >>),
      h'717311bd3d345c85963e77dc513fd41f48dab92ef742b9d9aafae087750b23945d65f384835e55fa0953571fc60093d825f5dfaf5c19dfd34314a3855c7c6e96'
    ]
  }
}
```

シンタックスハイライトすると次のようになります。

![mdoc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/55134701-6234-8346-e324-94e27507f69f.png)

デモは以上です。

# 実装実験

ヨーロッパでは次のようなコンソーシアム群が作られ、デジタルアイデンティティウォレットに関する大規模な実験 (Large Scale Pilot) が行われています。

- [Potential](https://www.digital-identity-wallet.eu/)
- [NOBID Consortium](https://www.nobidconsortium.com/)
- [EU Digital Identity Wallet Consortium](https://eudiwalletconsortium.org/)
- [Digital Credentials For Europe](https://www.dc4eu.eu/)

[OpenID Foundation](https://openid.net/) の枠内では [GAIN POC Community Group](https://openid.net/cg/gain-poc/) が OID4VCI の実験を行っています。私の会社 ([Authlete 社](https://www.authlete.com/ja/)) も GAIN POC に参加し、クレデンシャルイシュアの実装を提供しています。

日本では、[Trusted Web 推進協議会](https://www.kantei.go.jp/jp/singi/digitalmarket/trusted_web/index.html)の旗振りの元、幾つかの実証実験が OID4VCI などの Verifiable Credential 関連標準仕様の実装を進めています。

# OID4VCI 仕様詳細解説

Authlete 社のウェブサイト上に OID4VCI 仕様の詳細解説を載せているので、是非ご参照ください。おそらく、今後これより詳しい解説文書は世に出てこないと思います。

- 日本語: [OpenID for Verifiable Credential Issuance](https://www.authlete.com/ja/developers/oid4vci/)
- 英語: [OpenID for Verifiable Credential Issuance](https://www.authlete.com/developers/oid4vci/)

# おわりに

2023 年末の怒涛の仕様変更ラッシュ <font color="#999999">(おかげで年末年始も休まずコーディング (なお例年通り))</font> 、オプショナル機能の一括 VC 発行、SD-JWT VC の新規性、mdoc/mDL 技術文書の有償性 <font color="#999999">(ISO 文書は購入しないと読めない)</font>、GAIN POC 参加者の実装進捗状況を見るに、おそらく、一括クレデンシャルリクエストで SD-JWT VC と mdoc/mDL の同時発行に成功した例は、これが世界初だと思います:v:。

そんな感じで Verifiable Credential 関連仕様群の実装に鋭意取り組んでいたところ、4 月 9 日にイタリアのローマで開催される『**[2nd International Workshop on Trends in Digital Identity](https://st.fbk.eu/events/TDI2024/)**』(**TDI 2024**) というイベントに講演者として招待され、実装経験で得られた知見について何か話すことになりました。

![tdi2024.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/9b49dfe3-6026-593a-21b5-30c4534fc69d.jpeg)

TDI 2024 の翌日からの三日間 (4 月 10 日 〜 12 日) は、同じ場所で **[OAuth Security Workshop 2024](https://oauth.secworkshop.events/osw2024)** (**OSW 2024**) も開催されます。OSW オーガナイザーの [Daniel Fett 博士](https://www.linkedin.com/in/dr-fett/)が 2023 年 4 月から Authlete 社のメンバーになったこともあり、昨年の OSW 2023 に引き続き、今年も Authlete 社が OSW のメインスポンサーを務めます。

![osw2024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/b587c8c4-8e0a-f658-89f8-aef9390760d4.png)

Daniel が SD-JWT や SD-JWT VC の仕様を書き、Joseph が OpenWallet Foundation の取締役や Digital Credentials Protocols (DCP) Working Group の共同議長に就任するなど、気がつくと Authlete 社はデジタルアイデンティティウォレットや Verifiable Credential に深く関わるようになっていました。この分野にご興味のある方は、Authlete 社まで是非[お問い合わせ](https://www.authlete.com/ja/contact/)ください！ #PR 

# 余談

OpenID Summit Tokyo 2024 の会場につくと、自分の会社のロゴが大きく印刷されていて、「ありがたいけど、どうして？」、となりました。

|![openid_summit_tokyo_2024.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/9ab9e33b-2af2-483b-41cb-54db3004aea7.jpeg)|
|:-:|
| From https://twitter.com/kura_lab/status/1748136975327240407 by @kura_lab |

「Authlete 社が米国 OpenID Foundation に [Board Member](https://openid.net/foundation/board/) として納めたお金が活用されているからですよ」と教えてもらいました。言われてみればそんな話があったような気がしましたw！ そんなことでロゴを大きくしてくださるなんて、ありがとうございました！

OpenID Summit Tokyo 2024 参加者の皆様、運営の皆様、登壇者の皆様、お疲れ様でした＆ありがとうございました！