お断り: 本記事は C2PA Technical Specification v2.3(2026年4月時点)と c2pa-rs(コミット 0eeabc7のソースコードを筆者が読解して整理したものです。仕様は継続的に更新されており、細部の記述や用語は変更される可能性があります。実装や設計判断の根拠として用いる際は、必ずC2PA 公式仕様および関連する一次資料をご確認ください。本記事に誤りや古くなった箇所を見つけられた場合は、記事末尾のフィードバック枠よりお知らせいただけると助かります。

はじめに

C2PA(Coalition for Content Provenance and Authenticity)はコンテンツの来歴をメタデータとして埋め込む標準仕様です。SDK を呼ぶだけでも来歴情報の付与・検証はできますが、ファイルの中に何がどんな構造で書き込まれているかを掴んでおくと、検証ポリシーの設計やトラブルシューティング、独自ワークフローへの組み込みがぐっと楽になります。

本記事は「C2PA 実装入門」シリーズの第3回です。第1回で「なぜ来歴証明が必要なのか」、第2回で「署名から検証までの全体フロー」を押さえたうえで、ここからは Manifest の内部構造に踏み込みます。Assertion・Claim・Claim Signature・JUMBF コンテナという 4 つのレイヤーの役割と関係を、概念レベルで整理して理解しておきましょう。実際のファイルを c2patool で読み出して構造を確認するハンズオンは第4回で扱います。

登場人物と全体像

まずは概念レベルで、C2PA Manifest の内部にどのような要素が含まれているのかを整理します。

Manifest Store
└── Manifest
    ├── Assertion Store  (Assertion の実体の入れ物)
    │   ├── Assertion
    │   ├── Assertion
    │   └── ...
    ├── Claim            (Assertion への参照リスト+メタ情報)
    └── Claim Signature  (Claim に対する署名)

それぞれの要素の役割は、次のように整理できます。

  • Manifest Store: 1 つのアセットに紐付く Manifest 全体の入れ物。ファイル(JPEG・PNG・MP4・PDF など)に埋め込まれる最上位の構造。
  • Manifest: 1 回の「このコンテンツに対する来歴宣言」をひとまとめにした単位。時系列で複数の Manifest が連なることもあり、そのうち最後に有効なものが active_manifest として示されます。
  • Assertion: 「いつ・誰が・何をしたか」といった個別の事実。撮影・編集操作・AI 学習可否宣言・作成者の身元情報など、粒度の細かいドキュメントがそれぞれ 1 つの Assertion になります。実データは Assertion Store に入ります。
  • Claim: Assertion の実データは持たず、代わりに Assertion への参照(hashed URI)をリストアップしたメタ文書。「どの Assertion を 1 つの束とみなすか」を決める役割を持ちます。
  • Claim Signature: Claim に対する暗号署名と署名者の証明書チェーンを格納します。Claim 全体に対する信頼の起点となります。

仕様書においてこの全体像を 1 枚で俯瞰できる図として、C2PA Technical Specification v2.3 Chapter 12 “Entity Diagram”(Figure 11 “C2PA Entity Diagram”)が用意されています。Manifest Store・Manifest・Claim・Assertion・Signature の各要素と、それらがアセットや証明書チェーンとどう繋がっているかが網羅されているため、本記事の解説と対照しながら確認すると構造を理解しやすくなります。

C2PA Entity Diagram: Manifest Store・Manifest・Claim・Assertion・Signature とアセット・証明書チェーンの関係を示したクラス図
C2PA Technical Specification v2.3 Chapter 12「Entity Diagram」より Figure 11 "C2PA Entity Diagram"。一次資料はこちら

動画(BMFF)向けには 18.6.5 Fragmented BMFF Entity Diagram(Figure 15)という関連図も定義されています。

なぜこの4つのレイヤーに分けるのか

Manifest の内部は JUMBF コンテナ・Assertion・Claim・Claim Signature の 4 レイヤーに分かれていますが、この切り分けは単なる形式的な分類ではなく、C2PA が解決しようとする技術的課題の責務分担をそのまま反映したものです。それぞれの層が異なる問いに対応しています。

レイヤー担当する問い単位
JUMBF コンテナどうやってバイト列として運ぶか、どう addressing するか1つの「箱」(SuperBox)
Assertion何を主張するか個々の事実
Claimどの事実をひとまとめにして改ざん検知の対象範囲とするか1つの改ざん検知ユニット
Claim Signature誰がその塊を保証するか1つの署名行為

上から順に container / data / integrity / trust の 4 階層になっており、各層が上位・下位の関心事を分離する構造になっています。

  • JUMBF は ISO/IEC 19566-5 で標準化された汎用メタデータコンテナであり、C2PA 固有の技術ではありません。C2PA はバイト列の物理構造とアドレッシングを JUMBF に委ねることで、独自のファイル運搬形式を新規に策定することなく国際標準を活用しています。
  • Assertion は「個別の事実データ」であり、追加・差し替え・個別検証が Assertion 単位で可能です。AI で生成された事実、EXIF の撮影条件、元素材のハッシュなどが、それぞれ独立した Assertion として保持されます。
  • Claim は「どの Assertion 群をひとつの検証単位とするか」を定義するメタドキュメントであり、対象となる Assertion のハッシュ値を内部にリストアップします。Claim に対して 1 回署名を行うことで、リストに含まれるすべての Assertion の改ざん検知が暗号学的に成立します。
  • Claim Signature は「その Claim を誰が保証するか」の信頼性のみを担う層であり、署名値と署名者の証明書チェーンのみを保持します。この層が独立しているため、同一の Claim に対して別の主体が後から追認署名を行うような柔軟な運用も可能です。

このレイヤー分離は、たとえば「来歴情報(Assertion)だけを追加したい」「Claim の構造は変えずに署名鍵のみを更新したい」といった実運用上の要求において真価を発揮します。責務が明確に分離されていることで、各コンポーネントを部品単位で柔軟に設計・実装できます。

Assertion 個別の事実の積み上げ

Assertion は個別の事実を表す単位であり、それぞれが独立した CBOR/JSON ドキュメントとして Assertion Store に格納されます。代表的なラベルには次のようなものがあります。

  • c2pa.actions.v2 編集操作の履歴(一覧
  • c2pa.hash.data アセット本体のハッシュ(Hard Binding)
  • c2pa.thumbnail.claim 検証 UI 用のサムネイル
  • cawg.identity 作成者の身元情報(CAWG 拡張、Claim Signature とは独立した作成者署名を持つ)
  • cawg.training-mining AI 学習・推論での利用可否宣言
  • stds.exif / stds.iptc 撮影条件・メディアメタデータ

一度 Claim の一部に組み込まれた Assertion は事後的に改ざん・変更できません。プライバシー保護等の理由で過去の Assertion を取り除きたい場合は、Redaction という正式な仕様手順に則り、何を削除したかの記録を残した上で安全に処理します。

Claim Assertion を束ねて署名対象を作る

Claim は Manifest の中核となるメタ文書で、CBOR(Concise Binary Object Representation)形式でシリアライズされます。Claim が担う主な役割は次の 3 点です。

  1. Assertion Store に格納された個々の Assertion の内容を hashed URI でリストアップする
  2. 署名アルゴリズム、署名者情報、生成時刻などのメタデータを保持する
  3. アセット本体のハードバインディングを含めて、改ざん検知の対象範囲を確定する

Claim 自体が電子署名の直接の対象となるため、Claim 内部に対象 Assertion のハッシュ値を保持しておくことで、Claim を 1 回署名するだけで全 Assertion の改ざん検知が成立します。Merkle 木に類似した発想ですが、深さ 1 のシンプルな構造で目的を達成する効率的な設計となっています。

Claim v2 では、参照する Assertion のリストが created_assertions(署名者自身が責任を負うもの)と gathered_assertions(他の工程から引き継いだもの)の2 系統に明確に分かれています。この区別の実データについては、第4回c2patool の出力を通じて詳しく確認します。

Hard Binding と Soft Binding

C2PA Manifest がコンテンツ本体と正しく紐付いていることを保証する技術が Binding(結合)です。

Hard Binding は c2pa.hash.data などの Assertion を通じて、アセットのバイナリデータそのものの暗号学的ハッシュを Claim に取り込む方式です。アセットが 1 ビットでも改変されればハッシュ値が不一致となり、検証は即座に失敗します。極めて強固な保証が得られる一方、フォーマット変換や軽微な再エンコードでも検証が不合格となるため、配信経路で変換が生じるシステムでは適切な設計が求められます。

Soft Binding は知覚的ハッシュ(perceptual hash)や電子透かし(ウォーターマーク)を活用し、「同一の視覚・音響コンテンツである」ことを耐性高く紐付ける方式です。米国 NSA ら 4 機関による 2025 年 1 月の共同 CSI ガイダンスでも、Content Credentials の耐久性(Durability)を高めるために電子透かしやフィンガープリントとの併用が推奨されています。詳細はNSAら4機関がC2PA共同ガイダンスを公開 2025年1月CSIを読み解くを参照してください。

Claim Signature 信頼の起点

Claim Signature は COSE_Sign1(RFC 9052)形式で規定される署名構造であり、Claim の CBOR バイト列に対する電子署名と署名者の X.509 証明書チェーンを格納します。alg フィールドには C2PA で許可されている署名アルゴリズム識別子(Ps256, Es256, Ed25519 など)が記録され、生成時には RFC 3161 準拠のタイムスタンプ局(TSA)から取得した客観的な署名時刻情報も埋め込めます。

C2PA は一般的な Web PKI(Web サイト向け SSL/TLS 証明書体系)とは異なる独自の信頼モデルを採用しており、C2PA Trust List に登録された信頼できる認証局から発行された証明書がトラストの起点となります。検証側システムは証明書チェーンを Trust List に照合して検証し、Claim 署名が正当な発行元によって付与されたものであることを確認することで、Manifest 全体の真正性を保証します。

この仕組みにより「誰が署名したか」を確実に追跡できるとともに、万一の鍵漏洩時には失効リスト(CRL/OCSP)を通じて迅速に影響範囲を限定できます。また、CAWG の cawg.identity のように「作成者が自身の身元を Assertion 内で個別に署名する」仕様と組み合わせることで、パブリッシャー(配信責任者)とクリエイター(制作責任者)が異なる鍵を用いて信頼を重層的に形成する運用も可能です。

JUMBF Manifest を運ぶ箱

ここまで解説した Assertion、Claim、Claim Signature をバイト列としてメディアファイルへ物理的に埋め込むためのコンテナ規格が、JUMBF(JPEG Universal Metadata Box Format)です。C2PA は独自のファイル構造を策定する代わりに、ISO/IEC 19566-5 として標準化済みの JUMBF を全面的に採用しています(仕様書 Section 11.1 “Use of JUMBF”)。JUMBF は元来静止画向けに策定された規格ですが、C2PA では動画や音声、PDF などの多様なアセットに対応する汎用コンテナとして活用されています。

どのメディアフォーマットであっても JUMBF 内部のデータ構造(Manifest / Claim / Assertion のツリー構造)は完全に共通であり、異なるのは「各ファイルフォーマットのどの位置に JUMBF を格納するか」という点のみです。フォーマットごとの格納規則は仕様書の Appendix A “Embedding manifests” に定義されています。JUMBF 内部のボックス構造と URI アドレッシングの詳細については、第4回で実データを見ながら確認します。

まとめと続編

C2PA Manifest は、JUMBF というコンテナの上に Assertion・Claim・Claim Signature の 3 層を積み上げた論理的な構造を持っています。仕様書自体は網羅的で重厚に見えますが、本質は「個別の事実(Assertion)をハッシュ参照で束ね(Claim)、その束全体に電子署名を付与し(Claim Signature)、汎用ボックスで運搬する(JUMBF)」という明快なレイヤリングで成り立っており、エンジニアにとって非常に見通しのよい構造となっています。

この構造が実際のファイル内でどのように表現されているかを確認したい方は、続く第4回 c2patool で Manifest を覗いてみるにお進みください。c2pa-rs に付属するサンプル画像を対象に、c2patooljq を用いて JSON データを展開しながら内部構造を確認し、実運用における検証パイプライン設計の基礎を身につけていきます。

参考リンク


TechThanks は Content Credentials の実装支援に取り組んでいます。C2PA SDK の導入や検証パイプラインの設計についてお気軽にご相談ください。