本記事は生成AIと共同で執筆しています。事実関係は可能な範囲で公式ドキュメント・一次情報と照合していますが、誤りが含まれている可能性があります。重要な判断を行う前にご自身でも一次情報をご確認ください。

デジタルアイデンティティとは何かW3C は Verifiable Credentials の何を決めていて、何を決めていないかの続きです。前 2 本で「形」は標準になっていること、「誰を発行者として信じるか」は規格の外に残ることを見ました。今回は保持者の側、つまりウォレットの役割と、その「信じるか」を実際に運用している例を見ます。

二つの「ウォレット」

同じ語が別のものを指しているので、資料を読むときに毎回の判別が要ります。

意味
決済ウォレット支払い手段・鍵の入れ物Apple Pay、PayPay、MetaMask
アイデンティティ・ウォレット属性証明の保持・提示EUDI Wallet、EDC の identity-hub、Microsoft Authenticator

Ocean Protocol(データ流通の実装)や、その上に構築された Pontus-X(データスペース。公開カタログを覗いた記録があります)が wallet と言うときは前者(EOA = Externally Owned Account、秘密鍵から導かれるアカウント)を指し、Gaia-X や EDC (Eclipse Dataspace Components) が言うときは後者を指しています。以下は後者の話です。

表に挙げた EUDI Wallet (European Digital Identity Wallet) は、EU が加盟国に対して市民や居住者への提供を求めているデジタル身分証アプリで、2024 年 4 月の規則 (EU) 2024/1183(通称 eIDAS 2.0)が根拠になっています。EDC の identity-hub は、個人ではなく組織のサーバ側で資格情報を保持する実装です。同じ「ウォレット」でも、想定している持ち主が個人か組織かで作りが変わります。

ウォレットが担う 4 つの機能

アイデンティティ・ウォレットが担う 4 つの機能と、それが無いときに起きることを 4 行で対比した図。① 鍵の保護 (秘密鍵を外に出さず署名操作だけ提供する) が無いと、鍵ファイルを複製した相手がそのまま本人として振る舞える。② 保管 (複数の発行者からの資格情報を手元に貯める) が無いと、毎回発行者に取りに行くことになり、発行者が提示先を把握する。③ 選択的提示 (相手の要求に合うものだけを選んで出す) が無いと、生年月日を出さずに「18 歳以上」だけを示すことができない。④ Holder binding (いま提示しているのが本人だと自分の鍵で示す) が無いと、資格情報を拾った第三者がそのまま提示して通ってしまう。最下部に「①〜③ は既製のアプリを使わなくても実装できるが、④ は検証者との往復が要る」と記されている。

ウォレットという名前のアプリを使うかどうかではなく、この 4 つを誰かが担っているかどうかが問題になります。

ここで言う手元の検証環境は、Gaia-X Lab の Compliance Service (2.12.0) を Docker で動かし、自分で書いた自己記述を提出して適合性証明を受け取り、その提示を Ocean Node のダウンロード認可の条件に差し込んだものです。構成と組み立ての経緯は許可リストに載っている本人が、ダウンロードできない ── Gaia-X の適合性証明を Ocean の認可に差し込むに書きました。この環境では、資格情報を提出するスクリプトが鍵を読み、参加者の自己記述・利用規約への同意・法人番号の 3 通を 1 つの提示物 (VP、Verifiable Presentation) に束ねて署名しています。②の保管と、複数の資格情報をまとめて出す部分に相当する動作はここで行っていますが、①の「鍵を外に出さない」という意味での保護には達しておらず、秘密鍵はファイルとして置いてあります。③についても、相手の要求に応じて選ぶのではなく、決め打ちの 3 通を束ねているだけです。

const key = await importPKCS8(readFileSync(join(root, 'certs', 'key.pem'), 'utf8'), ALG)
// …
const vpJwt = await new SignJWT(vp)
  .setProtectedHeader({ alg: ALG, typ: 'vp+jwt', cty: 'vp', iss: DID, kid: KID })
  .sign(key)

埋まっていないのが 4 つ目です。

4 つ目が無いと、何を判定していることになるか

手元のポリシーサーバには、次のように書いてあります。

本来これは提示者が鍵で署名した所有証明(VP の holder binding、あるいはウォレット署名)で示すべきものである。ここではローカル検証のため、DID と実行主体のアドレスの対応表を外から与えている。

対応表を外から与えているので、この構成では「適合性証明という文字列を持っている者」なら誰でも通ります。VC-JWT は bearer token、つまり持っていること自体が権利になる形式(乗車券に近い性質)なので、ログや通信路やブラウザの拡張機能から一度写しが漏れれば、拾った第三者がそのまま提示できます。署名は正しく、有効期限も切れていないため、検証者の側からは正規の提示と区別がつきません。

提示物を第三者に拾われたときに検証者が止められるかどうかを、2 つの列で対比した図。左列は Holder binding が無い場合 (筆者の手元の構成)。本人が VP-JWT を提示する → ログや通信路から第三者が写しを得る → 第三者がそのまま同じ文字列を提示する → 検証者は通す (署名は正しく、有効期限も切れていないため) と進み、✗ 印がついている。右列は Holder binding がある場合。検証者がその場限りの値 (nonce) を出す → 本人が nonce を含めて自分の鍵で署名する → 第三者は過去の提示物しか持っていない → 検証者は止める (今回の nonce に対する署名が作れないため) と進み、✓ 印がついている。最下部に「④ が無い間は、認可の条件が『誰であるか』ではなく『その文字列を持っているか』のままになる」と記されている。

標準的な解き方は次の流れです。

  1. 発行者が資格情報の credentialSubject.id (DID = Decentralized Identifier、分散識別子) を保持者のものにする(手元では、前の記事で開いたとおり発行者側の URL が入っています)
  2. 検証者が nonce(毎回変わる使い捨ての値)と audience(提示先を示す識別子)を出す
  3. 保持者が提示物に nonce と audience を入れて、自分の鍵で署名して返す
  4. 検証者が「提示物の署名鍵」と「資格情報の subject の DID に結びついた鍵」が一致することを確かめる

要点は 2 と 3 で、検証者が毎回違う値を出し、それに対する署名を求めるところにあります。過去の提示物を拾っただけの第三者は、今回の nonce に対する署名を作れないので通りません。audience を含めるのは、ある検証者に出した提示物を別の検証者に転送されることを防ぐためです。

手元では発行者と保持者が同じ鍵になっているので、そこを分けるのが素直な直し方です。ただし後述するように、既存の機構を使うもう 1 つの経路もあります。

トラストアンカーとは何か

前の記事で「誰を発行者として信じるかは規格の外」と書きました。この「信じる」の実体が、トラストアンカー (trust anchor) と呼ばれるものです。定義としては、検証の連鎖をたどっていった先の出発点、つまり「それ以上さかのぼらずに信じると決めて、事前に手元へ置いておく鍵や証明書」を指します。

抽象的なので、学認 (GakuNin、学術認証フェデレーション。国立情報学研究所 (NII) の事業として学術認証運営委員会が運営) の運用を見ると分かりやすくなります。学認は SAML (Security Assertion Markup Language) という規格に基づく大学間の認証連携で、実装には Shibboleth がよく使われています。この方式では、参加するサーバどうしが互いの接続先 URL と署名鍵を知っている必要があり、その情報を記述したものをメタデータと呼びます。SAML とメタデータの中身については学認のメタデータを開いて読むで、実データを見ながら別に書きました。

学認では、参加する各機関の IdP / SP のメタデータを 1 つの XML にまとめ、学認が 1 本の鍵で署名して配信しています。各参加サーバは、その署名者証明書をあらかじめ手元に置いておき、署名が検証できた場合にだけ名簿を読み込みます。つまり、数百件のエンティティを個別に信頼するのではなく、名簿に署名する 1 本の鍵だけを信頼すれば済む形にしてあります。

実際に取得してみます。

curl -s -o gakunin.xml https://metadata.gakunin.nii.ac.jp/gakunin-metadata.xml
python3 -c '
import xml.etree.ElementTree as ET
MD = "{urn:oasis:names:tc:SAML:2.0:metadata}"
r = ET.parse("gakunin.xml").getroot()
ents = r.findall(MD + "EntityDescriptor")
idp = [e for e in ents if e.find(MD + "IDPSSODescriptor") is not None]
sp = [e for e in ents if e.find(MD + "SPSSODescriptor") is not None]
print(r.get("Name"), len(ents), len(idp), len(sp), r.get("validUntil"))
'
GakuNin 650 419 231 2026-08-24T14:00:00Z

