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 b276d47adc82dbb94b5930b321d48ae0b4fb6b87
parent db03f1f59fb00d850285de13693d109187f6e09a
Author: Eric Scouten <scouten@adobe.com>
Date:   Wed, 25 Oct 2023 16:26:48 -0400

(IGNORE) Refactor implementation of update_data_hash and update_bmff_hash (#330)

FYI this PR also removes the CI step titled "Check for unknown features in cfg attributes and macros."

A recent change to `cargo check` syntax appears to interoperate badly with some things we need in docs.rs.
Diffstat:
M.github/workflows/ci.yml | 15---------------
Msdk/src/claim.rs | 160+++++++++++++++++++++++++++++++++++++++----------------------------------------
2 files changed, 79 insertions(+), 96 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml @@ -246,21 +246,6 @@ jobs: version: latest args: --all-targets --all-features - unknown-features-cfg: - name: Check for unknown features in cfg attributes and macros - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@nightly - - - name: Check for unknown features - env: - RUSTFLAGS: "-D unexpected-cfgs" - run: cargo +nightly check -Z unstable-options -Z check-cfg=features --tests - version_bump: name: Ensure (MINOR) tag is used when making an API breaking change # Change all of these steps to (MAJOR) after 1.0 release diff --git a/sdk/src/claim.rs b/sdk/src/claim.rs @@ -855,94 +855,92 @@ impl Claim { self.assertion_store.push(assertion); } - // crate private function to allow for patching a data hash with final contents - pub(crate) fn update_data_hash(&mut self, mut data_hash: DataHash) -> Result<()> { - let mut replacement_assertion = data_hash.to_assertion()?; + // Patch an existing assertion with new contents. + // + // `replace_with` should match in name and size of an existing assertion. + fn update_assertion<MatchFn, PatchFn>( + &mut self, + replace_with: Assertion, + match_fn: MatchFn, + patch_fn: PatchFn, + ) -> Result<()> + where + MatchFn: Fn(&ClaimAssertion) -> bool, + PatchFn: FnOnce(&ClaimAssertion, Assertion) -> Result<Assertion>, + { + // Find the assertion that should be replaced. + let Some(ref mut target_assertion) = self + .assertion_store + .iter_mut() + .find(|ca| Assertion::assertions_eq(&replace_with, ca.assertion()) && match_fn(ca)) + else { + return Err(Error::NotFound); + }; - match self.assertion_store.iter_mut().find(|assertion| { - // is this a DataHash Assertion - if !Assertion::assertions_eq(&replacement_assertion, assertion.assertion()) { - return false; - } + // Save off copy of original hash to cross-check before + // replacing it. + let original_hash = target_assertion.hash().to_vec(); + + // Give caller a chance to patch/replace the assertion. + let replace_with = patch_fn(target_assertion, replace_with)?; + + // Calculate new hash, given new content. + let replacement_hash = Claim::calc_assertion_box_hash( + &target_assertion.label(), + &replace_with, + target_assertion.salt().clone(), + target_assertion.hash_alg(), + )?; + + target_assertion.update_assertion(replace_with, replacement_hash)?; + + let target_label = target_assertion.label(); + let target_hash = target_assertion.hash(); + + // Replace the existing hash in the hashed URI reference + // with the newly-calculated hash. + let Some(f) = self + .assertions + .iter_mut() + .find(|f| f.url().contains(&target_label) && vec_compare(&f.hash(), &original_hash)) + else { + return Err(Error::NotFound); + }; - if let Ok(dh) = DataHash::from_assertion(assertion.assertion()) { - dh.name == data_hash.name - } else { - false - } - }) { - Some(ref mut dh_assertion) => { - let original_hash = dh_assertion.hash().to_vec(); - let original_len = dh_assertion.assertion().data().len(); - data_hash.pad_to_size(original_len)?; - replacement_assertion = data_hash.to_assertion()?; - - let replacement_hash = Claim::calc_assertion_box_hash( - &dh_assertion.label(), - &replacement_assertion, - dh_assertion.salt().clone(), - dh_assertion.hash_alg(), - )?; - dh_assertion.update_assertion(replacement_assertion, replacement_hash)?; - - // fix up hashed uri - match self.assertions.iter_mut().find_map(|f| { - if f.url().contains(&dh_assertion.label()) - && vec_compare(&f.hash(), &original_hash) - { - // replace with newly updated hash - f.update_hash(dh_assertion.hash().to_vec()); - Some(f) - } else { - None - } - }) { - Some(_) => Ok(()), - None => Err(Error::NotFound), + // Replace existing hash with newly-calculated hash. + f.update_hash(target_hash.to_vec()); + Ok(()) + } + + // Crate private function to allow for patching a data hash with final contents. + pub(crate) fn update_data_hash(&mut self, mut data_hash: DataHash) -> Result<()> { + let dh_name = data_hash.name.clone(); + + self.update_assertion( + data_hash.to_assertion()?, + |ca: &ClaimAssertion| { + if let Ok(dh) = DataHash::from_assertion(ca.assertion()) { + dh.name == dh_name + } else { + false } - } - None => Err(Error::NotFound), - } + }, + |target_assertion: &ClaimAssertion, _: Assertion| { + let original_len = target_assertion.assertion().data().len(); + data_hash.pad_to_size(original_len)?; + data_hash.to_assertion() + }, + ) } - // crate private function to allow for patching a BMFF hash with final contents + // Crate private function to allow for patching a BMFF hash with final contents. #[cfg(feature = "file_io")] pub(crate) fn update_bmff_hash(&mut self, bmff_hash: BmffHash) -> Result<()> { - let replacement_assertion = bmff_hash.to_assertion()?; - - match self.assertion_store.iter_mut().find(|assertion| { - // is this a BMFFHash Assertion - Assertion::assertions_eq(&replacement_assertion, assertion.assertion()) - }) { - Some(ref mut bmff_assertion) => { - let original_hash = bmff_assertion.hash().to_vec(); - - let replacement_hash = Claim::calc_assertion_box_hash( - &bmff_assertion.label(), - &replacement_assertion, - bmff_assertion.salt().clone(), - bmff_assertion.hash_alg(), - )?; - bmff_assertion.update_assertion(replacement_assertion, replacement_hash)?; - - // fix up hashed uri - match self.assertions.iter_mut().find_map(|f| { - if f.url().contains(&bmff_assertion.label()) - && vec_compare(&f.hash(), &original_hash) - { - // replace with newly updated hash - f.update_hash(bmff_assertion.hash().to_vec()); - Some(f) - } else { - None - } - }) { - Some(_) => Ok(()), - None => Err(Error::NotFound), - } - } - None => Err(Error::NotFound), - } + self.update_assertion( + bmff_hash.to_assertion()?, + |_: &ClaimAssertion| true, + |_: &ClaimAssertion, a: Assertion| Ok(a), + ) } /// Redact an assertion from a prior claim.