v0.3.0 — BMFF (MP4/MOV/HEIC/HEIF/AVIF) support
Backfilled release notes — the v0.3.0 tag was pushed 2026-08 without a GitHub release entry.
Adds BMFF containers (MP4, MOV, HEIC, HEIF, AVIF) to the pure-Go (no cgo) toolkit, alongside the existing JPEG and PNG support.
Added — BMFF Container
The manifest is read from the top-level C2PA uuid box: purpose-aware, merkle-offset tolerant, padding-trimmed. Read and Validate both accept it.
Added — c2pa.hash.bmff.v2 / .v3 hard-binding verification
Validate verifies the BMFF hard binding per spec §18.6: exclusion xpath / length / data / subset / version / flags predicates, then a single ascending pass hashing each non-excluded top-level box as an 8-byte big-endian offset marker plus its bytes minus exclusions.
New status codes: assertion.bmffHash.match, assertion.bmffHash.mismatch, assertion.bmffHash.malformed.
Changed
- BEHAVIOR CHANGE — a BMFF hard binding on a non-BMFF container is now
hardBinding.missinginstead of an informational "unsupported". The old status let a bmff-only manifest validate with nothing actually checked. - v1
c2pa.hash.bmffis ignored per spec §18.6.1; a manifest whose only binding is v1 reportshardBinding.missing. - Fragmented / Merkle BMFF assets are reported as informational unsupported.
- Ingredient manifests no longer run hard-binding checks against the active asset's bytes — their binding refers to the ingredient's original bytes, so the result is informational instead of a spurious mismatch.
- The COSE
x5chainlookup also accepts the pre-1.3 c2pa-rs text key"x5chain"in either header.
Tests
Fixtures from c2pa-rs (Apache-2.0 / MIT): a signed MP4 that serves as the hash oracle and validates end to end, its unsigned twin, and a v1-legacy MP4. Two new fuzz targets (FuzzBMFFParse, FuzzBMFFHash); FuzzRead / FuzzValidate extended to the new container.
Full changelog: v0.2.0...v0.3.0