2026-08-12 時点で 650 エンティティ(IdP 419、SP 231)、ファイルは 5,655,173 バイト(約 5.7 MB)で、この名簿自体の有効期限は 2026-08-24 でした。期限があるので、参加サーバは定期的に取り直します。

署名者の証明書は XML の署名部分に埋め込まれています。

python3 -c '
import re, base64
d = open("gakunin.xml", encoding="utf-8").read()
m = re.search(r"<ds:X509Certificate>([^<]+)</ds:X509Certificate>", d)
open("signer.der", "wb").write(base64.b64decode("".join(m.group(1).split())))
'
openssl x509 -inform DER -in signer.der -noout -subject -issuer -dates
subject= /C=JP/O=GakuNin - Japanese Academic Access Management Federation/CN=GakuNin Metadata Signer - G2
issuer= /C=JP/O=GakuNin - Japanese Academic Access Management Federation/CN=GakuNin Metadata Signer - G2
notBefore=Nov 14 07:04:41 2017 GMT
notAfter=Nov 14 07:04:41 2027 GMT

出力は macOS 標準の LibreSSL のものです(Homebrew の OpenSSL 3 では subject=C=JP, O=…, CN=… の形式になりますが、値は同じです)。subject と issuer が同じ、つまり自己署名の証明書です。公的な認証局から辿れるわけではなく、「これを信じる」と各参加機関が決めて手元に置いている点が、まさにトラストアンカーの性質を表しています。有効期間は 2017 年から 2027 年までの 10 年です。

トラストアンカーの位置づけを学認の例で示した図。上段は、各大学の IdP / SP が接続先・鍵・属性方針を記述して提出し、NII が 1 つの XML に束ね (650 エンティティ、IdP 419 / SP 231)、1 本の鍵 (GakuNin Metadata Signer - G2) で署名する流れ。中段の左に「配信される名簿 metadata.gakunin.nii.ac.jp (約 5.7 MB)、有効期限 2026-08-24 まで。期限内に取り直す」、右に「この署名者証明書がトラストアンカー。各参加サーバが事前に手元へ置いておく。有効期間 2017-11-14 〜 2027-11-14 (自己署名)」があり、右から左へ「検証」の矢印が引かれている。下段に「名簿は毎回ネットワーク越しに取り直すが、それを信じてよいかの判断は手元の 1 つの鍵に還元されている (署名が検証できなければ、その名簿は読み込まない)」、さらに「Verifiable Credentials でも同じ構造が要る。『どの発行者 DID を信じるか』の一覧と、その一覧自体を誰がどう署名して配るか。この部分は W3C の仕様には含まれておらず、各エコシステムが個別に用意している」と記されている。

「学認に参加している」という状態は、この名簿に自分のエンティティが載り、かつ自分も署名者証明書を信じている、という双方向の関係になります。名簿そのものを信頼の対象にするのではなく、名簿に署名する鍵を信頼の対象にしているのが要点です。Verifiable Credentials でも同じ構造が要りますが、そこは仕様の外なので、エコシステムごとに用意されています。Gaia-X の場合はGaia-X Registry には何が入っているのかで実物を見ます。

学認とウォレット方式の構造差

学認(SAML / Shibboleth)ウォレット(Verifiable Credentials)
属性の流れIdP から直接 SP へIssuer → Holder → Verifier
IdP が提示先を知るか知る(毎回のログインを見る)知らない
属性の選択IdP の属性送出ポリシー(管理者が決める)利用者がウォレットで選ぶ
提示できる相手フェデレーション参加 SPフェデレーション外にも提示できる
オンライン性IdP が稼働していないと成立しない事前発行なので提示時に Issuer 不在でも成立
トラスト管理NII がメタデータを署名して集約(運用実績がある)Trust Anchor List を各エコシステムが個別に整備

最下段が要点です。Verifiable Credentials まわりで課題として挙げられることの多い「誰を信頼できる発行者とするか」を、学認は 2010 年度の本格運用開始以来 15 年を超える運用実績がある形で既に持っています。日本で VC 基盤を作るときに学認が土台になっているのは、この部分を引き継げるからだと読めます。

一方、学認の構造では扱いにくいものもあります。フェデレーション外の相手への提示、属性単位の選択的開示、そして IdP が閲覧履歴を把握する点です。

日本での実装例

在学資格証明を VC 化する実証が、デジタル庁の事業として 2026 年 3 月 2 日から 15 日まで実ユーザー参加で行われ、3 月 17 日に報告会が開かれています。構成は、学認の IdP を入口にして NII が開発した発行基盤が VC を発行し、利用者は Microsoft Authenticator で保持し、検証側が受け取る、という流れでした。

