1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright 2026 WritersLogic. All rights reserved.
// Licensed under the Apache License, Version 2.0 or the MIT license,
// at your option.
//! 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 exact `c2pa.hash.data` coverage,
//! 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`].
//!
//! [`c2pa-structured-text`]: https://crates.io/crates/c2pa-structured-text
//! [`c2pa-unstructured-text`]: https://crates.io/crates/c2pa-unstructured-text
pub use ;
pub use Error;