Skip to content

fix(identity): resolve identity assertion references into ingredient claims - #2843

Open
mrappard wants to merge 1 commit into
contentauth:mainfrom
mrappard:fix/cawg-identity-ingredient-references
Open

mrappard wants to merge 1 commit into
contentauth:mainfrom
mrappard:fix/cawg-identity-ingredient-references

Conversation

@mrappard

Copy link
Copy Markdown
Contributor

Changes in this pull request

1. References into ingredient claims are rejected. When reading, SignerPayload::check_against_partial_claim checks referenced assertions only against the identity assertion's own claim. A reference to an assertion in an ingredient's claim is therefore reported as cawg.identity.assertion.mismatch. CAWG Identity Assertion 1.3 allows these references:

  • §5.1.1: each referenced assertion must appear "in the created_assertions, gathered_assertions … of the C2PA claim or any ingredient's claim."
  • §7.1 step 2 checks "the C2PA claim or any ingredient's claim (traced recursively)."

2. cawg.identity.hard_binding_incorrect is never reported. The hard-binding check only requires some hard-binding reference. §5.1.1 requires the reference to be the claim's own hard binding, and to not reference any other. §7.1 step 4 reports cawg.identity.hard_binding_incorrect otherwise.

Changes:

  • PartialClaim gets a crate-private list of ingredient-claim assertions. Manifest::from_store fills it with the assertions of the claim's ingredient claims, traced recursively, using absolute URIs (self#jumbf=/c2pa/<ingredient label>/c2pa.assertions/<label>).
  • check_against_partial_claim resolves a reference against the claim first, then against the ingredient claims by exact URI. The hash is compared as before.
  • A hard-binding reference that isn't in the claim itself is reported as cawg.identity.hard_binding_incorrect. This adds ValidationError::IncorrectHardBindingAssertion and validation_status::CAWG_IDENTITY_HARD_BINDING_INCORRECT. Adding a variant to ValidationError, which isn't #[non_exhaustive], is technically a breaking change for exhaustive matches.

Not changed: SignerPayload::check_against_manifest (used by IdentityAssertion::validate) and the Reader::post_validate path still build their partial claim from the claim alone.

Tests: two new fixtures, generated with mrappard/c2pa-rs-text-support cawg/conformance-fixtures. Both are CA.jpg with the CA.jpg ingredient and an X.509 identity assertion.

  • identity_assertion_may_reference_ingredient_claim uses validation_method/references_ingredient_assertion.jpg. Its identity assertion also references the ingredient manifest's c2pa.actions. The test checks that no cawg.* failure is reported.
  • identity_assertion_with_ingredient_hard_binding uses validation_method/hard_binding_incorrect.jpg. Its identity assertion references the ingredient manifest's c2pa.hash.data instead of its own. The test checks that the only cawg.* failure is cawg.identity.hard_binding_incorrect.

Both fail without the fix, and pass with OpenSSL and with rust_native_crypto. cargo test -p c2pa --lib --features file_io passes, and Clippy is clean.

Conformance results

Found with a CAWG identity assertion conformance suite I'm building; it's not public yet.

Checklist

  • This PR represents a single feature, fix, or change.
  • All applicable changes have been documented.
  • Any TO DO items (or similar) have been entered as GitHub issues and the link to that issue has been included in a comment. (No new TODO items.)

🤖 Generated with Claude Code

…claims

When reading, an identity assertion's referenced assertions were checked
only against its own claim. A reference to an assertion in an ingredient's
claim was reported as cawg.identity.assertion.mismatch, although CAWG
Identity Assertion 1.3 §5.1.1 allows references into "the C2PA claim or any
ingredient's claim" and §7.1 step 2 checks both.

Also, the hard-binding check only required some hard-binding reference, so
cawg.identity.hard_binding_incorrect (§7.1 step 4) was never reported for a
reference to a hard binding other than the claim's own.

Manifest decoding now adds the assertions of ingredient claims (traced
recursively, with absolute URIs) to PartialClaim, and
check_against_partial_claim resolves references against them. A
hard-binding reference that is not in the claim itself is reported as
cawg.identity.hard_binding_incorrect (new
ValidationError::IncorrectHardBindingAssertion and
validation_status::CAWG_IDENTITY_HARD_BINDING_INCORRECT).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant