commit d9e052b594b1fa87bf639a1b167b8c26dd532513
parent 2cb845f1a9dc2a1faaebabb85eef78af09dc9800
Author: Gavin Peacock <gpeacock@adobe.com>
Date: Tue, 11 Jul 2023 13:24:41 -0700
(MINOR) Converts DataHash and BoxHash methods to use RemoteSigner instead of AsyncSigner (#280)
* Change
manifest.data_hash_manifest_placeholder
manifest.data_hash_embeddable_manifest
manifest.box_hash_embeddable_manifest
to use RemoteSigner instead of AsyncSigner
Added a new test function - temp_remote_signer()
Diffstat:
3 files changed, 101 insertions(+), 99 deletions(-)
diff --git a/sdk/src/manifest.rs b/sdk/src/manifest.rs
@@ -22,6 +22,8 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::Value;
use uuid::Uuid;
+#[cfg(feature = "file_io")]
+use crate::AsyncSigner;
use crate::{
assertion::{AssertionBase, AssertionData},
assertions::{
@@ -35,8 +37,7 @@ use crate::{
resource_store::{skip_serializing_resources, ResourceRef, ResourceStore},
salt::DefaultSalt,
store::Store,
- AsyncSigner, ClaimGeneratorInfo, Ingredient, ManifestAssertion, ManifestAssertionKind,
- RemoteSigner, Signer,
+ ClaimGeneratorInfo, Ingredient, ManifestAssertion, ManifestAssertionKind, RemoteSigner, Signer,
};
/// A Manifest represents all the information in a c2pa manifest
@@ -1167,7 +1168,7 @@ impl Manifest {
/// This is used to create a properly formatted file ready for signing
pub fn data_hash_placeholder(
&mut self,
- signer: &dyn AsyncSigner,
+ signer: &dyn RemoteSigner,
format: &str,
) -> Result<Vec<u8>> {
let dh: Result<DataHash> = self.find_assertion(DataHash::LABEL);
@@ -1196,7 +1197,7 @@ impl Manifest {
pub async fn data_hash_embeddable_manifest(
&mut self,
dh: &DataHash,
- signer: &dyn AsyncSigner,
+ signer: &dyn RemoteSigner,
format: &str,
mut asset_reader: Option<&mut dyn CAIRead>,
) -> Result<Vec<u8>> {
@@ -1215,7 +1216,7 @@ impl Manifest {
/// The manifest must include a box hash assertion with correct hashes
pub async fn box_hash_embeddable_manifest(
&mut self,
- signer: &dyn AsyncSigner,
+ signer: &dyn RemoteSigner,
format: Option<&str>,
) -> Result<Vec<u8>> {
let mut store = self.to_store()?;
@@ -1265,7 +1266,7 @@ pub(crate) mod tests {
use crate::{
assertions::{c2pa_action, Action, Actions},
- utils::test::{temp_signer, TEST_VC},
+ utils::test::{temp_remote_signer, temp_signer, TEST_VC},
Ingredient, Manifest, Result,
};
#[cfg(feature = "file_io")]
@@ -1280,7 +1281,7 @@ pub(crate) mod tests {
fixture_path, temp_dir_path, temp_fixture_path, write_jpeg_placeholder_file,
TEST_SMALL_JPEG,
},
- validation_status, SigningAlg,
+ validation_status,
};
// example of random data structure as an assertion
@@ -1601,32 +1602,14 @@ pub(crate) mod tests {
#[cfg(all(feature = "file_io", feature = "openssl_sign"))]
#[actix::test]
async fn test_embed_remote_sign() {
- struct MyRemoteSigner {}
-
- #[async_trait::async_trait]
- impl crate::signer::RemoteSigner for MyRemoteSigner {
- async fn sign_remote(&self, claim_bytes: &[u8]) -> Result<Vec<u8>> {
- let signer = crate::openssl::temp_signer_async::AsyncSignerAdapter::new(
- crate::SigningAlg::Ps256,
- );
-
- // this would happen on some remote server
- crate::cose_sign::cose_sign_async(&signer, claim_bytes, self.reserve_size()).await
- }
-
- fn reserve_size(&self) -> usize {
- 10000
- }
- }
-
let temp_dir = tempdir().expect("temp dir");
let output = temp_fixture_path(&temp_dir, TEST_SMALL_JPEG);
- let remote_signer = MyRemoteSigner {};
+ let remote_signer = temp_remote_signer();
let mut manifest = test_manifest();
manifest
- .embed_remote_signed(&output, &output, &remote_signer)
+ .embed_remote_signed(&output, &output, remote_signer.as_ref())
.await
.expect("embed");
let manifest_store = crate::ManifestStore::from_file(&output).expect("from_file");
@@ -1686,28 +1669,6 @@ pub(crate) mod tests {
);
}
- struct MyRemoteSigner {}
-
- #[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
- #[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
- impl crate::signer::RemoteSigner for MyRemoteSigner {
- async fn sign_remote(&self, claim_bytes: &[u8]) -> crate::error::Result<Vec<u8>> {
- use std::io::{Seek, Write};
-
- let mut sign_bytes = std::io::Cursor::new(vec![0u8; self.reserve_size()]);
-
- sign_bytes.rewind()?;
- sign_bytes.write_all(claim_bytes)?;
-
- // fake sig
- Ok(sign_bytes.into_inner())
- }
-
- fn reserve_size(&self) -> usize {
- 10000
- }
- }
-
#[cfg_attr(not(target_arch = "wasm32"), actix::test)]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
async fn test_embed_jpeg_stream_wasm() {
@@ -1731,11 +1692,11 @@ pub(crate) mod tests {
ingredient.set_title("parent.jpg");
manifest.set_parent(ingredient).expect("set_parent");
- let signer = MyRemoteSigner {};
+ let signer = temp_remote_signer();
// Embed a manifest using the signer.
let (out_vec, _out_manifest) = manifest
- .embed_from_memory_remote_signed("jpeg", image, &signer)
+ .embed_from_memory_remote_signed("jpeg", image, signer.as_ref())
.await
.expect("embed_stream");
@@ -1767,11 +1728,11 @@ pub(crate) mod tests {
))
.unwrap();
- let signer = MyRemoteSigner {};
+ let signer = temp_remote_signer();
// Embed a manifest using the signer.
let (out_vec, _out_manifest) = manifest
- .embed_from_memory_remote_signed("png", image, &signer)
+ .embed_from_memory_remote_signed("png", image, signer.as_ref())
.await
.expect("embed_stream");
@@ -2185,12 +2146,14 @@ pub(crate) mod tests {
async fn test_data_hash_embeddable_manifest() {
let ap = fixture_path("cloud.jpg");
- let signer = crate::openssl::temp_signer_async::AsyncSignerAdapter::new(SigningAlg::Ps256);
+ let signer = temp_remote_signer();
let mut manifest = Manifest::new("claim_generator");
// get a placeholder the manifest
- let placeholder = manifest.data_hash_placeholder(&signer, "jpeg").unwrap();
+ let placeholder = manifest
+ .data_hash_placeholder(signer.as_ref(), "jpeg")
+ .unwrap();
let temp_dir = tempfile::tempdir().unwrap();
let output = temp_dir_path(&temp_dir, "boxhash-out.jpg");
@@ -2215,7 +2178,12 @@ pub(crate) mod tests {
dh.exclusions = Some(exclusions);
let signed_manifest = manifest
- .data_hash_embeddable_manifest(&dh, &signer, "image/jpeg", Some(&mut output_file))
+ .data_hash_embeddable_manifest(
+ &dh,
+ signer.as_ref(),
+ "image/jpeg",
+ Some(&mut output_file),
+ )
.await
.unwrap();
@@ -2232,7 +2200,7 @@ pub(crate) mod tests {
#[actix::test]
#[cfg(feature = "file_io")]
- async fn test_box_hash_embedable_manifest() {
+ async fn test_box_hash_embeddable_manifest() {
let asset_bytes = include_bytes!("../tests/fixtures/CA.jpg");
let box_hash_data = include_bytes!("../tests/fixtures/boxhash.json");
let box_hash: crate::assertions::BoxHash = serde_json::from_slice(box_hash_data).unwrap();
@@ -2244,10 +2212,10 @@ pub(crate) mod tests {
.add_labeled_assertion(crate::assertions::labels::BOX_HASH, &box_hash)
.unwrap();
- let signer = crate::openssl::temp_signer_async::AsyncSignerAdapter::new(SigningAlg::Ps256);
+ let signer = temp_remote_signer();
let embeddable = manifest
- .box_hash_embeddable_manifest(&signer, None)
+ .box_hash_embeddable_manifest(signer.as_ref(), None)
.await
.expect("embeddable_manifest");
diff --git a/sdk/src/store.rs b/sdk/src/store.rs
@@ -51,7 +51,7 @@ use crate::{
hash_utils::{hash256, HashRange},
patch::patch_bytes,
},
- validation_status, AsyncSigner, ManifestStoreReport, Signer,
+ validation_status, AsyncSigner, ManifestStoreReport, RemoteSigner, Signer,
};
#[cfg(feature = "file_io")]
use crate::{
@@ -1628,7 +1628,7 @@ impl Store {
/// from `get_data_hashed_embeddable_manifest` will have a size that matches this function.
pub fn get_data_hashed_manifest_placeholder(
&mut self,
- signer: &dyn AsyncSigner,
+ signer: &dyn RemoteSigner,
format: &str,
) -> Result<Vec<u8>> {
let pc = self.provenance_claim_mut().ok_or(Error::ClaimEncoding)?;
@@ -1668,7 +1668,7 @@ impl Store {
pub async fn get_data_hashed_embeddable_manifest(
&mut self,
dh: &DataHash,
- signer: &dyn AsyncSigner,
+ signer: &dyn RemoteSigner,
format: &str,
asset_reader: Option<&mut dyn CAIRead>,
) -> Result<Vec<u8>> {
@@ -1705,9 +1705,9 @@ impl Store {
let mut jumbf_bytes = self.to_jumbf_internal(signer.reserve_size())?;
// sign contents
- let sig = self
- .sign_claim_async(pc, signer, signer.reserve_size())
- .await?;
+ let claim_bytes = pc.data()?;
+ let sig = signer.sign_remote(&claim_bytes).await?;
+
let sig_placeholder = Store::sign_claim_placeholder(pc, signer.reserve_size());
if sig_placeholder.len() != sig.len() {
@@ -1724,7 +1724,7 @@ impl Store {
/// included the necessary box hash assertion with the pregenerated hashes.
pub async fn get_box_hashed_embeddable_manifest(
&mut self,
- signer: &dyn AsyncSigner,
+ signer: &dyn RemoteSigner,
) -> Result<Vec<u8>> {
let pc = self.provenance_claim().ok_or(Error::ClaimEncoding)?;
@@ -1743,9 +1743,8 @@ impl Store {
let mut jumbf_bytes = self.to_jumbf_internal(signer.reserve_size())?;
// sign contents
- let sig = self
- .sign_claim_async(pc, signer, signer.reserve_size())
- .await?;
+ let claim_bytes = pc.data()?;
+ let sig = signer.sign_remote(&claim_bytes).await?;
let sig_placeholder = Store::sign_claim_placeholder(pc, signer.reserve_size());
if sig_placeholder.len() != sig.len() {
@@ -2896,8 +2895,8 @@ pub mod tests {
hash_utils::Hasher,
patch::patch_file,
test::{
- create_test_claim, fixture_path, temp_dir_path, temp_fixture_path, temp_signer,
- write_jpeg_placeholder_file,
+ create_test_claim, fixture_path, temp_dir_path, temp_fixture_path,
+ temp_remote_signer, temp_signer, write_jpeg_placeholder_file,
},
},
AssertionJson, SigningAlg,
@@ -3121,23 +3120,6 @@ pub mod tests {
}
}
- struct MyRemoteSigner {}
-
- #[async_trait::async_trait]
- impl crate::signer::RemoteSigner for MyRemoteSigner {
- async fn sign_remote(&self, claim_bytes: &[u8]) -> crate::error::Result<Vec<u8>> {
- let signer =
- crate::openssl::temp_signer_async::AsyncSignerAdapter::new(SigningAlg::Ps256);
-
- // this would happen on some remote server
- crate::cose_sign::cose_sign_async(&signer, claim_bytes, self.reserve_size()).await
- }
-
- fn reserve_size(&self) -> usize {
- 10000
- }
- }
-
#[test]
#[cfg(feature = "file_io")]
fn test_detects_unverifiable_signature() {
@@ -3294,11 +3276,11 @@ pub mod tests {
let claim1 = create_test_claim().unwrap();
// create my remote signer to map the CoseSign1 data back into the asset
- let remote_signer = MyRemoteSigner {};
+ let remote_signer = crate::utils::test::temp_remote_signer();
store.commit_claim(claim1).unwrap();
store
- .save_to_asset_remote_signed(&ap, &remote_signer, &op)
+ .save_to_asset_remote_signed(&ap, remote_signer.as_ref(), &op)
.await
.unwrap();
@@ -4512,11 +4494,11 @@ pub mod tests {
store.commit_claim(claim).unwrap();
// Do we generate JUMBF?
- let signer = crate::openssl::temp_signer_async::AsyncSignerAdapter::new(SigningAlg::Ps256);
+ let signer = temp_remote_signer();
// get the embeddable manifest
let em = store
- .get_box_hashed_embeddable_manifest(&signer)
+ .get_box_hashed_embeddable_manifest(signer.as_ref())
.await
.unwrap();
@@ -4577,7 +4559,7 @@ pub mod tests {
let ap = fixture_path("cloud.jpg");
// Do we generate JUMBF?
- let signer = crate::openssl::temp_signer_async::AsyncSignerAdapter::new(SigningAlg::Ps256);
+ let signer = temp_remote_signer();
// Create claims store.
let mut store = Store::new();
@@ -4589,7 +4571,7 @@ pub mod tests {
// get a placeholder the manifest
let placeholder = store
- .get_data_hashed_manifest_placeholder(&signer, "jpeg")
+ .get_data_hashed_manifest_placeholder(signer.as_ref(), "jpeg")
.unwrap();
let temp_dir = tempfile::tempdir().unwrap();
@@ -4617,7 +4599,12 @@ pub mod tests {
// get the embeddable manifest, letting API do the hashing
output_file.rewind().unwrap();
let cm = store
- .get_data_hashed_embeddable_manifest(&dh, &signer, "jpeg", Some(&mut output_file))
+ .get_data_hashed_embeddable_manifest(
+ &dh,
+ signer.as_ref(),
+ "jpeg",
+ Some(&mut output_file),
+ )
.await
.unwrap();
@@ -4640,7 +4627,7 @@ pub mod tests {
let mut hasher = Hasher::SHA256(Sha256::new());
// Do we generate JUMBF?
- let signer = crate::openssl::temp_signer_async::AsyncSignerAdapter::new(SigningAlg::Ps256);
+ let signer = temp_remote_signer();
// Create claims store.
let mut store = Store::new();
@@ -4652,7 +4639,7 @@ pub mod tests {
// get a placeholder for the manifest
let placeholder = store
- .get_data_hashed_manifest_placeholder(&signer, "jpeg")
+ .get_data_hashed_manifest_placeholder(signer.as_ref(), "jpeg")
.unwrap();
let temp_dir = tempfile::tempdir().unwrap();
@@ -4681,7 +4668,7 @@ pub mod tests {
// get the embeddable manifest, using user hashing
let cm = store
- .get_data_hashed_embeddable_manifest(&dh, &signer, "jpeg", None)
+ .get_data_hashed_embeddable_manifest(&dh, signer.as_ref(), "jpeg", None)
.await
.unwrap();
diff --git a/sdk/src/utils/test.rs b/sdk/src/utils/test.rs
@@ -27,7 +27,7 @@ use crate::{
claim::Claim,
salt::DefaultSalt,
store::Store,
- Result, Signer, SigningAlg,
+ RemoteSigner, Result, Signer, SigningAlg,
};
#[cfg(feature = "file_io")]
use crate::{
@@ -284,6 +284,11 @@ impl crate::Signer for TestGoodSigner {
}
}
+/// Create a [`Signer`] instance that can be used for testing purposes using ps256 alg.
+///
+/// # Returns
+///
+/// Returns a boxed [`Signer`] instance.
pub fn temp_signer() -> Box<dyn Signer> {
#[cfg(feature = "openssl_sign")]
{
@@ -331,6 +336,48 @@ pub fn temp_signer_with_alg(alg: SigningAlg) -> Box<dyn Signer> {
.expect("get_temp_signer_with_alg")
}
+struct TempRemoteSigner {}
+
+#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
+#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
+impl crate::signer::RemoteSigner for TempRemoteSigner {
+ async fn sign_remote(&self, claim_bytes: &[u8]) -> crate::error::Result<Vec<u8>> {
+ #[cfg(feature = "openssl_sign")]
+ {
+ let signer =
+ crate::openssl::temp_signer_async::AsyncSignerAdapter::new(SigningAlg::Ps256);
+
+ // this would happen on some remote server
+ crate::cose_sign::cose_sign_async(&signer, claim_bytes, self.reserve_size()).await
+ }
+ #[cfg(not(feature = "openssl_sign"))]
+ {
+ use std::io::{Seek, Write};
+
+ let mut sign_bytes = std::io::Cursor::new(vec![0u8; self.reserve_size()]);
+
+ sign_bytes.rewind()?;
+ sign_bytes.write_all(claim_bytes)?;
+
+ // fake sig
+ Ok(sign_bytes.into_inner())
+ }
+ }
+
+ fn reserve_size(&self) -> usize {
+ 10000
+ }
+}
+
+/// Create a [`RemoteSigner`] instance that can be used for testing purposes.
+///
+/// # Returns
+///
+/// Returns a boxed [`RemoteSigner`] instance.
+pub fn temp_remote_signer() -> Box<dyn RemoteSigner> {
+ Box::new(TempRemoteSigner {})
+}
+
#[test]
fn test_create_test_store() {
#[allow(clippy::expect_used)]