Skip to main content

c2pa/
lib.rs

1// Copyright 2022 Adobe. All rights reserved.
2// This file is licensed to you under the Apache License,
3// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
4// or the MIT license (http://opensource.org/licenses/MIT),
5// at your option.
6
7// Unless required by applicable law or agreed to in writing,
8// this software is distributed on an "AS IS" BASIS, WITHOUT
9// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
10// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
11// specific language governing permissions and limitations under
12// each license.
13
14#![deny(clippy::expect_used)]
15#![deny(clippy::panic)]
16#![deny(clippy::unwrap_used)]
17#![cfg_attr(docsrs, feature(doc_cfg))]
18
19//! This library supports reading, creating, and embedding C2PA data
20//! for a variety of asset types.
21//!
22//! Some functionality requires you to enable specific crate features,
23//! as noted in the documentation.
24//!
25//! The library has a Builder/Reader API that focuses on simplicity
26//! and stream support.
27//!
28//! For more information, see [CAI open source SDK - Rust library](https://opensource.contentauthenticity.org/docs/rust-sdk/)
29//!
30//! # Examples
31//!
32//! ## Reading a manifest
33//!
34//! ```
35//! # use c2pa::Result;
36//! use c2pa::{assertions::Actions, Reader};
37//!
38//! # fn main() -> Result<()> {
39//! let stream = std::fs::File::open("tests/fixtures/C.jpg")?;
40//! let reader = Reader::from_stream("image/jpeg", stream)?;
41//! println!("{}", reader.json());
42//!
43//! if let Some(manifest) = reader.active_manifest() {
44//!     let actions: Actions = manifest.find_assertion(Actions::LABEL)?;
45//!     for action in actions.actions {
46//!         println!("{}\n", action.action());
47//!     }
48//! }
49//! # Ok(())
50//! # }
51//! ```
52//!
53//! ## Reading a manifest using Context, Settings, and trust list
54//!
55//! Download the official [C2PA trust list](https://opensource.contentauthenticity.org/docs/conformance/trust-lists) PEM and
56//! point `trust.trust_anchors` to its contents.
57//!
58//! ```no_run
59//! use c2pa::{settings::Settings, Context, Reader, Result};
60//!
61//! # fn main() -> Result<()> {
62//! #[cfg(feature = "file_io")]
63//! {
64//!     // Load the official C2PA trust list (PEM bundle) from a local file you downloaded.
65//!     let trust_pem = std::fs::read_to_string("path/to/C2PA-TRUST-LIST.pem")?;
66//!
67//!     // Build Settings enabling certificate trust verification against the C2PA trust anchors.
68//!     let settings = Settings::new().with_value("trust.trust_anchors", trust_pem)?;
69//!
70//!     // Create a Context with these settings and read an asset.
71//!     let context = Context::new().with_settings(settings)?;
72//!     let reader = Reader::from_context(context).with_file("path/to/asset.jpg")?;
73//!
74//!     println!("{}", reader.json());
75//! }
76//! # Ok(())
77//! # }
78//! ```
79//!
80//! ## Adding a signed manifest to a file
81//!
82//! ```
83//! # use c2pa::Result;
84//! use std::io::Cursor;
85//!
86//! use c2pa::{Builder, BuilderIntent, Context};
87//! use serde::Serialize;
88//! use serde_json::json;
89//!
90//! #[derive(Serialize)]
91//! struct Test {
92//!     my_tag: usize,
93//! }
94//!
95//! # fn main() -> Result<()> {
96//! // Create context with signer configuration.
97//! let context =
98//!     Context::new().with_settings(include_str!("../tests/fixtures/test_settings.toml"))?;
99//!
100//! // Build manifest.
101//! let mut builder = Builder::from_context(context)
102//!     .with_definition(json!({"title": "Test"}))?;
103//! // Use Edit intent so the parent ingredient is captured from the source stream.
104//! builder.set_intent(BuilderIntent::Edit);
105//! builder.add_assertion("org.contentauth.test", &Test { my_tag: 42 })?;
106//!
107//! // Save with automatic signer from context (created from settings).
108//! let mut source = std::fs::File::open("tests/fixtures/C.jpg")?;
109//! let mut dest = Cursor::new(Vec::new());
110//! let _c2pa_data = builder.save_to_stream("image/jpeg", &mut source, &mut dest)?;
111//! # Ok(())
112//! # }
113//! ```
114//!
115//! ## Adding an ingredient and signing
116//!
117//! ```
118//! # use c2pa::Result;
119//! use std::io::Cursor;
120//!
121//! use c2pa::{Builder, BuilderIntent, Context, DigitalSourceType};
122//! use serde_json::json;
123//!
124//! # fn main() -> Result<()> {
125//! // Create context with signer configuration.
126//! let context =
127//!     Context::new().with_settings(include_str!("../tests/fixtures/test_settings.toml"))?;
128//!
129//! // Build manifest.
130//! let mut builder = Builder::from_context(context)
131//!     .with_definition(json!({"title": "Created Asset"}))?;
132//! // Use Create intent with a source type and add a component ingredient.
133//! builder.set_intent(BuilderIntent::Create(DigitalSourceType::DigitalCapture));
134//!
135//! // Add an ingredient using Builder helper (no direct Ingredient struct).
136//! let ingredient_json = json!({
137//!     "title": "My ingredient",
138//!     "relationship": "componentOf"
139//! }).to_string();
140//! let mut ingredient = std::fs::File::open("tests/fixtures/sample1.png")?;
141//! builder.add_ingredient_from_stream(ingredient_json, "image/png", &mut ingredient)?;
142//!
143//! // Sign and embed using the context's signer.
144//! let mut source = std::fs::File::open("tests/fixtures/C.jpg")?;
145//! let mut dest = Cursor::new(Vec::new());
146//! let _c2pa_data = builder.save_to_stream("image/jpeg", &mut source, &mut dest)?;
147//! # Ok(())
148//! # }
149//! ```
150//!
151//! # Features
152//!
153//! The crate provides the following features:
154//!
155//! These features are enabled by default:
156//! - **default_http**: Enables default HTTP features for sync and async HTTP resolvers (`http_req`, `http_reqwest`, `http_wasi`, and `http_std`).
157//! - **openssl**: Use the vendored `openssl` implementation for cryptography.
158//!
159//! One of `openssl` or `rust_native_crypto` must be enabled.
160//! If both are enabled, `rust_native_crypto` is used.
161//!
162//! Other features:
163//! - **add_thumbnails**: Adds the [`image`](https://github.com/image-rs/image) crate to enable auto-generated thumbnails, if possible and enabled in settings.
164//! - **fetch_remote_manifests**: Fetches remote manifests over the network when no embedded manifest is present and that option is enabled in settings.
165//! - **file_io**: Enables APIs that use filesystem I/O.
166//! - **json_schema**: Adds the [`schemars`](https://github.com/GREsau/schemars) crate to derive JSON schemas for JSON-compatible structs.
167//! - **pdf**: Enables basic PDF read support.
168//! - **rust_native_crypto**: Use Rust native cryptography.
169//!
170//! ## HTTP features
171//! WARNING: These features are for advanced users.  Most people can ignore them.
172//! These features toggle compilation with different HTTP libraries, depending on the one you use.
173//! Some are async-only and others are sync-only.
174//! Disabling all of them will disable HTTP, speed up compilation, and decrease build size.
175//!
176//! - **http_ureq**: Enables `ureq` for sync HTTP requests.
177//! - **http_reqwest**: Enables `reqwest` for async HTTP requests.
178//! - **http_reqwest_blocking**: Enables the `blocking` feature of `reqwest` for sync HTTP requests.
179//! - **http_wasi**: Enables `wasi` for sync HTTP requests on WASI.
180//! - **http_wstd**: Enables `wstd` for async HTTP requests on WASI.
181//!
182//! ## WASM and WASI
183//!
184//! For WASM the only supported HTTP feature is `http_reqwest`. This means WASM
185//! only supports the async API for network requests.
186//!
187//! For WASI the only supported HTTP features are `http_wasi`, which enables sync network requests,
188//! and `http_wstd` which enables async network requests.
189
190/// The internal name of the C2PA SDK.
191pub const NAME: &str = "c2pa-rs";
192
193/// The version of this C2PA SDK.
194pub const VERSION: &str = env!("CARGO_PKG_VERSION");
195
196// Public modules
197/// The `assertions` module contains the definitions for the assertions that are part of the C2PA specification.
198pub mod assertions;
199
200/// The `cose_sign` module contains the definitions for the COSE signing algorithms.
201pub mod cose_sign;
202
203/// The `create_signer` module contains the definitions for the signers that are part of the C2PA specification.
204pub mod create_signer;
205
206/// Cryptography primitives.
207#[doc(hidden)]
208pub mod crypto;
209
210/// Dynamic assertions are a new feature that allows you to add assertions to a C2PA file as a part of the signing process.
211#[doc(hidden)]
212pub mod dynamic_assertion;
213
214/// The `http` module contains generic traits for configuring sync and async HTTP resolvers.
215pub mod http;
216
217/// The `identity` module provides support for the [CAWG identity assertion](https://cawg.io/identity).
218#[doc(hidden)]
219pub mod identity;
220
221/// The `jumbf_io` module contains the definitions for the JUMBF data in assets.
222pub mod jumbf_io;
223
224/// The settings module provides a way to configure the C2PA SDK.
225pub mod settings;
226
227/// Supports status tracking as defined in the C2PA Technical Specification.
228#[doc(hidden)]
229pub mod status_tracker;
230
231/// The `validation_results` module contains the definitions for the
232/// validation results that are part of the C2PA specification.
233pub mod validation_results;
234
235/// The `validation_status` module contains the definitions for the
236/// validation status that are part of the C2PA specification.
237#[doc(hidden)]
238pub mod validation_status;
239
240// Public exports
241#[doc(inline)]
242pub use assertions::DigitalSourceType;
243#[doc(inline)]
244pub use assertions::Relationship;
245pub use builder::{Builder, BuilderIntent, ManifestDefinition};
246pub use callback_signer::{CallbackFunc, CallbackSigner};
247pub use claim_generator_info::ClaimGeneratorInfo;
248#[doc(inline)]
249pub use context::{Context, ProgressCallbackFunc, ProgressPhase};
250pub use crypto::raw_signature::SigningAlg;
251pub use error::{Error, Result};
252#[doc(hidden)]
253pub use external_manifest::ManifestPatchCallback;
254pub use hash_utils::{hash_stream_by_alg, HashRange};
255pub use hashed_uri::HashedUri;
256pub use ingredient::Ingredient;
257#[cfg(feature = "file_io")]
258#[doc(hidden)]
259pub use ingredient::{DefaultOptions, IngredientOptions};
260pub use manifest::{Manifest, SignatureInfo};
261pub use manifest_assertion::{ManifestAssertion, ManifestAssertionKind};
262pub use reader::Reader;
263#[doc(inline)]
264pub use resource_store::{ResourceRef, ResourceStore};
265#[doc(inline)]
266pub use settings::Settings;
267pub use signer::{AsyncSigner, BoxedAsyncSigner, BoxedSigner, Signer};
268pub use utils::{ephemeral_signer::EphemeralSigner, mime::format_from_path};
269#[doc(inline)]
270pub use validation_results::{ValidationResults, ValidationState};
271
272// Internal modules
273pub(crate) mod assertion;
274pub(crate) mod asset_handlers;
275pub(crate) mod asset_io;
276pub(crate) mod builder;
277pub(crate) mod callback_signer;
278pub(crate) mod claim;
279pub(crate) mod claim_generator_info;
280pub(crate) mod context;
281pub(crate) mod cose_validator;
282pub(crate) mod crjson;
283pub(crate) mod error;
284pub(crate) mod external_manifest;
285pub(crate) mod hashed_uri;
286pub(crate) mod ingredient;
287
288#[allow(dead_code)]
289pub(crate) mod jumbf;
290
291pub(crate) mod manifest;
292pub(crate) mod manifest_assertion;
293pub(crate) mod manifest_store_report;
294/// The `maybe_send_sync` module contains traits for conditional Send bounds based on target architecture.
295pub(crate) mod maybe_send_sync;
296pub(crate) mod reader;
297pub(crate) mod resource_store;
298pub(crate) mod salt;
299pub(crate) mod signer;
300pub(crate) mod store;
301
302pub(crate) mod utils;
303pub(crate) use utils::{cbor_types, hash_utils};
304
305#[cfg(not(any(feature = "openssl", feature = "rust_native_crypto")))]
306compile_error!("Either 'openssl' or 'rust_native_crypto' feature must be enabled.");