Skip to main content

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}