c2pa_azure/lib.rs
1//! # c2pa-acs
2//!
3//! Rust helpers for issuing C2PA signatures backed by Azure Trusted Signing.
4//! The [`TrustedSigner`] type bridges `c2pa-rs` with Azure so you can stamp
5//! evidence from CLIs, Azure Functions, or containerized workers while reusing
6//! the same manifest definition and verification settings.
7//!
8//! ## Using `TrustedSigner`
9//!
10//! - `TokenCredential`: supply any Azure credential (for example `DefaultAzureCredential`).
11//! - [`SigningOptions`]: describe the Trusted Signing account, certificate profile, and optional timestamping authority.
12//! - [`Context`](c2pa::Context) + [`Builder`](c2pa::Builder): supply TOML settings and your manifest definition before invoking the signer.
13//!
14//! ### Minimal example
15//!
16//! ```no_run
17//! use std::{
18//! fs::File,
19//! sync::Arc,
20//! };
21//!
22//! use azure_identity::DefaultAzureCredential;
23//! use c2pa::{Builder, Context};
24//! use c2pa_azure::{SigningOptions, TrustedSigner};
25//! use url::Url;
26//!
27//! #[tokio::main]
28//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
29//! let credential = Arc::new(DefaultAzureCredential::default());
30//!
31//! let options = SigningOptions::new(
32//! Url::parse("https://eus.codesigning.azure.net")?,
33//! "signing_account".to_string(),
34//! "certificate_profile".to_string(),
35//! None,
36//! );
37//!
38//! let settings = r#"[verify]\nverify_after_sign = true"#;
39//! let manifest_definition = r#"{"label":"example"}"#;
40//!
41//! let context = Context::new().with_settings(settings)?;
42//! let mut builder = Builder::from_context(context).with_definition(manifest_definition)?;
43//! let signer = TrustedSigner::new(credential, options).await?;
44//!
45//! let mut input = File::open("sample1.png")?;
46//! let mut output = File::create("signed.png")?;
47//!
48//! builder
49//! .sign_async(&signer, "image/png", &mut input, &mut output)
50//! .await?;
51//! Ok(())
52//! }
53//! ```
54//!
55//! ### Environment variables
56//!
57//! - `SIGNING_ENDPOINT`: Trusted Signing endpoint (for example `https://eus.codesigning.azure.net`).
58//! - `SIGNING_ACCOUNT`: Trusted Signing account name.
59//! - `CERTIFICATE_PROFILE`: certificate profile used for signing.
60//! - `ALGORITHM` *(optional)*: override the default signature algorithm (`ps384`).
61//! - `TIME_AUTHORITY_URL` *(optional)*: RFC3161 timestamp authority.
62//!
63//! ### Verifying a signed file
64//!
65//! The library exposes a thin wrapper around [`c2pa::Reader`] so you can inspect
66//! manifests produced by `TrustedSigner` or any other C2PA producer.
67//!
68//! ```no_run
69//! use std::fs::File;
70//!
71//! use c2pa::Reader;
72//!
73//! #[tokio::main]
74//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
75//! let signed = File::open("signed.png")?;
76//! let reader = Reader::from_stream_async("png", signed).await?;
77//! println!("Manifest Store: {}", reader.json());
78//! Ok(())
79//! }
80//! ```
81//!
82mod acs;
83mod auth;
84mod p7b;
85mod sign;
86
87pub use c2pa::Error;
88pub use envconfig::Envconfig;
89pub use sign::{SigningOptions, TrustedSigner};
90
91#[cfg(test)]
92mod tests {
93 use c2pa::Reader;
94 use std::io::Cursor;
95
96 #[tokio::test]
97 async fn test_verify_file() {
98 let data = include_bytes!("../../test_data/signed.png");
99 let stream = Cursor::new(data);
100 let result = Reader::from_stream_async("png", stream).await.unwrap();
101 assert_eq!(
102 &result.json(),
103 include_str!("../../test_data/manifest.json")
104 );
105 }
106}