commit a680db2bd6d6a82398e361ee604ce639c24fdef6
parent 7f12199f569d7b218379d2bbdd087804e9d5bd85
Author: Gavin Peacock <gpeacock@adobe.com>
Date: Fri, 17 Jun 2022 10:17:47 -0700
(MINOR) Remove temp_signer from sdk; update docs and examples to use get_signer_from_files (#52)
* Remove temp_signer from sdk.
Update docs and examples to use get_signer_from_files.
Move test_signer to utils::test and update unit tests.
* Proofreading doc comments
* Use correct heading (h1) for example
* Fix some outdated doc comments
Co-authored-by: Eric Scouten <scouten@adobe.com>
Diffstat:
11 files changed, 166 insertions(+), 168 deletions(-)
diff --git a/make_test_images/src/make_test_images.rs b/make_test_images/src/make_test_images.rs
@@ -15,8 +15,8 @@
//!
use c2pa::{
assertions::{c2pa_action, Action, Actions, CreativeWork, SchemaDotOrgPerson},
- get_temp_signer_by_alg, jumbf_io, Error, Ingredient, IngredientOptions, Manifest,
- ManifestStore,
+ get_signer_from_files, jumbf_io, Error, Ingredient, IngredientOptions, Manifest, ManifestStore,
+ Signer,
};
use anyhow::{Context, Result};
@@ -32,12 +32,13 @@ use twoway::find_bytes;
const IMAGE_WIDTH: u32 = 2048;
const IMAGE_HEIGHT: u32 = 1365;
-// returns a path to a file in the fixtures folder
-fn fixture_path(file_name: &str) -> PathBuf {
- let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
- path.push("../sdk/tests/fixtures");
- path.push(file_name);
- path
+fn get_signer_with_alg(alg: &str) -> c2pa::Result<Box<dyn Signer>> {
+ // sign and embed into the target file
+ let mut signcert_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+ signcert_path.push(format!("../sdk/tests/fixtures/certs/{}.pub", alg));
+ let mut pkey_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+ pkey_path.push(format!("../sdk/tests/fixtures/certs/{}.pem", alg));
+ get_signer_from_files(signcert_path, pkey_path, alg, None)
}
/// Defines an operation for creating a test image
@@ -265,10 +266,8 @@ impl MakeTestImages {
// add all our actions as an assertion now.
manifest.add_assertion(&actions)?; // extra get required here, since actions is an array
- // now create store; sign claim and embed in target
- let certs_dir = fixture_path("certs");
- let (signer, _) =
- get_temp_signer_by_alg(&certs_dir, &self.config.alg, self.config.tsa_url.clone());
+ // now sign manifest and embed in target
+ let signer = get_signer_with_alg(&self.config.alg)?;
manifest.embed(&dst_path, &dst_path, signer.as_ref())?;
diff --git a/sdk/examples/client/client.rs b/sdk/examples/client/client.rs
@@ -17,16 +17,9 @@ use anyhow::Result;
use c2pa::{
assertions::{c2pa_action, labels, Action, Actions, CreativeWork, SchemaDotOrgPerson},
- get_temp_signer, Ingredient, Manifest, ManifestStore,
+ get_signer_from_files, Ingredient, Manifest, ManifestStore,
};
use std::path::PathBuf;
-// returns a path to a file in the fixtures folder
-fn fixture_path(file_name: &str) -> PathBuf {
- let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
- path.push("../sdk/tests/fixtures");
- path.push(file_name);
- path
-}
const GENERATOR: &str = "test_app/0.1";
const INDENT_SPACE: usize = 2;
@@ -118,9 +111,11 @@ pub fn main() -> Result<()> {
.add_assertion(&creative_work)?;
// sign and embed into the target file
- let cert_dir = fixture_path("certs");
- let (signer, _) = get_temp_signer(&cert_dir);
- manifest.embed(&source, &dest, &signer)?;
+ let signcert_path = "../sdk/tests/fixtures/certs.ps256.pem";
+ let pkey_path = "../sdk/tests/fixtures/certs.ps256.pub";
+ let signer = get_signer_from_files(signcert_path, pkey_path, "ps256", None)?;
+
+ manifest.embed(&source, &dest, &*signer)?;
let manifest_store = ManifestStore::from_file(&dest)?;
diff --git a/sdk/src/asset_handlers/c2pa_io.rs b/sdk/src/asset_handlers/c2pa_io.rs
@@ -66,10 +66,9 @@ pub mod tests {
use tempfile::tempdir;
use crate::{
- openssl::temp_signer::get_temp_signer,
status_tracker::OneShotStatusTracker,
store::Store,
- utils::test::{fixture_path, temp_dir_path},
+ utils::test::{fixture_path, temp_dir_path, temp_signer},
};
#[test]
@@ -88,8 +87,7 @@ pub mod tests {
let store = Store::load_from_asset(&temp_path, false, &mut OneShotStatusTracker::new())
.expect("loading store");
- let cert_dir = fixture_path("certs");
- let (signer, _) = get_temp_signer(&cert_dir);
+ let signer = temp_signer();
let manifest2 = store.to_jumbf(&signer).expect("to_jumbf");
assert_eq!(&manifest, &manifest2);
diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs
@@ -45,7 +45,7 @@
//! # use c2pa::Result;
//! use c2pa::{
//! assertions::User,
-//! get_temp_signer,
+//! get_signer_from_files,
//! Manifest
//! };
//!
@@ -60,9 +60,13 @@
//! let dir = tempdir()?;
//! let dest = dir.path().join("test_file.jpg");
//!
-//! let cert_dir = PathBuf::from("tests/fixtures/certs");
-//! let (signer, _) = get_temp_signer(&cert_dir);
-//! manifest.embed(&source, &dest, &signer)?;
+//! // Create a ps256 signer using certs and key files
+//! let signcert_path = "tests/fixtures/certs/ps256.pub";
+//! let pkey_path = "tests/fixtures/certs/ps256.pem";
+//! let signer = get_signer_from_files(signcert_path, pkey_path, "ps256", None)?;
+//!
+//! // embed a manifest using the signer
+//! manifest.embed(&source, &dest, &*signer)?;
//! # Ok(())
//! # }
//! ```
@@ -94,10 +98,8 @@ pub(crate) mod ocsp_utils;
#[cfg(feature = "file_io")]
mod openssl;
#[cfg(feature = "file_io")]
-pub use crate::openssl::{
- signer::{get_signer, get_signer_from_files},
- temp_signer::{get_temp_signer, get_temp_signer_by_alg},
-};
+pub use crate::openssl::signer::{get_signer, get_signer_from_files};
+
#[cfg(feature = "file_io")]
mod signer;
#[cfg(feature = "async_signer")]
diff --git a/sdk/src/manifest.rs b/sdk/src/manifest.rs
@@ -542,28 +542,55 @@ impl Manifest {
Ok(store)
}
- /// Embed a signed manifest into the target file using a supplied signer
+ /// Embed a signed manifest into the target file using a supplied signer.
+ ///
+ /// # Example: Embed a manifest in a file
+ ///
+ /// ```
+ /// # use c2pa::Result;
+ /// use c2pa::{
+ /// assertions::User,
+ /// get_signer_from_files,
+ /// Manifest
+ /// };
+ /// # fn main() -> Result<()> {
+ /// let mut manifest = Manifest::new("my_app".to_owned());
+ /// manifest.add_assertion(&User::new("org.contentauth.mylabel", r#"{"my_tag":"Anything I want"}"#))?;
+ ///
+ /// let source = "tests/fixtures/C.jpg";
+ /// let dest = "../target/test_file.jpg";
+ ///
+ /// // Create a PS256 signer using certs and public key files.
+ /// let signcert_path = "tests/fixtures/certs/ps256.pub";
+ /// let pkey_path = "tests/fixtures/certs/ps256.pem";
+ /// let signer = get_signer_from_files(signcert_path, pkey_path, "ps256", None)?;
+ ///
+ /// // Embed a manifest using the signer.
+ /// manifest.embed(&source, &dest, &*signer)?;
+ /// # Ok(())
+ /// # }
+ /// ```
#[cfg(feature = "file_io")]
- pub fn embed(
+ pub fn embed<P: AsRef<Path>>(
&mut self,
- source_path: &Path,
- dest_path: &Path,
+ source_path: P,
+ dest_path: P,
signer: &dyn Signer,
) -> Result<Store> {
- if !source_path.exists() {
- let path = source_path.to_string_lossy().into_owned();
+ if !source_path.as_ref().exists() {
+ let path = source_path.as_ref().to_string_lossy().into_owned();
return Err(Error::FileNotFound(path));
}
// we need to copy the source to target before setting the asset info
- if !dest_path.exists() {
+ if !dest_path.as_ref().exists() {
std::fs::copy(&source_path, &dest_path)?;
}
// first add the information about the target file
- self.set_asset_from_path(dest_path);
+ self.set_asset_from_path(dest_path.as_ref());
// convert the manifest to a store
let mut store = self.to_store()?;
// sign and write our store to to the output image file
- store.save_to_asset(source_path, signer, dest_path.as_ref())?;
+ store.save_to_asset(source_path.as_ref(), signer, dest_path.as_ref())?;
// todo: update xmp
Ok(store)
@@ -620,10 +647,11 @@ pub(crate) mod tests {
#[cfg(feature = "file_io")]
use crate::{
- openssl::temp_signer::get_temp_signer,
status_tracker::{DetailedStatusTracker, StatusTracker},
store::Store,
- utils::test::{fixture_path, temp_dir_path, temp_fixture_path, TEST_SMALL_JPEG},
+ utils::test::{
+ fixture_path, temp_dir_path, temp_fixture_path, temp_signer, TEST_SMALL_JPEG,
+ },
Ingredient,
};
@@ -693,8 +721,7 @@ pub(crate) mod tests {
let test_output = dir.path().join("wc_embed_test.jpg");
//embed a claim generated from this manifest
- let cert_dir = fixture_path("certs");
- let (signer, _) = get_temp_signer(&cert_dir);
+ let signer = temp_signer();
let _store = manifest
.embed(&source_path, &test_output, &signer)
@@ -797,8 +824,7 @@ pub(crate) mod tests {
)
.expect("add_assertion");
- let cert_dir = fixture_path("certs");
- let (signer, _) = get_temp_signer(&cert_dir);
+ let signer = temp_signer();
let store1 = manifest.embed(&output, &output, &signer).expect("embed");
let claim1_label = store1.provenance_label().unwrap();
@@ -822,9 +848,7 @@ pub(crate) mod tests {
.expect("add_redaction");
//embed a claim in output2
- let cert_dir = fixture_path("certs");
- let (signer, _) = get_temp_signer(&cert_dir);
-
+ let signer = temp_signer();
let _store2 = manifest2.embed(&output2, &output2, &signer).expect("embed");
let mut report = DetailedStatusTracker::new();
diff --git a/sdk/src/openssl/mod.rs b/sdk/src/openssl/mod.rs
@@ -30,7 +30,8 @@ mod ed_validator;
pub(crate) use ed_validator::EdValidator;
pub mod signer;
-pub mod temp_signer;
+#[cfg(test)]
+pub(crate) mod temp_signer;
use openssl::x509::X509;
diff --git a/sdk/src/openssl/rsa_signer.rs b/sdk/src/openssl/rsa_signer.rs
@@ -212,13 +212,14 @@ mod tests {
use super::*;
- use crate::{openssl::temp_signer::get_temp_signer, utils::test::fixture_path, Signer};
+ use crate::{
+ utils::test::{fixture_path, temp_signer},
+ Signer,
+ };
#[test]
fn signer_from_files() {
- let cert_dir = fixture_path("certs");
-
- let (signer, _) = get_temp_signer(&cert_dir);
+ let signer = temp_signer();
let data = b"some sample content to sign";
let signature = signer.sign(data).unwrap();
diff --git a/sdk/src/openssl/temp_signer.rs b/sdk/src/openssl/temp_signer.rs
@@ -36,43 +36,8 @@ use std::path::{Path, PathBuf};
use crate::{
openssl::{EcSigner, EdSigner, RsaSigner},
signer::ConfigurableSigner,
- Signer,
};
-/// Create a [`Signer`] instance that can be used for testing purposes.
-///
-/// This is a suitable default for use when you need a [`Signer`], but
-/// don't care what the format is.
-///
-/// # Arguments
-///
-/// * `path` - A directory (which must already exist) to receive the temporary
-/// private key / certificate pair.
-///
-/// # Returns
-///
-/// Returns a tuple of `(signer, sign_cert_path)` where `signer` is
-/// the [`Signer`] instance and `sign_cert_path` is the path to the
-/// signing certificate.
-///
-/// # Panics
-///
-/// Can panic if unable to invoke OpenSSL executable properly.
-pub fn get_temp_signer<P: AsRef<Path>>(path: P) -> (RsaSigner, PathBuf) {
- let mut sign_cert_path = path.as_ref().to_path_buf();
- sign_cert_path.push("ps256");
- sign_cert_path.set_extension("pub");
-
- let mut pem_key_path = path.as_ref().to_path_buf();
- pem_key_path.push("ps256");
- pem_key_path.set_extension("pem");
-
- (
- RsaSigner::from_files(&sign_cert_path, &pem_key_path, "ps256".to_string(), None).unwrap(),
- sign_cert_path,
- )
-}
-
/// Create an OpenSSL ES256 signer that can be used for testing purposes.
///
/// # Arguments
@@ -210,50 +175,3 @@ pub fn get_rsa_signer<P: AsRef<Path>>(
sign_cert_path,
)
}
-
-/// Create a signer that can be used for testing purposes.
-///
-/// Can generate a [`Signer`] instance for all supported formats.
-///
-/// # Arguments
-///
-/// * `path` - A directory (which must already exist) to receive the temporary
-/// private key / certificate pair.
-/// * `alg` - A format for signing. Must be one of (`rs256`, `rs384`, `rs512`,
-/// `ps256`, `ps384`, `ps512`, `es256`, `es384`, `es512`, or `ed25519`).
-/// * `tsa_url` - Optional URL for a timestamp authority.
-///
-/// # Returns
-///
-/// Returns a tuple of `(signer, sign_cert_path)` where `signer` is
-/// the [`Signer`] instance and `sign_cert_path` is the path to the
-/// signing certificate.
-///
-/// # Panics
-///
-/// Can panic if unable to invoke OpenSSL executable properly.
-pub fn get_temp_signer_by_alg<P: AsRef<Path>>(
- path: P,
- alg: &str,
- tsa_url: Option<String>,
-) -> (Box<dyn Signer>, PathBuf) {
- match alg.to_lowercase().as_str() {
- "ps256" | "ps384" | "ps512" => {
- let (signer, sign_cert_path) = get_rsa_signer(path, alg, tsa_url);
- (Box::new(signer), sign_cert_path)
- }
- "es256" | "es384" | "es512" => {
- let (signer, sign_cert_path) = get_ec_signer(path, alg, tsa_url);
- (Box::new(signer), sign_cert_path)
- }
-
- "ed25519" => {
- let (signer, sign_cert_path) = get_ed_signer(path, alg, tsa_url);
- (Box::new(signer), sign_cert_path)
- }
- _ => {
- let (signer, sign_cert_path) = get_rsa_signer(path, "ps256", tsa_url);
- (Box::new(signer), sign_cert_path)
- }
- }
-}
diff --git a/sdk/src/store.rs b/sdk/src/store.rs
@@ -1721,15 +1721,15 @@ pub mod tests {
use crate::{
assertions::{Action, Actions, Ingredient, Uuid},
- claim::Claim,
- jumbf_io::{load_jumbf_from_file, save_jumbf_to_file},
+ claim::{AssertionStoreJsonFormat, Claim},
+ jumbf_io::{load_jumbf_from_file, save_jumbf_to_file, update_file_jumbf},
status_tracker::*,
- utils::test::{create_test_claim, fixture_path, temp_dir_path, temp_fixture_path},
- };
-
- use crate::{
- claim::AssertionStoreJsonFormat, jumbf_io::update_file_jumbf,
- openssl::temp_signer::get_temp_signer, utils::patch::patch_file,
+ utils::{
+ patch::patch_file,
+ test::{
+ create_test_claim, fixture_path, temp_dir_path, temp_fixture_path, temp_signer,
+ },
+ },
};
fn create_editing_claim(claim: &mut Claim) -> Result<&mut Claim> {
@@ -1779,8 +1779,7 @@ pub mod tests {
create_capture_claim(&mut claim_capture).unwrap();
// Do we generate JUMBF?
- let cert_dir = fixture_path("certs");
- let (signer, _) = get_temp_signer(&cert_dir);
+ let signer = temp_signer();
// Test generate JUMBF
// Get labels for label test
@@ -2072,8 +2071,7 @@ pub mod tests {
create_capture_claim(&mut claim_capture).unwrap();
// Do we generate JUMBF?
- let cert_dir = fixture_path("certs");
- let (signer, _) = get_temp_signer(&cert_dir);
+ let signer = temp_signer();
// Move the claim to claims list. Note this is not real, the claims would have to be signed in between commmits
store.commit_claim(claim1).unwrap();
@@ -2228,9 +2226,7 @@ pub mod tests {
fn test_verifiable_credentials() {
use crate::utils::test::create_test_store;
- let cert_dir = fixture_path("certs");
-
- let (signer, _) = get_temp_signer(&cert_dir);
+ let signer = temp_signer();
// test adding to actual image
let ap = fixture_path("earth_apollo17.jpg");
@@ -2282,9 +2278,7 @@ pub mod tests {
fn test_update_manifest() {
use crate::{hashed_uri::HashedUri, utils::test::create_test_store};
- let cert_dir = fixture_path("certs");
-
- let (signer, _) = get_temp_signer(&cert_dir);
+ let signer = temp_signer();
// test adding to actual image
let ap = fixture_path("earth_apollo17.jpg");
diff --git a/sdk/src/utils/test.rs b/sdk/src/utils/test.rs
@@ -20,6 +20,14 @@ use crate::{
store::Store,
Result,
};
+
+#[cfg(feature = "file_io")]
+use crate::{
+ get_signer_from_files,
+ openssl::RsaSigner,
+ signer::{ConfigurableSigner, Signer},
+};
+
use std::path::PathBuf;
use tempfile::TempDir;
@@ -164,6 +172,63 @@ pub fn temp_fixture_path(temp_dir: &TempDir, file_name: &str) -> PathBuf {
fixture_copy
}
+/// Create a [`Signer`] instance that can be used for testing purposes.
+///
+/// This is a suitable default for use when you need a [`Signer`], but
+/// don't care what the format is.
+///
+/// # Returns
+///
+/// Returns a boxed [`Signer`] instance.
+///
+/// # Panics
+///
+/// Can panic if the certs cannot be read. (This function should only
+/// be used as part of testing infrastructure.)
+#[cfg(feature = "file_io")]
+pub fn temp_signer() -> RsaSigner {
+ #![allow(clippy::expect_used)]
+ let mut sign_cert_path = fixture_path("certs");
+ sign_cert_path.push("ps256");
+ sign_cert_path.set_extension("pub");
+
+ let mut pem_key_path = fixture_path("certs");
+ pem_key_path.push("ps256");
+ pem_key_path.set_extension("pem");
+
+ RsaSigner::from_files(&sign_cert_path, &pem_key_path, "ps256".to_string(), None)
+ .expect("get_temp_signer")
+}
+
+/// Create a [`Signer`] instance for a specific algorithm that can be used for testing purposes.
+///
+/// # Parameters:
+/// alg: The algorithm to use
+///
+/// # Returns
+///
+/// Returns a boxed [`Signer`] instance.
+///
+/// # Panics
+///
+/// Can panic if the certs cannot be read. (This function should only
+/// be used as part of testing infrastructure.)
+#[cfg(feature = "file_io")]
+pub fn temp_signer_with_alg(alg: &str) -> Box<dyn Signer> {
+ #![allow(clippy::expect_used)]
+ // sign and embed into the target file
+ let mut sign_cert_path = fixture_path("certs");
+ sign_cert_path.push(alg);
+ sign_cert_path.set_extension("pub");
+
+ let mut pem_key_path = fixture_path("certs");
+ pem_key_path.push(alg);
+ pem_key_path.set_extension("pem");
+
+ get_signer_from_files(sign_cert_path.clone(), pem_key_path, alg, None)
+ .expect("get_temp_signer_with_alg")
+}
+
#[test]
fn test_create_test_store() {
#[allow(clippy::expect_used)]
diff --git a/sdk/tests/integration.rs b/sdk/tests/integration.rs
@@ -18,18 +18,21 @@ mod integration_1 {
use c2pa::{
assertions::{c2pa_action, Action, Actions},
- get_temp_signer, Ingredient, Manifest, ManifestStore, Result,
+ get_signer_from_files, Ingredient, Manifest, ManifestStore, Result, Signer,
};
use std::path::PathBuf;
use tempfile::tempdir;
const GENERATOR: &str = "app";
- fn fixture_path(file_name: &str) -> PathBuf {
- let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
- path.push("tests/fixtures");
- path.push(file_name);
- path
+ fn get_temp_signer() -> Box<dyn Signer> {
+ // sign and embed into the target file
+ let mut signcert_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+ signcert_path.push("tests/fixtures/certs/ps256.pub");
+ let mut pkey_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+ pkey_path.push("tests/fixtures/certs/ps256.pem");
+ get_signer_from_files(signcert_path, pkey_path, "ps256", None)
+ .expect("get_signer_from_files")
}
#[test]
@@ -98,10 +101,8 @@ mod integration_1 {
img.save(&output_path)?;
// sign and embed into the target file
- let cert_dir = fixture_path("certs");
- let (signer, _) = get_temp_signer(&cert_dir);
-
- manifest.embed(&output_path, &output_path, &signer)?;
+ let signer = get_temp_signer();
+ manifest.embed(&output_path, &output_path, &*signer)?;
// read our new file with embedded manifest
let manifest_store = ManifestStore::from_file(&output_path)?;