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 adafc0c829e81f34868c442ec6918094a4f5c653
parent 3dc7bf2335cc23bf0d49c8cc5414cfb0b0d2115f
Author: Dave Kozma <dkozma@adobe.com>
Date:   Thu, 22 Feb 2024 20:31:08 -0500

(MINOR) Update `xmp_toolkit` to v1.7.1, remove Ring dependency, fix build errors (#407)

* Update `xmp_toolkit` to v1.7.1 to resolve build issue
* Update Wasm to use Crypto::getRandomValues
* Remove dependency on ring
* Removed redundant imports
* Add `truncate(true)` calls to `OpenOptions`
* Update MSRV to 1.73.0
* Pin `id3` to v1.12.0
Diffstat:
M.github/workflows/ci.yml | 4++--
MREADME.md | 2+-
Mexport_schema/Cargo.toml | 2+-
Mmake_test_images/Cargo.toml | 9++++++---
Msdk/Cargo.toml | 16++++++++++------
Msdk/examples/data_hash.rs | 2++
Msdk/src/assertions/actions.rs | 2+-
Msdk/src/assertions/data_hash.rs | 5+----
Msdk/src/assertions/ingredient.rs | 2+-
Msdk/src/assertions/thumbnail.rs | 1-
Msdk/src/assertions/user_cbor.rs | 1-
Msdk/src/asset_handlers/bmff_io.rs | 1-
Msdk/src/asset_handlers/jpeg_io.rs | 4----
Msdk/src/ingredient.rs | 1-
Msdk/src/jumbf/boxes.rs | 1-
Msdk/src/manifest.rs | 2++
Msdk/src/openssl/ec_signer.rs | 2+-
Msdk/src/openssl/ec_validator.rs | 2+-
Msdk/src/openssl/ed_signer.rs | 2+-
Msdk/src/openssl/ed_validator.rs | 2+-
Msdk/src/salt.rs | 17++++++++++++++---
Msdk/src/store.rs | 14++++++++------
Msdk/src/time_stamp.rs | 8+++-----
Msdk/src/wasm/context.rs | 16++++++++++------
Msdk/src/wasm/mod.rs | 2++
Asdk/src/wasm/util.rs | 44++++++++++++++++++++++++++++++++++++++++++++
26 files changed, 112 insertions(+), 52 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: fail-fast: false matrix: os: [windows-latest, macos-latest, ubuntu-latest] - rust_version: [stable, 1.70.0] + rust_version: [stable, 1.73.0] # exclude: # - os: windows-latest # rust_version: stable @@ -57,7 +57,7 @@ jobs: fail-fast: false matrix: target: [aarch64-unknown-linux-gnu] - rust_version: [stable, 1.70.0] + rust_version: [stable, 1.73.0] steps: - name: Checkout repository diff --git a/README.md b/README.md @@ -29,7 +29,7 @@ We welcome contributions to this project. For information on contributing, prov ## Requirements -The library requires **Rust version 1.70.0** or newer. +The library requires **Rust version 1.73.0** or newer. ### Supported platforms diff --git a/export_schema/Cargo.toml b/export_schema/Cargo.toml @@ -4,7 +4,7 @@ version = "0.28.5" authors = ["Dave Kozma <dkozma@adobe.com>"] license = "MIT OR Apache-2.0" edition = "2018" -rust-version = "1.70.0" +rust-version = "1.73.0" [dependencies] anyhow = "1.0.40" diff --git a/make_test_images/Cargo.toml b/make_test_images/Cargo.toml @@ -4,7 +4,7 @@ version = "0.28.5" authors = ["Gavin Peacock <gpeacock@adobe.com>"] license = "MIT OR Apache-2.0" edition = "2021" -rust-version = "1.70.0" +rust-version = "1.73.0" [dependencies] anyhow = "1.0.40" @@ -15,8 +15,11 @@ c2pa = { path = "../sdk", features = [ "xmp_write", ] } env_logger = "0.10" -log = "0.4.8" -image = { version = "0.24.7", default-features = false, features = ["jpeg", "png"] } +log = "0.4.8" +image = { version = "0.24.7", default-features = false, features = [ + "jpeg", + "png", +] } memchr = "2.7.1" nom = "7.1.3" regex = "1.5.6" diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml @@ -17,7 +17,7 @@ readme = "../README.md" keywords = ["xmp", "metadata"] categories = ["api-bindings"] edition = "2021" -rust-version = "1.70.0" +rust-version = "1.73.0" exclude = ["tests/fixtures"] [package.metadata.docs.rs] @@ -77,7 +77,8 @@ coset = "0.3.1" extfmt = "0.1.1" fast-xml = "0.23.1" hex = "0.4.3" -id3 = "1.7.0" +# Version 1.13.0 doesn't compile under Rust < 1.75, pinning to 1.12.0 +id3 = "=1.12.0" img-parts = "0.3.0" jfifdump = "0.5.1" log = "0.4.8" @@ -88,11 +89,12 @@ multibase = "0.9.0" multihash = "0.11.4" mp4 = "0.13.0" png_pong = "0.8.2" +rand = "0.8.5" +rand_chacha = "0.3.1" range-set = "0.0.9" rasn-ocsp = "0.12.4" rasn-pkix = "0.12.4" rasn = "0.12.4" -ring = "0.16.20" riff = "1.0.1" schemars = { version = "0.8.13", optional = true } serde = { version = "1.0.137", features = ["derive"] } @@ -112,10 +114,13 @@ x509-certificate = "0.19.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] ureq = "2.4.0" -image = { version = "0.24.7", default-features = false, features = ["jpeg", "png"], optional = true } +image = { version = "0.24.7", default-features = false, features = [ + "jpeg", + "png", +], optional = true } instant = "0.1.12" openssl = { version = "0.10.61", features = ["vendored"], optional = true } -xmp_toolkit = { version = "1.6", optional = true } +xmp_toolkit = { version = "1.7.1", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] console_log = { version = "1.0.0", features = ["color"] } @@ -124,7 +129,6 @@ getrandom = { version = "0.2.7", features = ["js"] } # to handle certificate timestamp checking correctly. instant = { version = "0.1.12", features = ["wasm-bindgen", "inaccurate"] } js-sys = "0.3.58" -rand = "0.8.5" rsa = "0.6.1" serde-wasm-bindgen = "0.5.0" spki = "0.6.0" diff --git a/sdk/examples/data_hash.rs b/sdk/examples/data_hash.rs @@ -61,6 +61,7 @@ fn user_data_hash_with_sdk_hashing() { .read(true) .write(true) .create(true) + .truncate(true) .open(&dest) .unwrap(); @@ -178,6 +179,7 @@ fn user_data_hash_with_user_hashing() { .read(true) .write(true) .create(true) + .truncate(true) .open(&dest) .unwrap(); diff --git a/sdk/src/assertions/actions.rs b/sdk/src/assertions/actions.rs @@ -486,7 +486,7 @@ pub mod tests { use super::*; use crate::{ - assertion::{Assertion, AssertionData}, + assertion::AssertionData, assertions::metadata::{c2pa_source::GENERATOR_REE, DataSource, ReviewRating}, hashed_uri::HashedUri, }; diff --git a/sdk/src/assertions/data_hash.rs b/sdk/src/assertions/data_hash.rs @@ -286,10 +286,7 @@ pub mod tests { #![allow(clippy::unwrap_used)] use super::*; - use crate::{ - assertion::{Assertion, AssertionData}, - utils::test::fixture_path, - }; + use crate::{assertion::AssertionData, utils::test::fixture_path}; #[test] fn test_build_assertion() { diff --git a/sdk/src/assertions/ingredient.rs b/sdk/src/assertions/ingredient.rs @@ -175,7 +175,7 @@ pub mod tests { #![allow(clippy::unwrap_used)] use super::*; - use crate::assertion::{AssertionCbor, AssertionData}; + use crate::assertion::AssertionData; #[test] fn assertion_ingredient() { diff --git a/sdk/src/assertions/thumbnail.rs b/sdk/src/assertions/thumbnail.rs @@ -88,7 +88,6 @@ pub mod tests { #![allow(clippy::unwrap_used)] use super::*; - use crate::assertions::labels; // a binary assertion ('deadbeefadbeadbe') fn some_binary_data() -> Vec<u8> { diff --git a/sdk/src/assertions/user_cbor.rs b/sdk/src/assertions/user_cbor.rs @@ -75,7 +75,6 @@ pub mod tests { #![allow(clippy::unwrap_used)] use super::*; - use crate::assertion::Assertion; const LABEL: &str = "user_test_assertion"; const DATA: &str = r#"{ "l1":"some data", "l2":"some other data" }"#; diff --git a/sdk/src/asset_handlers/bmff_io.rs b/sdk/src/asset_handlers/bmff_io.rs @@ -14,7 +14,6 @@ use std::{ cmp::min, collections::HashMap, - convert::{From, TryFrom}, fs::{File, OpenOptions}, io::{Read, Seek, SeekFrom, Write}, path::Path, diff --git a/sdk/src/asset_handlers/jpeg_io.rs b/sdk/src/asset_handlers/jpeg_io.rs @@ -13,7 +13,6 @@ use std::{ collections::HashMap, - convert::{From, TryFrom}, fs::File, io::{BufReader, Cursor, Write}, path::*, @@ -1036,10 +1035,7 @@ pub mod tests { use std::io::{Read, Seek}; - use img_parts::Bytes; - use super::*; - use crate::asset_io::RemoteRefEmbedType; #[test] fn test_extract_xmp() { diff --git a/sdk/src/ingredient.rs b/sdk/src/ingredient.rs @@ -1338,7 +1338,6 @@ mod tests { use wasm_bindgen_test::*; use super::*; - use crate::assertions::Metadata; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); diff --git a/sdk/src/jumbf/boxes.rs b/sdk/src/jumbf/boxes.rs @@ -24,7 +24,6 @@ use std::{ any::Any, - convert::TryInto, ffi::CString, fmt, io::{Read, Result as IoResult, Seek, SeekFrom, Write}, diff --git a/sdk/src/manifest.rs b/sdk/src/manifest.rs @@ -2297,6 +2297,7 @@ pub(crate) mod tests { .read(true) .write(true) .create(true) + .truncate(true) .open(&output) .unwrap(); @@ -2353,6 +2354,7 @@ pub(crate) mod tests { .read(true) .write(true) .create(true) + .truncate(true) .open(&output) .unwrap(); diff --git a/sdk/src/openssl/ec_signer.rs b/sdk/src/openssl/ec_signer.rs @@ -197,7 +197,7 @@ mod tests { #![allow(clippy::unwrap_used)] use super::*; - use crate::{openssl::temp_signer, utils::test::fixture_path, SigningAlg}; + use crate::{openssl::temp_signer, utils::test::fixture_path}; #[test] fn es256_signer() { diff --git a/sdk/src/openssl/ec_validator.rs b/sdk/src/openssl/ec_validator.rs @@ -76,7 +76,7 @@ fn wrap_openssl_err(err: openssl::error::ErrorStack) -> Error { mod tests { #![allow(clippy::unwrap_used)] use super::*; - use crate::{openssl::temp_signer, utils::test::fixture_path, Signer, SigningAlg}; + use crate::{openssl::temp_signer, utils::test::fixture_path, Signer}; #[test] fn sign_and_validate_es256() { diff --git a/sdk/src/openssl/ed_signer.rs b/sdk/src/openssl/ed_signer.rs @@ -108,7 +108,7 @@ fn wrap_openssl_err(err: openssl::error::ErrorStack) -> Error { mod tests { #![allow(clippy::unwrap_used)] use super::*; - use crate::{openssl::temp_signer, utils::test::fixture_path, SigningAlg}; + use crate::{openssl::temp_signer, utils::test::fixture_path}; #[test] fn ed25519_signer() { diff --git a/sdk/src/openssl/ed_validator.rs b/sdk/src/openssl/ed_validator.rs @@ -44,7 +44,7 @@ mod tests { #![allow(clippy::unwrap_used)] use super::*; - use crate::{openssl::temp_signer, utils::test::fixture_path, Signer, SigningAlg}; + use crate::{openssl::temp_signer, utils::test::fixture_path, Signer}; #[test] fn sign_and_validate() { diff --git a/sdk/src/salt.rs b/sdk/src/salt.rs @@ -15,6 +15,7 @@ /// a funtion to generate a salt value used when hashing /// data. Providing a unique salt ensures a unique hash for /// a given data set. + pub trait SaltGenerator { /// generate a salt vector fn generate_salt(&self) -> Option<Vec<u8>>; @@ -59,13 +60,23 @@ impl SaltGenerator for DefaultSalt { { let mut salt = vec![0u8; self.salt_len]; openssl::rand::rand_bytes(&mut salt).ok()?; + + Some(salt) + } + #[cfg(all(not(feature = "openssl_sign"), target_arch = "wasm32"))] + { + let salt = crate::wasm::util::get_random_values(self.salt_len).ok()?; + Some(salt) } - #[cfg(not(feature = "openssl_sign"))] + #[cfg(all(not(feature = "openssl_sign"), not(target_arch = "wasm32")))] { - use ring::rand::SecureRandom; + use rand::prelude::*; + let mut salt = vec![0u8; self.salt_len]; - ring::rand::SystemRandom::new().fill(&mut salt).ok()?; + let mut rng = rand_chacha::ChaCha20Rng::from_entropy(); + rng.fill_bytes(&mut salt); + Some(salt) } } diff --git a/sdk/src/store.rs b/sdk/src/store.rs @@ -3034,12 +3034,9 @@ pub mod tests { use super::*; use crate::{ - assertions::{labels::BOX_HASH, Action, Actions, BoxHash, Ingredient, Uuid}, - claim::{AssertionStoreJsonFormat, Claim}, - jumbf_io::{ - get_assetio_handler_from_path, load_jumbf_from_file, save_jumbf_to_file, - update_file_jumbf, - }, + assertions::{labels::BOX_HASH, Action, Actions, BoxHash, Uuid}, + claim::AssertionStoreJsonFormat, + jumbf_io::{get_assetio_handler_from_path, update_file_jumbf}, status_tracker::*, utils::{ hash_utils::Hasher, @@ -4806,6 +4803,7 @@ pub mod tests { .read(true) .write(true) .create(true) + .truncate(true) .open(&output) .unwrap(); output_file.write_all(&out_stream.into_inner()).unwrap(); @@ -4886,6 +4884,7 @@ pub mod tests { .read(true) .write(true) .create(true) + .truncate(true) .open(&output) .unwrap(); output_file.write_all(&out_stream.into_inner()).unwrap(); @@ -4925,6 +4924,7 @@ pub mod tests { .read(true) .write(true) .create(true) + .truncate(true) .open(&output) .unwrap(); @@ -4987,6 +4987,7 @@ pub mod tests { .read(true) .write(true) .create(true) + .truncate(true) .open(&output) .unwrap(); @@ -5055,6 +5056,7 @@ pub mod tests { .read(true) .write(true) .create(true) + .truncate(true) .open(&output) .unwrap(); diff --git a/sdk/src/time_stamp.rs b/sdk/src/time_stamp.rs @@ -11,8 +11,6 @@ // specific language governing permissions and limitations under // each license. -use std::convert::TryFrom; - use async_generic::async_generic; use bcder::decode::Constructed; use coset::{sig_structure_data, ProtectedHeader}; @@ -182,15 +180,15 @@ pub(crate) fn time_stamp_message_http( message: &[u8], digest_algorithm: DigestAlgorithm, ) -> Result<Vec<u8>> { - use ring::rand::SecureRandom; + use rand::{thread_rng, Rng}; let mut h = digest_algorithm.digester(); h.update(message); let digest = h.finish(); let mut random = [0u8; 8]; - ring::rand::SystemRandom::new() - .fill(&mut random) + thread_rng() + .try_fill(&mut random) .map_err(|_| Error::CoseTimeStampGeneration)?; let request = crate::asn1::rfc3161::TimeStampReq { diff --git a/sdk/src/wasm/context.rs b/sdk/src/wasm/context.rs @@ -12,7 +12,7 @@ // each license. use wasm_bindgen::{prelude::*, JsCast, JsValue}; -use web_sys::{SubtleCrypto, Window, WorkerGlobalScope}; +use web_sys::{Crypto, SubtleCrypto, Window, WorkerGlobalScope}; use crate::{Error, Result}; @@ -51,13 +51,17 @@ impl WindowOrWorker { } } - pub fn subtle_crypto(&self) -> Result<SubtleCrypto> { - let crypto = match self { + pub fn crypto(&self) -> Result<Crypto> { + match self { Self::Window(window) => window.crypto(), Self::Worker(worker) => worker.crypto(), - }; - let subtle_crypto = crypto.map_err(|_err| Error::WasmNoCrypto)?.subtle(); + } + .map_err(|_err| Error::WasmNoCrypto) + } + + pub fn subtle_crypto(&self) -> Result<SubtleCrypto> { + let crypto = self.crypto()?; - Ok(subtle_crypto) + Ok(crypto.subtle()) } } diff --git a/sdk/src/wasm/mod.rs b/sdk/src/wasm/mod.rs @@ -14,6 +14,8 @@ #[cfg(target_arch = "wasm32")] pub(crate) mod context; #[cfg(target_arch = "wasm32")] +pub(crate) mod util; +#[cfg(target_arch = "wasm32")] pub(crate) mod webcrypto_validator; #[cfg(target_arch = "wasm32")] pub use webcrypto_validator::validate_async; diff --git a/sdk/src/wasm/util.rs b/sdk/src/wasm/util.rs @@ -0,0 +1,44 @@ +use web_sys::Crypto; + +use crate::{wasm::context::WindowOrWorker, Error, Result}; + +pub fn get_random_values(len: usize) -> Result<Vec<u8>> { + let context = WindowOrWorker::new(); + let crypto: Crypto = context?.crypto()?; + let mut values = vec![0u8; len]; + crypto + .get_random_values_with_u8_array(&mut values) + .map_err(|_err| Error::WasmNoCrypto)?; + + Ok(values) +} + +#[cfg(test)] +pub mod tests { + #![allow(clippy::unwrap_used)] + + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::*; + + use super::*; + + #[cfg(target_arch = "wasm32")] + wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); + + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[wasm_bindgen_test] + fn test_get_random_values() { + let len: usize = 32; + let random1 = get_random_values(len).unwrap(); + let random2 = get_random_values(len).unwrap(); + let sum_fn = |sum: u32, i: &u8| sum + (*i as u32); + let sum1 = random1.iter().fold(0u32, sum_fn); + let sum2 = random2.iter().fold(0u32, sum_fn); + + assert_eq!(random1.len(), len); + assert_eq!(random2.len(), len); + assert_ne!(sum1, sum2); + assert!(sum1 > 0); + assert!(sum2 > 0); + } +}