commit 1c12e1c8cb3293226b4b53e1c50faa6f22414300
parent 8dc217b93bbbee643a8d5aa6b4a0f28122c6ab6d
Author: mauricefisher64 <92736594+mauricefisher64@users.noreply.github.com>
Date: Fri, 8 Sep 2023 11:43:56 -0400
(MINOR) Expose HashRange (#300)
* Make HashRange public
* Change embedding manifest functions to be synchronous.
Create example of using embedding functions.
* Fix formatting
* format fix
* Disable example for WASM
* Disable more WASM stuff
* Clippy fixes
* wasm fix
Diffstat:
5 files changed, 344 insertions(+), 74 deletions(-)
diff --git a/sdk/examples/data_hash.rs b/sdk/examples/data_hash.rs
@@ -0,0 +1,268 @@
+// Copyright 2023 Adobe. All rights reserved.
+// This file is licensed to you under the Apache License,
+// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+// or the MIT license (http://opensource.org/licenses/MIT),
+// at your option.
+
+// Unless required by applicable law or agreed to in writing,
+// this software is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
+// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
+// specific language governing permissions and limitations under
+// each license.
+
+// Example code (in unit test) for how you might use client DataHash values. This allows clients
+// to perform the manifest embedding and optionally the hashing
+
+#[cfg(not(target_arch = "wasm32"))]
+use std::{
+ io::{Read, Seek, Write},
+ path::PathBuf,
+};
+
+#[cfg(not(target_arch = "wasm32"))]
+use c2pa::{
+ assertions::{c2pa_action, Action, Actions, CreativeWork, DataHash, Exif, SchemaDotOrgPerson},
+ create_signer, hash_stream_by_alg, HashRange, Ingredient, Manifest, ManifestStore, SigningAlg,
+};
+
+fn main() {
+ println!("DataHash demo");
+
+ #[cfg(not(target_arch = "wasm32"))]
+ user_data_hash_with_sdk_hashing();
+
+ #[cfg(not(target_arch = "wasm32"))]
+ user_data_hash_with_user_hashing();
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+fn user_data_hash_with_sdk_hashing() {
+ const GENERATOR: &str = "test_app/0.1";
+
+ // You will often implement your own Signer trait to perform on device signing
+ let signcert_path = "sdk/tests/fixtures/certs/es256.pub";
+ let pkey_path = "sdk/tests/fixtures/certs/es256.pem";
+ let signer =
+ create_signer::from_files(signcert_path, pkey_path, SigningAlg::Es256, None).unwrap();
+
+ let src = "sdk/tests/fixtures/earth_apollo17.jpg";
+ let dst = "target/tmp/output.jpg";
+
+ let source = PathBuf::from(src);
+ let dest = PathBuf::from(dst);
+
+ let mut input_file = std::fs::OpenOptions::new()
+ .read(true)
+ .open(&source)
+ .unwrap();
+
+ let mut output_file = std::fs::OpenOptions::new()
+ .read(true)
+ .write(true)
+ .create(true)
+ .open(&dest)
+ .unwrap();
+
+ let parent = Ingredient::from_file(source.as_path()).unwrap();
+
+ // create an action assertion stating that we imported this file
+ let actions = Actions::new().add_action(
+ Action::new(c2pa_action::PLACED)
+ .set_parameter("identifier", parent.instance_id().to_owned())
+ .unwrap(),
+ );
+
+ // build a creative work assertion
+ let creative_work = CreativeWork::new()
+ .add_author(SchemaDotOrgPerson::new().set_name("me").unwrap())
+ .unwrap();
+
+ let exif = Exif::from_json_str(
+ r#"{
+ "@context" : {
+ "exif": "http://ns.adobe.com/exif/1.0/"
+ },
+ "exif:GPSVersionID": "2.2.0.0",
+ "exif:GPSLatitude": "39,21.102N",
+ "exif:GPSLongitude": "74,26.5737W",
+ "exif:GPSAltitudeRef": 0,
+ "exif:GPSAltitude": "100963/29890",
+ "exif:GPSTimeStamp": "2019-09-22T18:22:57Z"
+ }"#,
+ )
+ .unwrap();
+
+ // create a new Manifest
+ let mut manifest = Manifest::new(GENERATOR.to_owned());
+ // add parent and assertions
+ manifest
+ .set_parent(parent)
+ .unwrap()
+ .add_assertion(&actions)
+ .unwrap()
+ .add_assertion(&creative_work)
+ .unwrap()
+ .add_assertion(&exif)
+ .unwrap();
+
+ // get the composed manifest ready to insert into a file (returns manifest of same length as finished manifest)
+ let unfinished_manifest = manifest
+ .data_hash_placeholder(signer.as_ref(), "jpg")
+ .unwrap();
+
+ // Figure out where you want to put the manifest, let's put it at the beginning of the JPEG as first segment
+ // generate new file inserting unfinished manifest into file
+ input_file.rewind().unwrap();
+ let mut before = vec![0u8; 2];
+ input_file.read_exact(before.as_mut_slice()).unwrap();
+
+ output_file.write_all(&before).unwrap();
+
+ // write completed final manifest
+ output_file.write_all(&unfinished_manifest).unwrap();
+
+ // write bytes after
+ let mut after_buf = Vec::new();
+ input_file.read_to_end(&mut after_buf).unwrap();
+ output_file.write_all(&after_buf).unwrap();
+
+ // we need to add a data hash that excludes the manifest
+ let mut dh = DataHash::new("my_manifest", "sha265");
+ let hr = HashRange::new(2, unfinished_manifest.len());
+ dh.add_exclusion(hr);
+
+ // tell SDK to fill in the hash and sign to complete the manifest
+ output_file.rewind().unwrap();
+ let final_manifest = manifest
+ .data_hash_embeddable_manifest(&dh, signer.as_ref(), "jpg", Some(&mut output_file))
+ .unwrap();
+
+ // replace temporary manifest with final signed manifest
+ // move to location where we inserted manifest,
+ // note: temporary manifest and final manifest will be the same size
+ output_file.seek(std::io::SeekFrom::Start(2)).unwrap();
+
+ // write completed final manifest bytes over temporary bytes
+ output_file.write_all(&final_manifest).unwrap();
+
+ // make sure the output file is correct
+ let manifest_store = ManifestStore::from_file(&dest).unwrap();
+
+ // example of how to print out the whole manifest as json
+ println!("{manifest_store}\n");
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+fn user_data_hash_with_user_hashing() {
+ const GENERATOR: &str = "test_app/0.1";
+
+ // You will often implement your own Signer trait to perform on device signing
+ let signcert_path = "sdk/tests/fixtures/certs/es256.pub";
+ let pkey_path = "sdk/tests/fixtures/certs/es256.pem";
+ let signer =
+ create_signer::from_files(signcert_path, pkey_path, SigningAlg::Es256, None).unwrap();
+
+ let src = "sdk/tests/fixtures/earth_apollo17.jpg";
+ let dst = "target/tmp/output.jpg";
+
+ let source = PathBuf::from(src);
+ let dest = PathBuf::from(dst);
+
+ let mut input_file = std::fs::OpenOptions::new()
+ .read(true)
+ .open(&source)
+ .unwrap();
+
+ let mut output_file = std::fs::OpenOptions::new()
+ .read(true)
+ .write(true)
+ .create(true)
+ .open(&dest)
+ .unwrap();
+
+ let parent = Ingredient::from_file(source.as_path()).unwrap();
+
+ // create an action assertion stating that we imported this file
+ let actions = Actions::new().add_action(
+ Action::new(c2pa_action::PLACED)
+ .set_parameter("identifier", parent.instance_id().to_owned())
+ .unwrap(),
+ );
+
+ // build a creative work assertion
+ let creative_work = CreativeWork::new()
+ .add_author(SchemaDotOrgPerson::new().set_name("me").unwrap())
+ .unwrap();
+
+ let exif = Exif::from_json_str(
+ r#"{
+ "@context" : {
+ "exif": "http://ns.adobe.com/exif/1.0/"
+ },
+ "exif:GPSVersionID": "2.2.0.0",
+ "exif:GPSLatitude": "39,21.102N",
+ "exif:GPSLongitude": "74,26.5737W",
+ "exif:GPSAltitudeRef": 0,
+ "exif:GPSAltitude": "100963/29890",
+ "exif:GPSTimeStamp": "2019-09-22T18:22:57Z"
+ }"#,
+ )
+ .unwrap();
+
+ // create a new Manifest
+ let mut manifest = Manifest::new(GENERATOR.to_owned());
+ // add parent and assertions
+ manifest
+ .set_parent(parent)
+ .unwrap()
+ .add_assertion(&actions)
+ .unwrap()
+ .add_assertion(&creative_work)
+ .unwrap()
+ .add_assertion(&exif)
+ .unwrap();
+
+ // get the composed manifest ready to insert into a file (returns manifest of same length as finished manifest)
+ let unfinished_manifest = manifest
+ .data_hash_placeholder(signer.as_ref(), "jpg")
+ .unwrap();
+
+ // Figure out where you want to put the manifest, let's put it at the beginning of the JPEG as first segment
+ // we will need to add a data hash that excludes the manifest
+ let mut dh = DataHash::new("my_manifest", "sha265");
+ let hr = HashRange::new(2, unfinished_manifest.len());
+ dh.add_exclusion(hr);
+
+ // since the only thing we are excluding in this example is the manifest we can just hash all the bytes
+ // if you have additional exclusions you can add them to the DataHash and pass them to this function to be '
+ // excluded from the hash generation
+ let hash = hash_stream_by_alg("sha256", &mut input_file, None, true).unwrap();
+ dh.set_hash(hash);
+
+ // tell SDK to fill we will provide the hash and sign to complete the manifest
+ let final_manifest = manifest
+ .data_hash_embeddable_manifest(&dh, signer.as_ref(), "jpg", None)
+ .unwrap();
+
+ // generate new file inserting final manifest into file
+ input_file.rewind().unwrap();
+ let mut before = vec![0u8; 2];
+ input_file.read_exact(before.as_mut_slice()).unwrap();
+
+ output_file.write_all(&before).unwrap();
+
+ // write completed final manifest
+ output_file.write_all(&final_manifest).unwrap();
+
+ // write bytes after
+ let mut after_buf = Vec::new();
+ input_file.read_to_end(&mut after_buf).unwrap();
+ output_file.write_all(&after_buf).unwrap();
+
+ // make sure the output file is correct
+ let manifest_store = ManifestStore::from_file(&dest).unwrap();
+
+ // example of how to print out the whole manifest as json
+ println!("{manifest_store}\n");
+}
diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs
@@ -145,9 +145,10 @@ pub(crate) mod status_tracker;
pub(crate) mod store;
pub(crate) mod time_stamp;
pub(crate) mod utils;
-pub use utils::cbor_types::DateT;
pub mod validation_status;
+pub use hash_utils::HashRange;
pub(crate) use utils::{cbor_types, hash_utils};
+pub use utils::{cbor_types::DateT, hash_utils::hash_stream_by_alg};
pub(crate) mod validator;
#[cfg(target_arch = "wasm32")]
pub mod wasm;
diff --git a/sdk/src/manifest.rs b/sdk/src/manifest.rs
@@ -32,12 +32,12 @@ use crate::{
asset_io::CAIRead,
claim::{Claim, RemoteManifest},
error::{Error, Result},
- hash_utils::HashRange,
jumbf,
resource_store::{skip_serializing_resources, ResourceRef, ResourceStore},
salt::DefaultSalt,
store::Store,
- ClaimGeneratorInfo, Ingredient, ManifestAssertion, ManifestAssertionKind, RemoteSigner, Signer,
+ ClaimGeneratorInfo, HashRange, Ingredient, ManifestAssertion, ManifestAssertionKind,
+ RemoteSigner, Signer,
};
/// A Manifest represents all the information in a c2pa manifest
@@ -1147,22 +1147,16 @@ impl Manifest {
/// The return value is pre-formatted for insertion into a file of the given format
/// For JPEG it is a series of App11 JPEG segments containing space for a manifest
/// This is used to create a properly formatted file ready for signing
- pub fn data_hash_placeholder(
- &mut self,
- signer: &dyn RemoteSigner,
- format: &str,
- ) -> Result<Vec<u8>> {
+ pub fn data_hash_placeholder(&mut self, signer: &dyn Signer, format: &str) -> Result<Vec<u8>> {
let dh: Result<DataHash> = self.find_assertion(DataHash::LABEL);
if dh.is_err() {
let mut ph = DataHash::new("jumbf manifest", "sha256");
for _ in 0..10 {
ph.add_exclusion(HashRange::new(0, 2));
}
- let data = vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- let mut stream = std::io::Cursor::new(data);
- ph.gen_hash_from_stream(&mut stream)?;
self.add_assertion(&ph)?;
}
+
let mut store = self.to_store()?;
let placeholder = store.get_data_hashed_manifest_placeholder(signer, format)?;
Ok(placeholder)
@@ -1175,10 +1169,10 @@ 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
- pub async fn data_hash_embeddable_manifest(
+ pub fn data_hash_embeddable_manifest(
&mut self,
dh: &DataHash,
- signer: &dyn RemoteSigner,
+ signer: &dyn Signer,
format: &str,
mut asset_reader: Option<&mut dyn CAIRead>,
) -> Result<Vec<u8>> {
@@ -1186,22 +1180,20 @@ 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)
- .await?;
+ let cm = store.get_data_hashed_embeddable_manifest(dh, signer, format, asset_reader)?;
Ok(cm)
}
/// Generates a signed box hashed manifest, optionally preformatted for embedding
///
/// The manifest must include a box hash assertion with correct hashes
- pub async fn box_hash_embeddable_manifest(
+ pub fn box_hash_embeddable_manifest(
&mut self,
- signer: &dyn RemoteSigner,
+ 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).await?;
+ let mut cm = store.get_box_hashed_embeddable_manifest(signer)?;
if let Some(format) = format {
cm = store.get_composed_manifest(&cm, format)?;
}
@@ -2217,12 +2209,12 @@ pub(crate) mod tests {
assert!(active_manifest.thumbnail().is_none());
}
- #[actix::test]
+ #[test]
#[cfg(feature = "file_io")]
- async fn test_data_hash_embeddable_manifest() {
+ fn test_data_hash_embeddable_manifest() {
let ap = fixture_path("cloud.jpg");
- let signer = temp_remote_signer();
+ let signer = temp_signer();
let mut manifest = Manifest::new("claim_generator");
@@ -2260,7 +2252,6 @@ pub(crate) mod tests {
"image/jpeg",
Some(&mut output_file),
)
- .await
.unwrap();
use std::io::{Seek, SeekFrom, Write};
@@ -2274,9 +2265,9 @@ pub(crate) mod tests {
assert!(manifest_store.validation_status().is_none());
}
- #[actix::test]
+ #[test]
#[cfg(feature = "file_io")]
- async fn test_box_hash_embeddable_manifest() {
+ fn test_box_hash_embeddable_manifest() {
let asset_bytes = include_bytes!("../tests/fixtures/boxhash.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();
@@ -2288,20 +2279,18 @@ pub(crate) mod tests {
.add_labeled_assertion(crate::assertions::labels::BOX_HASH, &box_hash)
.unwrap();
- let signer = temp_remote_signer();
+ let signer = temp_signer();
let embeddable = manifest
.box_hash_embeddable_manifest(signer.as_ref(), None)
- .await
.expect("embeddable_manifest");
// Validate the embeddable manifest against the asset bytes
- let manifest_store = crate::ManifestStore::from_manifest_and_asset_bytes_async(
+ let manifest_store = crate::ManifestStore::from_manifest_and_asset_bytes(
&embeddable,
"image/jpeg",
asset_bytes,
)
- .await
.unwrap();
println!("{manifest_store}");
assert!(!manifest_store.manifests().is_empty());
diff --git a/sdk/src/manifest_store.rs b/sdk/src/manifest_store.rs
@@ -283,6 +283,43 @@ impl ManifestStore {
Ok(Self::from_store(&store, &mut validation_log))
}
+
+ /// Synchronously loads a manifest from a buffer holding a binary manifest (.c2pa) and validates against an asset buffer
+ ///
+ /// # Example: Creating a manifest store from a .c2pa manifest and validating it against an asset
+ /// ```
+ /// use c2pa::{Result, ManifestStore};
+ ///
+ /// # fn main() -> Result<()> {
+ /// # async {
+ /// let asset_bytes = include_bytes!("../tests/fixtures/cloud.jpg");
+ /// let manifest_bytes = include_bytes!("../tests/fixtures/cloud_manifest.c2pa");
+ ///
+ /// let manifest_store = ManifestStore::from_manifest_and_asset_bytes(manifest_bytes, "image/jpg", asset_bytes)
+ /// .unwrap();
+ ///
+ /// println!("{}", manifest_store);
+ /// # };
+ /// #
+ /// # Ok(())
+ /// }
+ /// ```
+ pub fn from_manifest_and_asset_bytes(
+ manifest_bytes: &[u8],
+ format: &str,
+ asset_bytes: &[u8],
+ ) -> Result<ManifestStore> {
+ let mut validation_log = DetailedStatusTracker::new();
+ let store = Store::from_jumbf(manifest_bytes, &mut validation_log)?;
+
+ Store::verify_store(
+ &store,
+ &mut ClaimAssetData::Bytes(asset_bytes, format),
+ &mut validation_log,
+ )?;
+
+ Ok(Self::from_store(&store, &mut validation_log))
+ }
}
impl Default for ManifestStore {
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, RemoteSigner, Signer,
+ validation_status, AsyncSigner, ManifestStoreReport, 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 RemoteSigner,
+ signer: &dyn Signer,
format: &str,
) -> Result<Vec<u8>> {
let pc = self.provenance_claim_mut().ok_or(Error::ClaimEncoding)?;
@@ -1665,10 +1665,10 @@ impl Store {
/// It is an error if `get_data_hashed_manifest_placeholder` was not called first
/// as this call inserts the DataHash placeholder assertion to reserve space for the
/// actual hash values not required when using BoxHashes.
- pub async fn get_data_hashed_embeddable_manifest(
+ pub fn get_data_hashed_embeddable_manifest(
&mut self,
dh: &DataHash,
- signer: &dyn RemoteSigner,
+ signer: &dyn Signer,
format: &str,
asset_reader: Option<&mut dyn CAIRead>,
) -> Result<Vec<u8>> {
@@ -1705,8 +1705,7 @@ impl Store {
let mut jumbf_bytes = self.to_jumbf_internal(signer.reserve_size())?;
// sign contents
- let claim_bytes = pc.data()?;
- let sig = signer.sign_remote(&claim_bytes).await?;
+ let sig = self.sign_claim(pc, signer, signer.reserve_size())?;
let sig_placeholder = Store::sign_claim_placeholder(pc, signer.reserve_size());
@@ -1722,10 +1721,7 @@ impl Store {
/// Returns a finalized, signed manifest. The client is required to have
/// included the necessary box hash assertion with the pregenerated hashes.
- pub async fn get_box_hashed_embeddable_manifest(
- &mut self,
- signer: &dyn RemoteSigner,
- ) -> Result<Vec<u8>> {
+ pub fn get_box_hashed_embeddable_manifest(&mut self, signer: &dyn Signer) -> Result<Vec<u8>> {
let pc = self.provenance_claim().ok_or(Error::ClaimEncoding)?;
// make sure there is only one
@@ -1743,8 +1739,7 @@ impl Store {
let mut jumbf_bytes = self.to_jumbf_internal(signer.reserve_size())?;
// sign contents
- let claim_bytes = pc.data()?;
- let sig = signer.sign_remote(&claim_bytes).await?;
+ let sig = self.sign_claim(pc, signer, signer.reserve_size())?;
let sig_placeholder = Store::sign_claim_placeholder(pc, signer.reserve_size());
if sig_placeholder.len() != sig.len() {
@@ -2895,8 +2890,8 @@ pub mod tests {
hash_utils::Hasher,
patch::patch_file,
test::{
- create_test_claim, fixture_path, temp_dir_path, temp_fixture_path,
- temp_remote_signer, temp_signer, write_jpeg_placeholder_file,
+ create_test_claim, fixture_path, temp_dir_path, temp_fixture_path, temp_signer,
+ write_jpeg_placeholder_file,
},
},
AssertionJson, SigningAlg,
@@ -3988,24 +3983,6 @@ pub mod tests {
}
#[test]
- fn test_modify_xmp() {
- // modify the XMP (change xmp magic id value) - this should cause a data hash mismatch (OTGP)
- let mut report = patch_and_report(
- "cloud.jpg",
- b"W5M0MpCehiHzreSzNTczkc9d",
- b"W5M0MpCehiHzreSzNTczkXXX",
- );
- assert!(!report.get_log().is_empty());
- let errors = report_split_errors(report.get_log_mut());
-
- assert!(errors[0].error_str().unwrap().starts_with("HashMismatch"));
- assert_eq!(
- errors[0].validation_status.as_deref(),
- Some(validation_status::ASSERTION_DATAHASH_MISMATCH)
- ); // what validation status should we have for this?
- }
-
- #[test]
fn test_claim_modified() {
// replace the title that is inside the claim data - should cause signature to not match
let mut report = patch_and_report("C.jpg", b"C.jpg", b"X.jpg");
@@ -4472,10 +4449,9 @@ pub mod tests {
}
}
}
-
- #[actix::test]
+ #[test]
#[cfg(feature = "file_io")]
- async fn test_boxhash_embeddable_manifest() {
+ fn test_boxhash_embeddable_manifest() {
// test adding to actual image
let ap = fixture_path("boxhash.jpg");
let box_hash_path = fixture_path("boxhash.json");
@@ -4495,12 +4471,11 @@ pub mod tests {
store.commit_claim(claim).unwrap();
// Do we generate JUMBF?
- let signer = temp_remote_signer();
+ let signer = temp_signer();
// get the embeddable manifest
let em = store
.get_box_hashed_embeddable_manifest(signer.as_ref())
- .await
.unwrap();
// get composed version for embedding to JPEG
@@ -4554,13 +4529,14 @@ pub mod tests {
assert!(errors.is_empty());
}
- #[actix::test]
- async fn test_datahash_embeddable_manifest() {
+ #[test]
+ #[cfg(feature = "file_io")]
+ fn test_datahash_embeddable_manifest() {
// test adding to actual image
let ap = fixture_path("cloud.jpg");
// Do we generate JUMBF?
- let signer = temp_remote_signer();
+ let signer = temp_signer();
// Create claims store.
let mut store = Store::new();
@@ -4606,7 +4582,6 @@ pub mod tests {
"jpeg",
Some(&mut output_file),
)
- .await
.unwrap();
// path in new composed manifest
@@ -4620,15 +4595,16 @@ pub mod tests {
assert!(errors.is_empty());
}
- #[actix::test]
- async fn test_datahash_embeddable_manifest_user_hashed() {
+ #[test]
+ #[cfg(feature = "file_io")]
+ fn test_datahash_embeddable_manifest_user_hashed() {
// test adding to actual image
let ap = fixture_path("cloud.jpg");
let mut hasher = Hasher::SHA256(Sha256::new());
// Do we generate JUMBF?
- let signer = temp_remote_signer();
+ let signer = temp_signer();
// Create claims store.
let mut store = Store::new();
@@ -4670,7 +4646,6 @@ pub mod tests {
// get the embeddable manifest, using user hashing
let cm = store
.get_data_hashed_embeddable_manifest(&dh, signer.as_ref(), "jpeg", None)
- .await
.unwrap();
// path in new composed manifest