open-standards/wai/live-conformance/c2pa-live/README.md

5.9 KiB

live-conformance/c2pa-live — live provenance

The corpus of extensions/live-provenance.md §13: C2PA 2.4 §19 live video streams, each an initialization segment and its segments in the order a verifier receives them, with, for a room track, the JWP group and object receipts of its groups; the trust anchor every vector is verified under; and what a verifier states of each.

Files. vectors.json lists the vectors, each its name, kind (track or take), init, segments (each a file and, for a track, the group it came in), receipts (a JSON file of groups and objects in jwp-receipts §2.4's forms, or null for a take) and expect. A file whose bytes another vector already wrote is named by that vector's path, so a negative that changes one segment holds one file of its own. anchor.der is the trust anchor for c2pa-kp-claimSigning, and time the instant T (§11.1).

Equivalence. A conforming verifier given a vector's files, the anchor and T reaches the outcome expect states (§11):

  • refuse: the reason of §12, at (init, segment k counting received segments from 0, or group g), and the two C2PA codes §12 gives the reason, c2pa (§15's) and livevideo (§19.7's), each null where §12 gives none;
  • accept: the streamId, the sourceType, the registration (the repository, the treeSize and the leafIndex of the receipt of inclusion) or null, and for each segment (§11.6) its sequenceNumber, its group (a track) or chunk (a take), its methods (manifest, vsi or manifest+vsi), the active manifestId, its number of chunks, and its group's root or its take chunk's chunkHash, in lowercase hexadecimal.

The vectors.

  • Good: camera-manifests (the per-segment method), camera-vsi (the Verifiable Segment Info method from group 10, the session key rotated at the third segment by a manifest in it, the receipts' chain restarting under the new key), avatar-manifests (a track labelled machine-made, with its AI disclosure), composite-manifests (a compositor's output of the camera and the avatar: compositeSynthetic and the avatar's disclosure), take-both (a take under both methods at once, the device's key as its session key), camera-failover (the camera track, a second packager under its own claim signer taking over at the third segment, the continuity chain holding across it because the identifiers are derived) and camera-registered (the camera track's initialization segment with its update manifest and repository receipt; repositories in vectors.json names the repository and its key).
  • One negative for each reason of §12, and for some reasons more than one; each name says its defect.

Provenance. wai_live_provenance_vectors gen writes every file but this one from fixed seeds: every key is SHA-256 of a label and no key is one anyone holds; the certificates are issued under the corpus's own test anchor; the media are the AV1 floor of pack-conformance/packs/video-base-01, its samples cut into chunks of at most 15 frames, each group one of the floor's pieces, renumbered and retimed across the stream.

Checked by. wai_live_provenance_vectors verify and tests/live_provenance.rs in wai-rs (every file regenerates byte for byte and no other is here; every vector gets its outcome; every reason refuses one; §12 lists the reference's codes), and ../c2pa_live_verify.py, the second implementation, written from the extension's text, which also requires every mutated copy of a good vector to be refused.

An independent C2PA validator. The corpus's files were also read with the C2PA command-line tool, version 0.27.22, given anchor.der as its trust anchor, on 2026-10-21:

  • every good vector's initialization segment validates: state Trusted, with assertion.bmffHash.match, assertion.hashedURI.match, claimSignature.validated, claimSignature.insideValidity and signingCredential.trusted. The manifest store, the claim, its signature, the certificate chain and the BMFF hash over the moov are therefore read the same way by an implementation that shares nothing with this one;
  • camera-registered/init.mp4 validates too, state Trusted, its active manifest the update manifest: the tool reads the ingredient (ingredient.manifest.validated) and its validation results. Before the ingredient carried them it reported assertion.ingredient.malformed, which C2PA 2.4 §18.16.12.4.3 requires; update-ingredient/init.mp4 is reported ingredient.manifest.mismatch, where this corpus states update_manifest_invalid; repository-receipt-forged/init.mp4 is reported Trusted: the receipt's proof is the repository's form (§18.27), which the tool does not check;
  • cert-untrusted/init.mp4 is reported signingCredential.untrusted, as here;
  • cert-expired/init.mp4 is reported signingCredential.expired, a code C2PA 2.4 does not list; §15.8 names this failure claimSignature.outsideValidity, which this corpus states;
  • cert-wrong-eku/init.mp4, whose end entity is valid for id-kp-timeStamping alone, is reported Trusted: the tool's default list of accepted extended key usages includes time-stamping and OCSP signing. C2PA 2.4 §14.5.1.1 makes a certificate valid for either of those purposes valid for no other, and §14.5.1.2 requires a claim signer's to hold an EKU of the validator's configuration, so this corpus refuses it credential_invalid;
  • the tool reads no media segment: a file that does not begin with ftyp is not one it opens, so it does not verify §19 per-segment manifests, segment-info maps or session keys. The segments are checked by the two implementations above alone.

The tool reports a claim signature as failed when the end-entity certificate's subject holds no organization name, which C2PA does not require; the corpus's names all hold one (§4.4).