c2pa-rs

A fork of https://github.com/contentauth/c2pa-rs/
git clone git://archive.git.mtrnord.blog/mtrnords-photography-manager/c2pa-rs.git
Log | Files | Refs | README

commit 4e6e390fef0f52c45d3527d5f389ef1c4545a20c
parent e9eaf6699c414bf9ec2fd9f37e43062eb15866dd
Author: Gavin  Peacock <gpeacock@adobe.com>
Date:   Thu,  9 May 2024 11:31:28 -0700

Steps toward removing RemoteSigner APIs. (#466)

Support direct_cose_handling() on on all signing methods, sync and async.
Adds:
manifest.data_hash_embeddable_manifest_async
manifest.box_hash_embeddable_manifest_async.
Diffstat:
Msdk/src/manifest.rs | 27++++++++++++++++++++++++---
Msdk/src/signer.rs | 8++++++++
Msdk/src/store.rs | 24+++++++++++++++---------
3 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/sdk/src/manifest.rs b/sdk/src/manifest.rs @@ -1205,6 +1205,13 @@ impl Manifest { /// This can directly replace a placeholder manifest to create a properly signed asset /// The data hash must contain exclusions and may contain pre-calculated hashes /// if an asset reader is provided, it will be used to calculate the data hash + #[async_generic(async_signature( + &mut self, + dh: &DataHash, + signer: &dyn AsyncSigner, + format: &str, + mut asset_reader: Option<&mut dyn CAIRead>, + ))] pub fn data_hash_embeddable_manifest( &mut self, dh: &DataHash, @@ -1216,8 +1223,13 @@ impl Manifest { if let Some(asset_reader) = asset_reader.as_deref_mut() { asset_reader.rewind()?; } - let cm = store.get_data_hashed_embeddable_manifest(dh, signer, format, asset_reader)?; - Ok(cm) + if _sync { + store.get_data_hashed_embeddable_manifest(dh, signer, format, asset_reader) + } else { + store + .get_data_hashed_embeddable_manifest_async(dh, signer, format, asset_reader) + .await + } } /// Generates an data hashed embeddable manifest for a file @@ -1246,13 +1258,22 @@ impl Manifest { /// Generates a signed box hashed manifest, optionally preformatted for embedding /// /// The manifest must include a box hash assertion with correct hashes + #[async_generic(async_signature( + &mut self, + signer: &dyn AsyncSigner, + format: Option<&str>, + ))] pub fn box_hash_embeddable_manifest( &mut self, signer: &dyn Signer, format: Option<&str>, ) -> Result<Vec<u8>> { let mut store = self.to_store()?; - let mut cm = store.get_box_hashed_embeddable_manifest(signer)?; + let mut cm = if _sync { + store.get_box_hashed_embeddable_manifest(signer) + } else { + store.get_box_hashed_embeddable_manifest_async(signer).await + }?; if let Some(format) = format { cm = Store::get_composed_manifest(&cm, format)?; } diff --git a/sdk/src/signer.rs b/sdk/src/signer.rs @@ -77,6 +77,14 @@ pub trait Signer { fn ocsp_val(&self) -> Option<Vec<u8>> { None } + + /// If this returns true the sign function is responsible for for direct handling of the COSE structure. + /// + /// This is useful for cases where the signer needs to handle the COSE structure directly. + /// Not recommended for general use. + fn direct_cose_handling(&self) -> bool { + false + } } /// Trait to allow loading of signing credential from external sources diff --git a/sdk/src/store.rs b/sdk/src/store.rs @@ -505,9 +505,19 @@ impl Store { let claim_bytes = claim.data()?; let result = if _sync { - cose_sign(signer, &claim_bytes, box_size) + if signer.direct_cose_handling() { + // Let the signer do all the COSE processing and return the structured COSE data. + return signer.sign(&claim_bytes); // do not verify remote signers (we never did) + } else { + cose_sign(signer, &claim_bytes, box_size) + } } else { - cose_sign_async(signer, &claim_bytes, box_size).await + if signer.direct_cose_handling() { + // Let the signer do all the COSE processing and return the structured COSE data. + return signer.sign(claim_bytes.clone()).await; // do not verify remote signers (we never did) + } else { + cose_sign_async(signer, &claim_bytes, box_size).await + } }; match result { Ok(sig) => { @@ -2046,15 +2056,11 @@ impl Store { intermediate_stream.set_position(0); let pc = self.provenance_claim().ok_or(Error::ClaimEncoding)?; let sig = if _sync { - self.sign_claim(pc, signer, signer.reserve_size())? - } else if signer.direct_cose_handling() { - // Let the signer do all the COSE processing and return the structured COSE data. - // This replaces the RemoteSigner interface. - signer.sign(pc.data()?).await? + self.sign_claim(pc, signer, signer.reserve_size()) } else { self.sign_claim_async(pc, signer, signer.reserve_size()) - .await? - }; + .await + }?; let sig_placeholder = Store::sign_claim_placeholder(pc, signer.reserve_size()); intermediate_stream.rewind()?;