お断り: 本記事は C2PA Technical Specification v2.3(2026年4月時点)を筆者が読解して整理したものです。仕様は継続的に更新されており、細部の記述は変更される可能性があります。実装や設計判断の根拠として用いる際は、必ずC2PA 公式仕様をご確認ください。本記事に誤りや古くなった箇所を見つけられた場合は、記事末尾のフィードバック枠よりお知らせいただけると助かります。
はじめに
本記事は「C2PA 実装入門」シリーズの第2回です。第1回では「なぜ来歴証明が必要なのか」を整理しました。本記事では、C2PA が技術的にどう動くのかを一連のフローとして俯瞰します。
C2PA の仕様書(Section 2.1 Actors and Actions)では、以下の役割が定義されています。
- Claim generator: Claim を生成するハードウェアまたはソフトウェア(カメラ、編集ソフト、AI 生成ツールなど)
- Signer: Claim の署名に使う秘密鍵の保持者。Claim generator が Signer の鍵を使って署名する
- Manifest consumer: 来歴データを取得する目的で Manifest 付きアセットを消費する人やシステム
- Validator: Manifest consumer のうち、暗号署名やハッシュの検証を実行する役割
本記事ではこの役割分担に沿って、Claim generator / Signer 側がコンテンツに署名を付与し、Manifest consumer / Validator 側がそれを検証する、という一連のフローを追いかけます。
署名から検証までの全体フロー
C2PA におけるコンテンツのライフサイクルを1本のフローとして描くと、次のようになります。
以降、各ステップをもう少し掘り下げます。
ステップ 1-2: コンテンツ作成と Assertion の記録
コンテンツの作成と同時に、あるいは直後に、来歴に関する事実が Assertion として記録されます。
カメラでの撮影なら「撮影した」という事実が c2pa.actions 内のアクション c2pa.created として記録されます(撮影条件の EXIF は別の Assertion stds.exif として独立して格納されます)。Photoshop での編集なら「切り抜いた」(c2pa.cropped)「色調を変えた」(c2pa.adjustedColor)といった操作が c2pa.actions の中に並びます。プリディファインドのアクション名一覧は仕様書の Table 8 “List of pre-defined actions” にまとまっています。
重要なのは、各 Assertion は独立したドキュメントであり、「いつ・誰が・何をしたか」を細粒度で記録する設計になっているということです。なお、一度 Claim の一部になった Assertion は変更できません(仕様書に「they cannot be modified once made as part of a claim」と明記されています)。先行 Manifest の Assertion を取り除きたい場合は、Redaction という正式な手続きを通じて「何を消したか」の記録を残しながら行います。
ステップ 3: Claim の構築
作成された Assertion 群を「1つの署名単位」としてまとめるのが Claim です。仕様書の定義では “a digitally signed and tamper-evident data structure that references a set of assertions” とあり、Claim は Assertion の実データを直接含まず、代わりに各 Assertion への hashed URI(ハッシュ付き参照)のリストを保持します。CDDL スキーマ上もフィールドの型は $hashed-uri-map(URI + ハッシュ値の組)であり、Assertion そのものではありません。
Claim v2 では、このリストが created_assertions(署名者が責任を持つもの)と gathered_assertions(他の工程から引き継いだもの)の2系統に分かれています。これにより「署名者は何に責任を持っているのか」が構造的に明示されます。
ステップ 4: Claim への署名
Claim が構築されたら、署名者の秘密鍵を使って COSE_Sign1 形式で署名します。署名と一緒に、署名者の X.509 証明書チェーンも Claim Signature に含められます。
RFC 3161 準拠のタイムスタンプ局(TSA)から署名時刻の証明を取得して埋め込むことも仕様で想定されていて、「いつ署名されたか」を第三者が証明できるようになります。
署名者の証明書は C2PA Trust List に登録された認証局(CA)から発行されている必要があり、これが C2PA の信頼モデルの起点となります。信頼モデルの詳細は第3回の Claim Signature セクションで扱います。
ステップ 5: Manifest の埋め込み
Assertion Store(Assertion 群の入れ物)、Claim、Claim Signature の3つがそろったら、これらを JUMBF(JPEG Universal Metadata Box Format)というコンテナ形式にまとめ、コンテンツファイルの中に直接埋め込みます。
ファイル(JPEG / PNG / MP4 / PDF ...)
├── コンテンツ本体(画素データ、映像、音声等)
└── JUMBF メタデータ
└── Manifest Store
└── Manifest
├── Assertion Store
├── Claim
└── Claim Signature
メタデータとコンテンツが一体化するため、ファイルをコピーや転送しても来歴情報が維持されます。これは「来歴メタデータを外部サーバーに置く」方式と対照的で、ファイル単独で完結するのが C2PA の大きな特徴です。
各ファイルフォーマットごとの埋め込み方法(JPEG は APP11、PNG は専用チャンク、MP4 は ISO BMFF box など)は仕様で定義されています。
ステップ 6: 配信経路での注意点
署名済みコンテンツが SNS やメッセージアプリを経由して配信されるとき、メタデータが失われるリスクがあります。プラットフォームが画像を再エンコードしたり、メタデータを自動的に除去したりするためです。
この問題に対して C2PA は2つの対策を用意しています。
- Soft Binding: 知覚的ハッシュやデジタル透かしを使い、メタデータが剥がれても「元のコンテンツと同一である」ことを緩やかに紐づけておく仕組み
- Content Credentials Cloud: メタデータのコピーをクラウド上にも保持し、メタデータが失われたコンテンツをフィンガープリントで突き合わせて復元する仕組み
配信経路の設計は実運用上の大きな論点であり、第7回で詳しく扱います。
ステップ 7: 検証
受け取ったコンテンツの来歴を確認するのが検証ステップです。検証は大まかに次の順序で行われます。
- ファイルから JUMBF メタデータを取り出す
- Claim に列挙された hashed URI と Assertion Store のハッシュが一致するか確認
- コンテンツ本体のハッシュとハードバインディング Assertion の値が一致するか確認
- Claim Signature の暗号署名を検証
- 署名者の証明書チェーンが C2PA Trust List に適合しているか確認
- アプリケーション固有のポリシー判定(例: AI 生成は社内のみ許可)
ステップ 1〜5 は C2PA SDK(c2pa-rs、c2pa-node 等)が標準で対応しています。ステップ 6 はビジネスロジック側の責務であり、SDK の外で自前で実装する部分です。
検証の実装については第6回で SDK を使って実際にコードを書いていきます。
既存の Manifest がある素材を取り込むとき
コンテンツの編集ワークフローでは、「すでに C2PA 署名が付いた素材を読み込み、編集して、新しい Manifest 付きで書き出す」という場面がよくあります。
このとき、元素材の Manifest は Ingredient(素材)として新しい Manifest の中に参照として取り込まれます。これにより、最終的なコンテンツから遡って元素材の来歴まで辿ることができ、編集の連鎖を時系列で追跡できます。
写真 (Manifest A)
↓ Photoshop で編集
編集済み画像 (Manifest B, Ingredient: Manifest A)
↓ CMS に投稿
記事掲載画像 (Manifest C, Ingredient: Manifest B)
この「Manifest のチェーン」は Manifest Store の中に複数の Manifest が並ぶ形で表現されます。
SDK とツールの選択肢
C2PA の署名と検証を実装するためのオープンソースツールがいくつか公開されています。
| ツール | 言語 | 用途 |
|---|---|---|
| c2pa-rs | Rust | 参照実装。最も機能が充実 |
| c2patool | CLI | c2pa-rs ベースのコマンドラインツール |
| c2pa-node | Node.js | c2pa-rs の WASM / ネイティブバインディング |
| c2pa-python | Python | データパイプライン・AI ワークフロー向け |
このシリーズでは主に c2patool(第4回)と c2pa-rs(第5回以降)を使って実装を進めます。
まとめと次回予告
C2PA の署名から検証までのフローを整理しました。要点は3つです。
- 「事実の記録(Assertion)→ 束ねて署名(Claim + Signature)→ ファイルに埋め込み(JUMBF)→ 検証」という一方向の流れ
- メタデータとコンテンツがファイル内で一体化するので、ファイル単独で来歴が完結する
- 検証のうち暗号処理は SDK がやってくれるが、ポリシー判定は自前で設計する
次回の第3回 Manifest の内部構造を理解するでは、このフローの中心にある Manifest の中を分解し、Assertion・Claim・Claim Signature・JUMBF の4レイヤーがそれぞれどんな役割を担っているかを詳しく見ていきます。
参考リンク
TechThanks は Content Credentials の実装支援に取り組んでいます。コンテンツ来歴技術の導入検討やワークフロー設計について、お気軽にご相談ください。