Expand description
C2PA manifest embedding, referencing, and hard binding for HTML documents.
Implements the Embedding Manifests into HTML section of the C2PA Technical
Specification: a C2PA Manifest Store carried inline as the Base64 content of
a <script type="application/c2pa"> element, or referenced externally by a
<link rel="c2pa-manifest"> element, both in the document head.
§Scope
- Association (
document): discover, embed, reference, and remove. - Hard binding (
hardbinding): the exactc2pa.hash.datacoverage, with compute and verify.
Signature verification, certificate trust, assertion validation, and resolution of an external manifest URI are not implemented here.
§Bytes, not text
The specification directs a validator to treat the document “as a series of
bytes (vs. text)”, so every entry point takes &[u8] and returns Vec<u8>.
A document in a legacy ASCII-compatible encoding scans correctly, and byte
offsets mean what the hard binding says they mean.
§Zero dependencies, no features
Discovery, embedding, Base64, SHA-2, and the binding algorithm are all in-crate. There is nothing to enable and nothing to pull in: the dependency list is empty in every configuration.
Hashing still goes through hardbinding::Hasher, with hardbinding::Sha2
as the built-in implementation. A caller with a reason to substitute — an
accelerated digest for a large asset, or one the host runtime already
provides — passes their own.
§Examples
Reference an external Manifest Store, which the specification prefers:
use c2pa_html::document;
let page = b"<html>\n<head>\n <title>Example</title>\n</head>\n<body></body>\n</html>";
let out = document::embed_reference(page, "https://fabrikam.example/m.c2pa").unwrap();
let manifest = document::extract(&out).unwrap();
assert_eq!(manifest.href(), Some("https://fabrikam.example/m.c2pa"));Or carry the Manifest Store inline:
use c2pa_html::document;
let page = b"<html>\n<head>\n <title>Example</title>\n</head>\n<body></body>\n</html>";
let out = document::embed(page, b"manifest-store-bytes").unwrap();
assert_eq!(
document::extract(&out).unwrap().store(),
Some(&b"manifest-store-bytes"[..])
);
// Removing the manifest restores the document byte for byte.
assert_eq!(document::remove(&out).unwrap(), page);Bind the document:
use c2pa_html::document;
use c2pa_html::hardbinding::{compute_data_hash, verify_data_hash, Algorithm, Sha2};
let page = b"<html>\n<head>\n <title>Example</title>\n</head>\n<body></body>\n</html>";
let out = document::embed(page, b"manifest-store-bytes").unwrap();
let binding = compute_data_hash(&out, Algorithm::Sha256, &Sha2).unwrap();
assert!(verify_data_hash(&out, &binding, &Sha2).is_ok());§Relationship to the text bindings
HTML is a file format, so its binding hashes stored bytes with no
normalization, and re-serializing the document invalidates it by design. The
text methods differ deliberately: A.9 structured text also hashes raw bytes
but has no element to exclude, and A.8 unstructured text normalizes to NFC
because clipboard-portable text may arrive in any normalization form. See
c2pa-structured-text and c2pa-unstructured-text.
Re-exports§
pub use document::embed;pub use document::embed_reference;pub use document::extract;pub use document::locate_all;pub use document::remove;pub use document::Manifest;pub use error::Error;
Modules§
- document
- Discovering, embedding, and removing a C2PA manifest association in an HTML document.
- error
- hardbinding
- The
c2pa.hash.datahard binding for HTML documents.