AI画像って、どんなモデルで作ったか分かるの? Copilotの画像の署名を覗いてみたら意外だった

コトの発端は、ちょっとした素朴な疑問でした。

Microsoft CopilotからChatGPTを使って画像を生成したとき、ふと「この画像、実際に作ったモデルは何なんだろう🤔?」と思ったんですよね。 Copilotの裏で動いているのはChatGPTのはずだけれど、画像そのものを生成したのはどのモデルなのか。GPT-4oなのか、DALL-Eなのか、それともGPT-Image-2なのか。

画像を見ても、そんなことは表示されません。でも、もし画像に「これは何で作られたか」という情報が埋め込まれているなら、それを覗けば分かるんじゃないかと調べ始めたのが、今回の出発点です。

その手がかりになりそうだったのがC2PAでした。AI生成画像には、来歴を示す署名のようなものがこっそり埋め込まれていることがあります。今回は、その署名を「Webで確認する方法」と「Pythonで中身を覗く方法」の両方で実際に追いかけてみました。 先に言ってしまうと、答えは自分の予想と少し違っていました。

⚠️この記事の情報は2026年6月時点のものです。C2PAの仕様や各サービスの対応状況は更新が早いので、公式ドキュメントでご確認してください。

1. C2PAとは?

C2PAはCoalition for Content Provenance and Authenticityの略で、デジタルコンテンツの「出どころ」と「編集の履歴」を、改ざん検知できる形で記録するための業界標準とのことです。 Adobe、Microsoft、Arm、Intel、Truepicなどが立ち上げに関わっていて、最近ではNikonやCanonといったカメラメーカー、報道機関なども採用を進めています。

この記録を実際にファイルへ埋め込んだものがContent Credentials(コンテンツ来歴情報)というものです。AI画像生成サービス側が対応していると、「このソフトが」「いつ」「AIで生成した」といった情報が、画像に署名付きで添えられる、という仕組みになります。

2. 「透かし」とはちょっと違う機能

C2PAは「電子透かしのようなもの」と紹介されることがあるんですが、自分が調べた範囲では、本体はそれとは違うようです。

正確には、C2PAの中心は画像ファイルに埋め込まれた署名付きのメタデータ(マニフェスト)です。発行者の証明書(X.509)で署名されていて、画像の中身とハッシュで結びつけられています。だから、あとから画像やメタデータが書き換えられると署名の検証が失敗する。これが「改ざん検知できる」と言われる理由ですね。

では透かしは無関係かというとそうでもなく、メタデータはスクリーンショットやSNSへのアップロードで簡単に消えてしまうので、それを補うために「電子透かしを併用して、メタデータが剥がれても来歴を復元できるようにする」という仕組み(ソフトバインディング)も用意されているようです。つまり「透かし的」という言い方は、補助の層を指しているといえばそうなのかもしれません。本体は署名付きメタデータ、復元の保険として透かし、という整理がいいのかもしれません。

更に大事なのは、C2PAは画像のピクセルを解析してAI生成を見抜くものではないという点です。あくまで生成ソフトが「これはAIで作りました」と申告した内容を、署名付きで記録しているだけです。

3. まずはWebサービスで確認してみる

確認として手軽なのはWebサービスサイトです。ブラウザの中だけで処理が完結し、画像はサーバーにアップロードされません。手元の画像を気軽に試せます。

  • verify.contentauthenticity.org … Content Authenticity Initiativeの公式Verifyサイト。署名者や編集履歴を、一般の人にも読みやすい形で表示してくれます
  • c2paviewer.com … マニフェストの生JSONやアサーションの詳細まで見られる、開発者・研究者向けの表示。中身をしっかり確認したいときはこちら

verify.contentauthenticity.org

c2paviewer.com

使い方はどちらもシンプルで、画像をドラッグ&ドロップするだけです。

今回使用したサンプル画像(Microsoft Copilotで生成)

verify.contentauthenticity.orgでの表示

c2paviewer.comでの表示

表示でまず見るのは検証ステータスです。だいたい次の3パターンになります。

  • 有効(Valid) … 署名は正しく、署名後に改ざんされていない
  • データなし … C2PA情報が付いていない。来歴は確認できない
  • 無効/破損 … マニフェストはあるが署名検証に失敗。来歴は信頼できない

⚠️ 検証には生成されたオリジナルのファイルが必要です。スクリーンショットや、SNSで一度アップロードして保存し直した画像だと、メタデータが剥がれていて「データなし」になってしまいがちです。「途中で剥がれただけ」もあるということは覚えておきたいです。

