Skip to content

Instantly share code, notes, and snippets.

@basilesimon
Last active April 1, 2025 15:58
Show Gist options
  • Save basilesimon/1ca32550ba6f105a3a133a744c34df30 to your computer and use it in GitHub Desktop.
Save basilesimon/1ca32550ba6f105a3a133a744c34df30 to your computer and use it in GitHub Desktop.
Chain of C2PA attestations

Stated Goal: Add photographer metadata to 1.JPG, then add a highlight metadata to the resulting 2.JPG. What will be contained in the resulting 3.JPG? Presumably, a store of all previous Assertions.

$ c2patool 1.JPG -m manifest-1.json -o 2.JPG
...
$ c2patool 2.JPG -m manifest-2.json -o 3.JPG
...
$ c2patool 3.JPG --tree
Tree View:
 Asset:3.JPG, Manifest:starling-me:urn:uuid:100d326b-3cf4-4aa3-a418-bdd4f5ca23e9
├── Assertion:my-c2pa-actions
└── Asset:2.JPG, Manifest:original-photographer:urn:uuid:3b8d4328-1d0d-411e-877e-ed7eefbd477a
    └── Assertion:stds.exif
{
"alg": "es256",
"private_key": "es256_private.key",
"sign_cert": "es256_certs.pem",
"vendor": "original-photographer",
"title": "Cool pub and cafe",
"caption": "View on Granary Square, London",
"assertions":
[
{
"label": "stds.exif",
"data":
{ "@context":
{ "EXIF": "http://ns.adobe.com/EXIF/1.0/"},
"EXIF:GPSLatitude": "51.5351435342179",
"EXIF:GPSLongitude": "-0.12433145875081522" },
"kind": "Json"
}
]
}
{
"alg": "es256",
"private_key": "es256_private.key",
"sign_cert": "es256_certs.pem",
"vendor": "starling-me",
"claim_generator": "integrity-something/0.1",
"assertions":
[{
"label": "my-c2pa-actions",
"data":{
"actions":[{
"changes": [{
"region":
[{ "type": "spatial",
"shape": {
"type": "rectangle",
"unit": "pixel",
"origin": {
"x": 10.0,
"y": 10.0 },
"width": 2000.0,
"height": 1100.0 }}],
"description": "Matched area for geolocation"
}]
}]
}
}]
}

The resulting manifest for 3.JPG does indeed contain everything + a bonus relationship between this photograph, and its parent.

{
  "active_manifest": "starling-me:urn:uuid:100d326b-3cf4-4aa3-a418-bdd4f5ca23e9",
  "manifests": {
    "original-photographer:urn:uuid:3b8d4328-1d0d-411e-877e-ed7eefbd477a": {
      "claim": {
        "claim_generator": "c2pa-rs/0.48.2",
        "claim_generator_info": [{...}],
        "signature": "self#jumbf=/c2pa/original-photographer:urn:uuid:3b8d4328-1d0d-411e-877e-ed7eefbd477a/c2pa.signature",
        "assertions": [...],
        "dc:format": "image/jpeg",
        "instanceID": "xmp:iid:6162448b-e8a0-4d76-a71e-02997334355f",
        "dc:title": "Cool pub and cafe",
        "alg": "sha256"
      },
      "assertion_store": {
        "c2pa.thumbnail.claim.jpeg": "<omitted> len = 184758",
        "stds.exif": {
          "@context": {
            "EXIF": "http://ns.adobe.com/EXIF/1.0/"
          },
          "EXIF:GPSLatitude": "51.5351435342179",
          "EXIF:GPSLongitude": "-0.12433145875081522"
        },
        "c2pa.hash.data": {
          "exclusions": [
            {
              "start": 65472,
              "length": 198529
            }
          ],...
        }
      },
      "signature": {
        "alg": "es256",
        "issuer": "C2PA Test Signing Cert"
      }
    },
    "starling-me:urn:uuid:100d326b-3cf4-4aa3-a418-bdd4f5ca23e9": {
      "claim": {
        "claim_generator": "c2pa-rs/0.48.2",
        "claim_generator_info": [...],
        "signature": "self#jumbf=/c2pa/starling-me:urn:uuid:100d326b-3cf4-4aa3-a418-bdd4f5ca23e9/c2pa.signature",
        "assertions": [...],
        "dc:format": "image/jpeg",
        "instanceID": "xmp:iid:0412780a-ea41-4aab-90ac-6be4a1fb897b",
        "dc:title": "3.JPG",
        "alg": "sha256"
      },
      "assertion_store": {
        "c2pa.ingredient.v2": {
          "dc:title": "2.JPG",
          "dc:format": "image/jpeg",
          "relationship": "parentOf",
          "instanceID": "xmp:iid:e7acd200-c0f7-4905-abe5-0fc84b5843c1",
          "c2pa_manifest": {
            "url": "self#jumbf=/c2pa/original-photographer:urn:uuid:3b8d4328-1d0d-411e-877e-ed7eefbd477a",
            "alg": "sha256",
            "hash": "OBOFubYRqjqlFkrdJaS3Q81oTGxho7e+wLmqf1D7sf0="
          },
          "thumbnail": {
            "url": "self#jumbf=/c2pa/original-photographer:urn:uuid:3b8d4328-1d0d-411e-877e-ed7eefbd477a/c2pa.assertions/c2pa.thumbnail.claim.jpeg",
            "hash": "W6YhuePN4W6c2j6QjFGSioQvKzEZQpKJaMICunJIjpo="
          }
        },
        "my-c2pa-actions": {
          "actions": [
            {
              "changes": [
                {
                  "region": [
                    {
                      "type": "spatial",
                      "shape": {
                        "type": "rectangle",
                        "unit": "pixel",
                        "width": 2000.0,
                        "height": 1100.0,
                        "origin": {
                          "x": 10.0,
                          "y": 10.0
                        }
                      }
                    }
                  ],
                  "description": "Matched area for geolocation"
                }
              ]
            }
          ]
        },
        ...
        }
      },
      "signature": {
        "alg": "es256",
        "issuer": "C2PA Test Signing Cert"
      }
    }
  },
  "validation_results": {
    "activeManifest": {
      "success": [...],
      "informational": [],
      "failure": []
    },
    "ingredientDeltas": [
      {
        "ingredientAssertionURI": "self#jumbf=/c2pa/original-photographer:urn:uuid:3b8d4328-1d0d-411e-877e-ed7eefbd477a",
        "validationDeltas": {
          "success": [...,
          "informational": [],
          "failure": []
        }
      },
      {
        "ingredientAssertionURI": "self#jumbf=/c2pa/starling-me:urn:uuid:100d326b-3cf4-4aa3-a418-bdd4f5ca23e9/c2pa.assertions/c2pa.ingredient.v2",
        "validationDeltas": {
          "success": [...],
          "informational": [],
          "failure": []
        }
      }
    ]
  },
  "validation_state": "Valid"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment