前章の検証は、何を言っていなかったか
第5章の判定は3値でした。valid / drifted / invalid。そこで valid が意味していたのは、正確には次のことだけです。
この証明書が名指した DID の鍵で、署名が検証できた。
「その DID を信じてよいか」は、一言も言っていません。
これは穴になります。攻撃者が自分の鍵で他人の資料に署名すれば、判定は堂々と valid になるからです。しかも did:key はホストも認証局も要らないので、誰でも1秒で「発行者」になれます。
第3章で「did:key はその鍵が誰のものか誰も保証しない」と書きました。それが検証の出力にどう現れるか、というのがこの章です。
名簿を1枚置く
対策は、技術的にはあっけないものです。受け入れてよい署名者の名簿を配ります。
{
"id": "https://nakamura196.github.io/did-log/trustlist.json",
"name": "Example trust list for cultural heritage issuers",
"maintainer": "(この試作では未定。名簿を誰が維持するかは技術では決まらない)",
"entries": [
{
"did": "did:web:nakamura196.github.io:did-log",
"name": "例示大学",
"notBefore": "2026-01-01T00:00:00Z",
"scope": ["https://nakamura196.github.io/did-log/iiif/genji/"]
},
{
"did": "did:key:zDnaerjYMognqPq2rcFG8HwbxHEdKWUjfHuNM6Tmb7ZwhN83K",
"name": "例示県立文書館",
"notBefore": "2019-04-01T00:00:00Z",
"notAfter": "2026-06-30T00:00:00Z",
"scope": ["https://nakamura196.github.io/did-log/iiif/genji/"]
},
{
"did": "did:key:zDnaeqxhJ1Kdk6gEWeWRL7ZQsNvbi5wzMyhVopJNFHGq67ucM",
"name": "例示美術館",
"notBefore": "2020-04-01T00:00:00Z",
"scope": ["https://nakamura196.github.io/did-log/iiif/ise/"]
}
]
}
1件は「いつからいつまで、どの範囲について、この DID の主張を受け入れるか」を表します。これも静的ファイル1枚で配れます。
そして判定に4つ目が加わります。
| 判定 | 意味 |
|---|---|
valid | 署名が通り、署名者が名簿にあり、内容も一致 |
drifted | 署名も署名者も通るが、別の版 |
untrusted | 署名は数学的に正しいが、署名者を信じる根拠がない |
invalid | 署名が通らない / 期限切れ / 失効 / 別の資料 |
4つ目は、前の3つとは性質が違います。
valid/drifted/invalidが「この文書はどうか」を言うのに対して、untrustedは「この署名者はどうか」を言う。 前者は手元の計算だけで決まるが、後者は名簿を誰が維持するかという制度に依存する。
名簿を渡さなければこの判定は行われず、従来どおりの3値に戻ります。
5つのケース
| ケース | 内容 | 名簿なし | 名簿あり |
|---|---|---|---|
| A | 所蔵機関が署名する | valid | valid |
| B | 第三者が他人の資料に署名する | valid | untrusted |
| C | 名簿から外れた機関の、外れる前の保証 | valid | valid |
| D | 同じ機関が、外れた後に署名する | valid | untrusted |
| E | 別の機関が他館の資料に署名する | valid | untrusted |
B が要点
[B] 第三者が他人の資料に署名する — did:key。ホストも CA も要らない
✔ 発行者の署名 did:key:zDnaeRCfNb5w1Bzn9UFhgB8g6E8tkr27ipEiEGXaDTE35Ln9U の鍵で検証OK
✔ 有効期限 (無期限)
✔ 失効リスト 該当なし
✔ 対象 URI の一致 https://…/iiif/genji/manifest.json
✔ 正規化方式の一致 sorted-keys-json
✘ 署名者の信用 名簿にない
名簿なし → valid 名簿あり → untrusted
上の5行がすべて ✔ であることに注目してください。 署名は数学的に完璧で、対象の URI も合っていて、正規化方式も一致しています。第5章までの検証は、これを valid と判定していました。
止めているのは暗号ではありません。名簿です。そして名簿は技術ではありません。
C と D の差 — 判定の基準時刻
同じ機関の、同じ形式の署名でも、結果が分かれます。
[C] 名簿から外れた機関の、外れる前の保証 — 2026-05-01 発行 / 名簿は 06-30 まで
✔ 署名者の信用 名簿にある — 例示県立文書館
✔ (注記) 発行時点では名簿にあったが、現在は外れている
名簿あり → valid
[D] 同じ機関が、外れた後に署名する — 2026-08-01 発行
✘ 署名者の信用 名簿の有効期間外 — 2026-06-30 に名簿から外れている
名簿あり → untrusted
判定を「いま」で行うか「発行時点」で行うかの違いです。
「いま」で判定すると、機関が統廃合された瞬間に、それまで出した保証が全部無効になります。長期保存を前提にする以上、これは採れません。だから発行時点で判定します。
代償があります。名簿から外す操作は遡及しません。 不正が後から分かっても、過去に出された保証は取り消せない。取り消したければ、失効リストという別の仕組みが要ります。名簿と失効リストが別々に必要なのは、この非対称性のためです。
E — 名簿にあるだけでは足りない
[E] 別の機関が他館の資料に署名する — 名簿にはあるが、範囲が自館のみ
✘ 署名者の信用 名簿の範囲外 —
例示美術館 は https://…/iiif/genji/manifest.json について語る権限を持たない
名簿あり → untrusted
名簿に載っていることと、何について語れるかは別です。A館が名簿にいるからといって、B館の資料の真正性を保証してよいことにはなりません。
この試作では名簿の各エントリに scope を持たせて、対象の範囲を書けるようにしました。
C2PA と ARCHANGEL が置いた場所
この穴は、この試作に固有のものではありません。
C2PA(Content Credentials、画像や動画の来歴を記録する規格)が同じ場所に置いたのは C2PA Trust List です。署名者に証明書を出す認証局をリストで配り、そこに繋がらない署名者は信用しない。中身は技術ではなく名簿です。
ただし C2PA の Trust List は認証局を載せるだけで、そこに「何について語れるか」は書かれていません。範囲にあたるものは別の名簿——Conforming Products List——の側にあり、たとえば「この製品は『カメラで撮影した』と主張してはならない」(disallowedSignals)が製品単位で書かれています。証明書の拡張鍵用途(EKU)でも用途は絞られます。
つまり C2PA に範囲の概念が無いのではありません。範囲が署名者名簿とは別の場所に分かれて置かれていて、検証者がそれを参照するかは仕様上 SHOULD 止まり、という形です。上の E に相当する区別は、名簿1枚を見ただけでは付きません。
逆に言えば、所蔵という制度は「誰が何を持っているか」が比較的はっきりしている世界なので、範囲を署名者名簿と同じ1枚に書き下せます。ここは文化資源の側が持っている、珍しく有利な条件です。
ARCHANGEL(英国国立公文書館とサリー大学ほか、2017–19)は、複数の国立公文書館が参加する permissioned chain(proof-of-authority)を使いました。各館が sealer node を運用して合意を取る形です。「permissioned」とは、参加者を事前に決めておく、という意味です。つまり 「どの公文書館を validator にするか」という名簿の問題が、チェーンの内側に入っているだけです。
これは「トラストアンカー」と呼ばれているもの
この名簿にあたるものは、一般に trust anchor(トラストアンカー) と呼ばれます。「信頼の起点」という意味で、そこから先は検証で辿れるが、そこ自体は検証できない点を指します。証明書の連鎖をどこまで遡っても、最後は「これは信じることにする」という一点に行き着きます。名簿は、その一点を明示的に書き出したものです。
実際の枠組みが誰を起点に置いているかを並べます。技術ではなく制度の話なので、枠組みごとにかなり違います。
Gaia-X
欧州のデータ基盤の枠組みです。トラストアンカーの一覧は Gaia-X Registry に置かれ、Gaia-X 側が維持します。
| 名簿を維持するのは | Gaia-X(どの種別を受け入れるかは Compliance Document で決め、実際の事業者一覧は Registry に置く) |
| 載っているのは | eIDAS の適格トラストサービス事業者(QTSP) ほか、認められた種別の事業者 |
| 何を保証するか | その事業者が発行した証明書は、参加者の身元確認を経ている |
eIDAS を起点にしているのが要点です。欧州には、加盟国政府が維持する信頼リストという制度が先にあり、Gaia-X はそれを借りています。第11章で「EU は既存の公開鍵基盤の上に組んでいる」と書くのは、この構造を指しています。
Pontus-X
Gaia-X 準拠のデータスペースの1つです。ここでは deltaDAO がトラストアンカーとして参加者を受け入れます。
| 名簿を維持するのは | deltaDAO |
| 載っているのは | 参加者クレデンシャルを発行された法人 |
| 載ると何ができるか | サービスの公開・利用、フェデレーションサービスの利用 |
未登録のアカウントは、そもそも動かすための通貨を受け取れません。 Faucet は「既知のアカウント」にしか配らないので、支払手段が手に入らず、計算資源の利用にも到達しません。加えてサービスの公開者は、消費者を絞る許可・拒否リストを個別に設定できます(既定では誰でも消費できる、と公式ドキュメントは書いています)。つまり名簿は表示上の飾りではなく、実行の可否を実質的に決めています。
3つを並べる
| 名簿を維持するのは | 載っているのは | |
|---|---|---|
| Gaia-X | Gaia-X(Registry) | eIDAS QTSP 等の事業者 |
| Pontus-X | deltaDAO | 参加者クレデンシャルを持つ法人 |
| C2PA | C2PA(Trust List / Conforming Products List)+各検証実装の設定 | 署名者に証明書を出す認証局(範囲は別名簿の側) |
| この試作 | 未定 | 例示大学 / 例示県立文書館 / 例示美術館 |
技術的にはどれも「名簿を1つ配る」だけです。 違うのは、その名簿を誰が持つかという一点で、そこが枠組みの性格をほぼ決めています。Gaia-X は政府の制度に寄りかかり、Pontus-X は特定の法人に集約し、C2PA は自前の名簿を持ちつつ参照するかを実装に委ねています。
そして文化資源の分野には、これに相当する主体がまだいません。
この試作が答えを出せない部分
docs/trustlist.json の maintainer 欄は空のままです。
誰が名簿を維持し、誰を入れ、誰を外すか。
これは技術では解けません。第4章で「チェーンが witness を務める」と書きましたが、チェーンを持ち込んでもこの問題だけは外れません。ARCHANGEL が permissioned chain で直面したのも、まったく同じものでした。
前節で見た Gaia-X も Pontus-X も、この問いに技術で答えてはいません。誰かが引き受けているだけです。第11章で「EU は既存の公開鍵基盤の上に組んでいる」と書きますが、その「既存」の中身は、暗号ではなくこの名簿を誰が維持するかという合意です。
前章の記述を訂正しておく
第5章では判定を3値と書きましたが、名簿を導入した時点で4値になります。そして valid の意味も変わります。
第5章の valid | この章以降の valid | |
|---|---|---|
| 署名が正しい | ✔ | ✔ |
| 内容が署名時と一致 | ✔ | ✔ |
| 署名者を信じる根拠がある | — | ✔ |
第5章の valid は「この文書は改竄されていない」しか言っていませんでした。誰が保証しているのかは、そこには入っていなかったわけです。