役割担当
全体取り纏め・実証受託者・検証側西日本旅客鉄道
デジタル資格証明発行基盤システム国立情報学研究所 (NII)
システム連携・在学資格発行・学生参加大和大学、京都女子大学、大阪大学、広島大学
在学資格の検証コシダカホールディングス
VC 実装支援・技術監修OpenID ファウンデーション・ジャパン
保持者のウォレットMicrosoft Authenticator(既製品)

大学側の接続形式が 3 種類用意されていた点も、既存の学内認証基盤の構成が大学ごとに異なることを前提にした設計だと読めます。

形式採用校
AP フロント形式(大学所有 IdP 型)大和大学
AP フロント形式(SaaS 型)広島大学、京都女子大学
IdP フロント形式大阪大学

holder binding をどう扱っていたか

この実証では、4 つ目の機能にあたる部分を、公開資料から読み取れる範囲では二経路の突合で扱っています。提示された在学証明 VC と、デジタル認証アプリ経由のマイナンバーカードによる本人確認を、その場で突き合わせて同一人物と判定する構成です(報告資料には「在学証明書・マイナンバーカードを突合し、学生認証を実施」とあり、暗号的な holder binding を併用しているかどうかまでは書かれていません)。

純粋な暗号的 holder binding ではありませんが、公開されている範囲では、既製のウォレットで暗号的な holder binding まで担保する構成が一般的ではない時期の実装として参考になります。事前に管理者が書く静的な対応表と違い、その場で 2 つの独立した経路から来た身元を突き合わせる構成なので、公開されている説明を読む限り、資格情報の写しを拾っただけでは通らない作りに見えます。

手元の構成に当てはめると、Ocean 側のウォレット署名(nonce に対する署名)を第二の経路として使えば、対応表を外部から与える必要がなくなります。既存の機構だけで済むので、次の一手としてはこちらのほうが現実的に見えます。

アーカイブのアクセス制御に当てはめる

以上を、筆者が実際に検討している、利用制限のかかった資料へのアクセス制御に当てはめてみます。調べた範囲では、現実的な順序は次のようになりそうです。

  1. 国内研究者の所属証明は学認で足ります。eduPersonScopedAffiliationfaculty@u-tokyo.ac.jp のように、役割と所属ドメインを組にした標準の属性)で「特定の大学の教員である」ことは既に証明できるので、VC を持ち出す必要は薄い
  2. VC が要るのは学認の外に出るときです。海外の研究者、フェデレーション非加盟の機関、市民アーキビスト、そして「所属」ではなく「倫理審査を通過している」「コミュニティの承認を得ている」のような、大学が発行しない資格
  3. 2 の後者では、証明を出す権威が大学でも行政でもなく当該コミュニティになります。技術は既存の実証がそのまま使える一方、そのコミュニティを発行者として承認する枠組みは、学認の名簿にも Gaia-X の名簿にも、現時点では区分が用意されていません

3 番目は、暗号や仕様からは出てこない部分です。

ここで関係してくるのが、NII と伊藤忠テクノソリューションズ (CTC) が 2024 年 10 月から 2026 年 3 月まで実施した、学術機関のデジタル資格証明の標準化に向けた共同研究です。学位・学修歴・学生証を対象に、学認のトラストフレームワークを参考にして、デジタル署名を検証できるアーキテクチャを検討する、という枠組みでした。トラストフレームワークというのは、誰が発行者になれるか、何を証明してよいか、規則に反したときにどう扱うかといった、技術仕様の外側にある取り決めの集まりです。学認は SAML を前提としたそれを既に持っているので、VC でも通用する形をそこから起こすことになります。

公表資料では、W3C の Verifiable Credentials と ISO/IEC 18013-5(運転免許証などをスマートフォンで提示するための国際規格。この形式を mdoc と呼びます)のどちらを採るかは未決とされ、課題として技術規格の分断、属性定義や多言語対応の不統一、正当な機関を認証する仕組みの不足が挙げられています。3 番目の課題は、ここまで見てきた「誰を発行者として信じるか」と同じ論点です。この共同研究は 2026 年 3 月で期間を終えているので、後続の枠組みが立ち上がる時期にあたります。アーカイブ側の要件を出すなら、このあたりという面はありそうです。

出典