4. Pythonで署名の中身を覗いてみる

Webで概要を見られるのは便利なんですが、自分は中で何が起きているのかも触ってみたい質なので、Pythonでも確認してみます。公式のc2pa-pythonを使います。署名の検証や読み取りだけなら証明書(秘密鍵)は不要で、ファイルを読むだけで済みます。

環境はいつものとおりuvで用意します(Python 3.10以上が必要です)。

$ mkdir C2PADisplay
$ cd  C2PADisplay
$ uv venv
$ source .venv/bin/activate
$ uv pip install c2pa-python

まずは最小のコードで、検証ステータスと署名者・使用ソフトだけを取り出してみます。

import c2pa
import json
import sys

# 引数チェック(ファイル名が無ければ使い方を表示)
if len(sys.argv) < 2:
    print(f"使い方: python {sys.argv[0]} <画像ファイル>")
    sys.exit(1)

path = sys.argv[1]

# マニフェストが無い場合は例外ではなく None が返る
reader = c2pa.Reader.try_create(path)

if reader is None:
    print(f"C2PAデータなし(来歴を検証できません): {path}")
    sys.exit(0)

try:
    print("検証ステータス:", reader.get_validation_state())

    store = json.loads(reader.json())
    m = store["manifests"][store["active_manifest"]]

    # 署名者(issuer)
    sig = m.get("signature_info") or {}
    print("署名者     :", sig.get("issuer") or "(不明)")

    # 使用ソフト(claim_generator)。新しい claim_generator_info も拾う
    gen = m.get("claim_generator")
    info = m.get("claim_generator_info")
    if not gen and info:
        # claim_generator_info は [{"name": ..., "version": ...}] 形式
        gen = ", ".join(
            f'{i.get("name","")} {i.get("version","")}'.strip() for i in info
        )
    print("使用ソフト :", gen or "(記載なし)")

    # 署名日時
    print("署名日時   :", sig.get("time") or "(時刻情報なし)")

    # 由来種別(digitalSourceType)と編集履歴(actions)を actions から抽出
    source_types = []
    history = []
    for a in m.get("assertions", []):
        if a.get("label", "").startswith("c2pa.actions"):
            for act in (a.get("data") or {}).get("actions", []):
                history.append(act.get("action", "?"))
                dst = act.get("digitalSourceType")
                if dst:
                    # URI の末尾コードだけ取り出す
                    source_types.append(dst.rstrip("/").split("/")[-1])

    print("由来種別   :", " / ".join(dict.fromkeys(source_types)) or "(記載なし)")
    print("編集履歴   :", " → ".join(history) or "(記載なし)")
finally:
    reader.close()

⚠️ C2PA情報が付いていない画像を渡すと、c2pa.Reader(...)は例外(ManifestNotFound)を投げます。「付いていない場合」も静かに扱いたいときは、例外の代わりにNoneを返してくれるtry_create()が便利です。

手元のテスト画像(AI生成扱いの署名入り)で動かすと、こんな出力が返ってきました。

Microsoft Copilotで生成した画像

$ python C2PADisplay.py sample1.png
検証ステータス: Valid
署名者     : Microsoft Corporation
使用ソフト : Microsoft_Responsible_AI/1.0
署名日時   : 2026-06-27T07:06:59+00:00
由来種別   : trainedAlgorithmicMedia
編集履歴   : c2pa.created

ChatGPTで生成した画像

$ python C2PADisplay.py sample3.png
検証ステータス: Valid
署名者     : OpenAI OpCo, LLC
使用ソフト : OpenAI Media Service API
署名日時   : 2026-06-27T07:33:30.393682+00:00
由来種別   : trainedAlgorithmicMedia
編集履歴   : c2pa.created → c2pa.converted → c2pa.watermarked.unbound

署名なしの画像で動かすと、こんな出力が返ってきます。

$ python C2PADisplay.py sample2.png
C2PAデータなし(来歴を検証できません): sample2.png

5. 署名から何が読み取れるのか?

reader.json()で取れるマニフェストには、けっこういろいろ入っています。自分が「これは見ておきたい」と思った項目を挙げると、次のあたりです。

  • 署名者(issuer) … 証明書に書かれた発行者。例としてAdobe、Googleといった組織名が入ります
  • 使用ソフト(claim_generator) … どのアプリ・モデルで作られたか
  • 署名日時 … いつ署名されたか
  • 由来種別(digitalSourceType) … 撮影なのか、AI生成なのか。algorithmicMediatrainedAlgorithmicMediaといったコードでAI生成を示します
  • 編集履歴(actions) … 作成→トリミング→色調整、といった工程の積み重ね

とくに最後の「由来種別」が、生成AI画像を見分けるうえでの肝になります。actionsアサーションの中のdigitalSourceTypeを読むと、AI由来かどうかが書かれているわけです。実際、Adobe FireflyやChatGPTの画像生成、GoogleのImagenなど、C2PA対応の生成AIで作った画像には、この申告が入るようになってきています。

由来種別やアクションまで含めて読みやすく整形するスクリプトも書いてみたんですが、長くなるので、それはまた別の記事で紹介しようと思います。ここでは「署名から、誰がどのソフトでAI生成したかまで読める」というところまで掴んでもらえれば十分です。

6. 発端の疑問に戻る

さて、冒頭の「Copilotで作った画像のモデルは何?」に立ち返ります。実際に署名を覗いてみると、自分の予想とは少しズレた答えが返ってきました😅

期待していたのは「DALL-E 3」や「GPT-4o image generation」といった、生成したモデル名そのものでした。ところが実際に署名を覗いてみると、出てくるのは責任を持って署名した「発行元」の名前のほうだったんです。 手元の2枚で試したところ、署名者(issuer)はこう出ました。

  • OpenAI で作った画像 … 署名者は OpenAI OpCo, LLC
  • Copilot 系で作った画像 … 署名者は Microsoft Corporation

「ChatGPTが作りました」「DALL-E 3が作りました」ではなく、「OpenAIが署名しました」「Microsoftが署名しました」という形で出てくる、というわけです。 Copilot(Microsoft)から ChatGPT(OpenAI)を使ったはずなのに、画像によって署名元がわかるようになると。

では内部のモデル名はまったく分からないのかというと、そこは生成側の裁量になります。C2PAの仕様では、アサーション(署名に含める個々の情報)はすべて任意で、必須のものは一つもありません。 実際、OpenAI の画像は使用ソフト(claim_generator)が空で、モデル名どころかソフト名すら出してくれませんでした。一方 Microsoft の画像には Microsoft_Responsible_AI/1.0 という名前が入っていましたが、これも「責任あるAIの枠組みで署名した」ことを示すだけで、GPT-4o や DALL-E といった具体的なモデル名ではありません。 「モデル名やバージョンが載っているか」は、その生成サービスが入れてくれているかどうか次第で「署名を見ればモデルが一発で分かるはず」という素朴な期待が叶わなかった理由でした。

考えてみれば、これは理にかなっています。C2PAは「中身を解析した結果」ではなく「誰が責任を持って署名したか」を示す仕組みなので、まず出てくるのが署名者の名前だ、というのは筋が通っていますね。 モデル名は、その署名者が「おまけ」として正直に書き添えてくれたら見える、くらいの距離感で捉えるのがちょうどよさそうです。

7. 注意したいこと(メディアリテラシーの観点)

最後に、C2PAは便利なんですが、万能の真偽判定機ではありません。使うときに踏まえておきたい前提が3つあります。

  1. C2PAが付いていない=偽物、ではありません … そもそも対応していないカメラやソフトで作った画像には付きませんし、付いていたものが途中で剥がれることも普通にあります。「無いから怪しい」と決めつけるのは早すぎます。
  2. C2PAはピクセルを解析していません … 生成ソフトが申告した内容を記録しているだけです。逆に言えば、対応ソフトが正直に「AIで作った」と記録してくれているからこそ価値がある、ということでもあります。
  3. 署名による改ざん検知はちゃんと効きます … 「Valid」と出れば、少なくとも署名後にその画像が書き換えられていないことは確認できる。これがC2PAの強みになります。

C2PAは「白黒をつける道具」ではなく「来歴を透明にする手がかり」です。AI生成という事実も含めて正直に記録する、という思想で作られています。この感覚を持っておくいいのかもしれません。

おわりに

今回は「Copilotで作った画像のモデルは何だろう?」という素朴な疑問から出発して、WebとPythonの両方でC2PA署名を覗いてみました。

たどり着いた答えは、期待していた「モデル名」そのものではなく、「誰が責任を持って署名したか」という形のものです。ですが、そっちのほうがむしろC2PAという仕組みの本質が分かったようにも見えます。 普段なんとなく見ているAI生成画像にも情報が含まれているのかと思うと面白いです。