Some checks failed
wai-audit collector and player integration / does this change touch it (push) Successful in 15s
joule-moq-web browser client / joule-moq-web · does this change touch it (push) Successful in 20s
joule-moq-remote host agent / joule-moq-remote · does this change touch it (push) Successful in 22s
wai-fleet service / does this change touch it (push) Successful in 20s
wai-sink-android native sink library / does this change touch it (push) Successful in 9s
WAI Studio / does this change touch it (push) Successful in 13s
wai-sink-swift native sink package / does this change touch it (push) Successful in 14s
wai-app and Create / wai-app · does this change touch it (push) Successful in 2m16s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 10s
WAI examples / WAI examples · does this change touch them (push) Successful in 8s
wai-quantum for JavaScript / does this change touch it (push) Successful in 3m41s
joule-moq-room room service / joule-moq-room · does this change touch it (push) Successful in 3m44s
wai-ledger service / does this change touch it (push) Successful in 3m44s
WAI operation catalogue / does this change touch it (push) Successful in 3m45s
wai-quantum studio and desktop / does this change touch it (push) Successful in 3m48s
joule-moq-http live HTTP egress / joule-moq-http · does this change touch it (push) Successful in 3m58s
wai-pack / wai-pack · does this change touch it (push) Successful in 3m53s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Successful in 1m39s
wai-audit collector and player integration / collector · linux (push) Successful in 3m21s
wai-fleet service / service · linux (push) Successful in 3m14s
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (push) Successful in 1m3s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Successful in 2m30s
wai-ledger service / service · linux (push) Successful in 2m37s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Successful in 7m31s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (push) Successful in 2m28s
wai-pack / wai-pack · linux (push) Successful in 5m27s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Successful in 4m26s
wai-quantum for JavaScript / javascript · linux (push) Successful in 10m50s
wai-quantum studio and desktop / studio · browser (push) Successful in 9m7s
WAI operation catalogue / the catalogue and every door · linux (push) Successful in 10m45s
wai-quantum studio and desktop / desktop app · linux (push) Successful in 9m41s
WAI Studio / Studio in WebKit · linux (push) Successful in 26m7s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Failing after 13m17s
WAI examples / WAI examples · portable · linux (push) Successful in 22m54s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (push) Successful in 2m0s
joule-moq-remote host agent / joule-moq-remote, every target (macos) (push) Successful in 52s
wai-fleet service / service · macos (push) Successful in 44s
joule-moq-http live HTTP egress / joule-moq-http, every target (push) Successful in 3m28s
wai-pack / wai-pack · linux-arm64 (push) Successful in 4m36s
wai-pack / wai-pack · the floor through a media prober (push) Successful in 1m49s
wai-pack / wai-pack · dependency licences (push) Successful in 2m5s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Successful in 9m44s
WAI Studio / Studio in Chromium and Firefox · macos (push) Successful in 10m57s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (push) Successful in 14m29s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Successful in 13m11s
joule-moq-room room service / joule-moq-room, every target (push) Successful in 10m22s
WAI examples / WAI examples · android-app · linux-arm64 (push) Successful in 11m25s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (push) Successful in 8m51s
wai-ledger service / service · macos (push) Successful in 1m8s
wai-pack / wai-pack · independent verifier (Python) (push) Successful in 21m13s
wai-pack / wai-pack · macos (push) Successful in 3m53s
wai-quantum studio and desktop / desktop app · macos (push) Successful in 5m53s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (push) Successful in 22m0s
wai-quantum studio and desktop / desktop app · windows (push) Successful in 13m39s
Every identity assertion WAI wrote was reported cawg.x509.signature.mismatch by the C2PA SDK's validator. Read at their sources: Identity Assertion 1.0 to 1.3 §8.2.1 (the payload is serialized in RFC 8949 §4.2.1's core deterministic encoding and those bytes are signed; no later version or erratum), and the c2pa crate at 0.91.7 and 0.91.11, its newest release, which signs and verifies its own serialization of the payload's members in the schema's order (referenced_assertions, sig_type, role; url, alg, hash) with the writer that keeps declaration order. The bytes signed were the whole difference: the COSE structure, protected header, sig_type, hashed URIs and chain of a WAI assertion and of one the SDK's builder writes are the same. c2pa-binding §4.10, §4.11, §6.2 step 12, §6.3, §9.2, §9.3 and decisions D6 (revised): a writer signs the schema's order by default and may be asked for the core deterministic encoding (identity::Signed); the stored assertion stays deterministic either way. The verifier accepts a signature over either serialization of the payload's members, states which, and refuses one over a third order, over other members, or by another key. On the SDK's path an identity assertion is read in any well-formed encoding (one the SDK's builder wrote is accepted) and a map with a key twice is refused. Tests run the SDK's validator, configured with the corpora's anchors, on manifests signed through the SDK and on the store writer's stores beside their envelopes: trusted, no failure code, cawg.x509.credential.trusted, cawg.x509.signature.validated and cawg.identity.well-formed for each identity assertion. The strict form gets exactly cawg.x509.signature.mismatch, pinned. c2pa-sdk-identity/vectors.json pins the validator's report of every file at the SDK's version. Both corpora regenerated with their tools (c2pa-identity byte for byte on x86_64 and aarch64); new vectors for the strict form, the SDK builder's assertion, a signature over a third order and over other members. Both Python verifiers compute the two serializations themselves and are caught without either and when they take the members in any order. The wire break and the three API changes are acknowledged in the change note. Co-Authored-By: Claude Fable 5.2 <[email protected]>
89 lines
6.9 KiB
Markdown
89 lines
6.9 KiB
Markdown
# live-conformance/c2pa-identity — trust lists, soft bindings, the ISCC soft binding and identifier, and identities
|
|
|
|
The corpus of [`extensions/c2pa-binding.md`](../../extensions/c2pa-binding.md) §9.2: C2PA Manifest
|
|
Stores beside stored WAI envelopes that carry, after the three assertions of §4.1, soft bindings of
|
|
`wai-mark:tent64` (§4.8), the ISCC soft binding `io.iscc.v0` and the ISCC identifier (§4.9) and
|
|
the Creator Assertions Working Group's
|
|
identity assertions (§4.10), verified against trust lists pinned by digest (§6.4); and what a
|
|
verifier states of each.
|
|
|
|
**Files.** `vectors.json` lists the vectors, each its `name`, `envelope`, `store`, `receipts` (as
|
|
in `c2pa-envelope/`), `claimLists` and `identityLists` (the trust lists its verifier is configured
|
|
with, each its `file`, the `uri` and `type` the verifier names it by, and the `digest` it pinned),
|
|
`robustness` (the robustness record and claims its verifier was given, in order) and `expect`.
|
|
`trust/` holds the lists in the form the C2PA Trust List is published in; `robustness/` the
|
|
record of `wai-mark:tent64` over the corpus's first two pictures, the claim of every attack it
|
|
shows survived, and a claim of one attack more; `objects/` the four envelopes, the receipts, and
|
|
for each envelope its first good store, as an origin serves them (a second good store over one
|
|
envelope is in its vector's own directory). A file another vector already wrote is named by that
|
|
vector's path. `anchors` is empty: every anchor comes from a list. `time` is the instant *T*.
|
|
|
|
**Equivalence.** A conforming verifier given a vector's files and *T* reaches the outcome
|
|
`expect` states (§6): for `refuse`, the `reason` of §7 and the code §7 gives it (`c2pa`, the
|
|
C2PA 2.4 code for §7.1's reasons and the Identity Assertion's for an identity's, `null` where §7
|
|
gives none); for `accept`, what §6.3 states, among it the `trustLists` that held the claim
|
|
signer's anchor, the `softBindings`, the `isccBinding` (its `alg`, its sequence in its canonical
|
|
form as `iscc`, and its `generator`), the `iscc` identifier in its canonical form and the
|
|
`identities` with the identity list that held each anchor.
|
|
|
|
**The vectors.**
|
|
|
|
- Good: `bound-full` (a soft binding, the ISCC identifier and the creator's identity over the hard
|
|
binding, the actions, the WAI assertion and the soft binding), `bound-two-identities` (the
|
|
publisher's identity referencing the creator's), `bound-identity-only` (the unmarked
|
|
picture's store with one identity), `bound-identity-deterministic` (the same store with the
|
|
identity signed over the payload's core deterministic encoding, the form a writer may ask
|
|
for; every other identity of the corpus is signed over the payload's members in the schema's
|
|
order, §4.10's default, and each accepted identity's `signed` says which), `bound-iscc-binding` (the first picture's store with its
|
|
watermark's soft binding, the ISCC soft binding, the identifier and the creator's identity over
|
|
the three assertions and both soft bindings), `bound-iscc-binding-only` (the unmarked picture's
|
|
store with the ISCC soft binding alone: an Image-Code, a Data-Code and an Instance-Code) and
|
|
`bound-featureless-picture` (a picture of one grey: the ISCC soft binding holds a Data-Code and
|
|
an Instance-Code and no Image-Code, and the identifier holds the featureless Image-Code).
|
|
- An identity's signature is refused (`identity_signature_mismatch`) when it is the creator's
|
|
under the publisher's certificates (`identity-credential-swapped`), over the payload's members
|
|
in a third order, which is neither serialization of §4.10 (`identity-signed-third-order`), or
|
|
over a payload with another role than the one the assertion holds
|
|
(`identity-signed-other-members`).
|
|
- One negative for each reason of §7.2, and three of §7.1's `credential_untrusted`: a signer under
|
|
an anchor no list holds, an anchor its list withdrew, and an anchor whose trust starts after
|
|
*T*; each name says its defect.
|
|
- The ISCC soft binding's negatives, `iscc-binding-*`: computed from another envelope; its
|
|
Data-Code the envelope's and its Instance-Code that of the envelope with one bit changed, which
|
|
iscc §5 would match and §6.2 step 11 refuses; a unit missing; units of 64 bits; a featureless
|
|
Image-Code included (`iscc_mismatch`, each); its sequence cut by a byte; its value the
|
|
sequence's text; no generator; a second ISCC binding; the ISCC binding before the watermark's
|
|
(`manifest_malformed`, each); and the watermark's robustness claim named as its own
|
|
(`soft_binding_unevidenced`).
|
|
|
|
**Provenance.** `wai_c2pa_identity_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 four test anchors; the lists are the corpus's own; the pictures are rings and
|
|
ramps the generator draws, two of them marked with `wai-mark:tent64`, and one picture of a single
|
|
grey, each written as PNG by the
|
|
packaging corpus's still writer, so each store states the source type `algorithmicMedia`. The
|
|
robustness record's table is the harness's (robustness-evidence §6), run over the two unmarked
|
|
pictures, and is reproduced by anyone who holds them.
|
|
|
|
**Checked by.** `wai_c2pa_identity_vectors verify` and `tests/c2pa_identity.rs` in `wai-rs`
|
|
(every file regenerates byte for byte and no other is here; every vector gets its outcome; every
|
|
reason of §7.2 refuses one), and `../c2pa_live_verify.py`, the second implementation, written from
|
|
the extension's text, which reads the lists and the identity assertions itself, detects the mark
|
|
with `_wai_mark.py`, verifies the robustness evidence with `robustness_verify.py` and recomputes
|
|
the ISCC units with `iscc_verify.py`, requires every mutated copy of a good vector to be refused,
|
|
and requires every one of its own checks, dropped, to be caught.
|
|
|
|
**Read by a C2PA SDK's validator.** Every good store here that carries an identity assertion is
|
|
given to a C2PA SDK's validator beside its envelope, with the certificates of the vector's trust
|
|
lists as its anchors for claim signers and for identity credentials, by the test
|
|
`the_sdks_validator_accepts_the_stores_the_store_writer_writes` of `c2pa_emit::identity_corpus`
|
|
(`wai-rs`, features `c2pa_emit,c2pa_envelope`; it runs in the conformance workflow's
|
|
`c2pa-emitter` job). Of each store whose identities are signed over the schema's order the
|
|
validator's state is trusted, it reports the claim signature validated, the data hash matched
|
|
and no failure code, and for each identity assertion `cawg.x509.credential.trusted`,
|
|
`cawg.x509.signature.validated` and `cawg.identity.well-formed`. Of
|
|
`bound-identity-deterministic` it reports `cawg.x509.signature.mismatch` and nothing else: that
|
|
validator does not verify the core deterministic encoding (c2pa-binding §4.10). It reads the
|
|
claim, the hard binding, the hashed URIs and the identity assertions; the soft bindings, the
|
|
ISCC assertions and WAI's own assertion it carries as assertions whose hashes it checks and
|
|
whose content it does not judge.
|