commit aeb4a32d2928d32bf63332346e2a7f713e839f42
parent 3aa77b991763b4bcc5d0271497f60a39c7149743
Author: Gavin Peacock <gpeacock@adobe.com>
Date: Mon, 6 Jun 2022 14:00:45 -0700
Export top level signing functions, hide other signature details (#32)
* New public interface for signing
Adds get_signer and get_singer_from_files
get_temp_signer and get_temp_signer_with_alg
Hides other info
* Remove AsyncPlaceholder
Diffstat:
13 files changed, 143 insertions(+), 88 deletions(-)
diff --git a/make_test_images/src/make_test_images.rs b/make_test_images/src/make_test_images.rs
@@ -15,9 +15,8 @@
//!
use c2pa::{
assertions::{c2pa_action, Action, Actions, CreativeWork, SchemaDotOrgPerson},
- jumbf_io,
- openssl::temp_signer::get_signer_by_alg,
- Error, Ingredient, IngredientOptions, Manifest, ManifestStore,
+ get_temp_signer_by_alg, jumbf_io, Error, Ingredient, IngredientOptions, Manifest,
+ ManifestStore,
};
use anyhow::{Context, Result};
@@ -262,7 +261,7 @@ impl MakeTestImages {
// now create store; sign claim and embed in target
let temp_dir = tempdir()?;
let (signer, _) =
- get_signer_by_alg(&temp_dir.path(), &self.config.alg, self.config.ta.clone());
+ get_temp_signer_by_alg(&temp_dir.path(), &self.config.alg, self.config.ta.clone());
manifest.embed(&dst_path, &dst_path, signer.as_ref())?;
diff --git a/sdk/examples/client/client.rs b/sdk/examples/client/client.rs
@@ -17,8 +17,7 @@ use anyhow::Result;
use c2pa::{
assertions::{c2pa_action, labels, Action, Actions, CreativeWork},
- openssl::temp_signer::get_signer,
- Ingredient, Manifest, ManifestStore,
+ get_temp_signer, Ingredient, Manifest, ManifestStore,
};
use std::path::PathBuf;
use tempfile::tempdir;
@@ -111,7 +110,7 @@ pub fn main() -> Result<()> {
// sign and embed into the target file
let temp_dir = tempdir()?;
- let (signer, _) = get_signer(&temp_dir.path());
+ let (signer, _) = get_temp_signer(&temp_dir.path());
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,7 +66,7 @@ pub mod tests {
use tempfile::tempdir;
use crate::{
- openssl::temp_signer::get_signer,
+ openssl::temp_signer::get_temp_signer,
status_tracker::OneShotStatusTracker,
store::Store,
utils::test::{fixture_path, temp_dir_path},
@@ -88,7 +88,7 @@ pub mod tests {
let store = Store::load_from_asset(&temp_path, false, &mut OneShotStatusTracker::new())
.expect("loading store");
- let (signer, _) = get_signer(&temp_dir.path());
+ let (signer, _) = get_temp_signer(&temp_dir.path());
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
@@ -44,9 +44,9 @@
//! ```
//! # use c2pa::Result;
//! use c2pa::{
-//! Manifest,
-//! openssl::temp_signer::get_signer,
-//! assertions::User
+//! assertions::User,
+//! get_temp_signer,
+//! Manifest
//! };
//!
//! use std::path::PathBuf;
@@ -60,7 +60,7 @@
//! let dir = tempdir()?;
//! let dest = dir.path().join("test_file.jpg");
//!
-//! let (signer, _) = get_signer(&dir.path());
+//! let (signer, _) = get_temp_signer(&dir.path());
//! manifest.embed(&source, &dest, &signer)?;
//! # Ok(())
//! # }
@@ -89,11 +89,18 @@ pub use manifest_store_report::ManifestStoreReport;
#[cfg(feature = "file_io")]
pub(crate) mod ocsp_utils;
#[cfg(feature = "file_io")]
-pub mod openssl;
+mod openssl;
#[cfg(feature = "file_io")]
-pub mod signer;
+pub use crate::openssl::{
+ signer::{get_signer, get_signer_from_files},
+ temp_signer::{get_temp_signer, get_temp_signer_by_alg},
+};
+#[cfg(feature = "file_io")]
+mod signer;
#[cfg(feature = "async_signer")]
-pub use signer::{AsyncPlaceholder, AsyncSigner};
+pub use signer::AsyncSigner;
+#[cfg(feature = "file_io")]
+pub use signer::Signer;
/// crate private declarations
#[allow(dead_code, clippy::enum_variant_names)]
pub(crate) mod asn1;
@@ -114,8 +121,6 @@ pub(crate) mod hashed_uri;
#[allow(dead_code)]
pub(crate) mod jumbf;
pub(crate) mod salt;
-#[cfg(feature = "file_io")]
-pub(crate) use signer::Signer;
pub(crate) mod status_tracker;
pub(crate) mod store;
pub(crate) mod time_stamp;
diff --git a/sdk/src/manifest.rs b/sdk/src/manifest.rs
@@ -570,7 +570,7 @@ pub(crate) mod tests {
use crate::{
assertions::{c2pa_action, Action, Actions},
- openssl::temp_signer::get_signer,
+ openssl::temp_signer::get_temp_signer,
status_tracker::{DetailedStatusTracker, StatusTracker},
utils::test::{fixture_path, temp_dir_path, temp_fixture_path, TEST_SMALL_JPEG, TEST_VC},
};
@@ -642,7 +642,7 @@ pub(crate) mod tests {
let test_output = dir.path().join("wc_embed_test.jpg");
//embed a claim generated from this manifest
- let (signer, _) = get_signer(&dir.path());
+ let (signer, _) = get_temp_signer(&dir.path());
let _store = manifest
.embed(&source_path, &test_output, &signer)
@@ -747,7 +747,7 @@ pub(crate) mod tests {
)
.expect("add_assertion");
- let (signer, _) = get_signer(&temp_dir.path());
+ let (signer, _) = get_temp_signer(&temp_dir.path());
let store1 = manifest.embed(&output, &output, &signer).expect("embed");
let claim1_label = store1.provenance_label().unwrap();
@@ -772,7 +772,7 @@ pub(crate) mod tests {
let temp_dir = tempdir().expect("temp dir");
//embed a claim in output2
- let (signer, _) = get_signer(&temp_dir.path());
+ let (signer, _) = get_temp_signer(&temp_dir.path());
let _store2 = manifest2.embed(&output2, &output2, &signer).expect("embed");
diff --git a/sdk/src/manifest_store_report.rs b/sdk/src/manifest_store_report.rs
@@ -52,7 +52,7 @@ impl ManifestStoreReport {
}
/// Creates a ManifestStoreReport from an existing Store and a validation log
- pub fn from_store_with_log(
+ pub(crate) fn from_store_with_log(
store: &Store,
validation_log: &mut impl StatusTracker,
) -> Result<Self> {
diff --git a/sdk/src/openssl/mod.rs b/sdk/src/openssl/mod.rs
@@ -12,23 +12,24 @@
// each license.
mod rsa_signer;
-pub use rsa_signer::RsaSigner;
+pub(crate) use rsa_signer::RsaSigner;
mod rsa_validator;
-pub use rsa_validator::RsaValidator;
+pub(crate) use rsa_validator::RsaValidator;
mod ec_signer;
-pub use ec_signer::EcSigner;
+pub(crate) use ec_signer::EcSigner;
mod ec_validator;
-pub use ec_validator::EcValidator;
+pub(crate) use ec_validator::EcValidator;
mod ed_signer;
-pub use ed_signer::EdSigner;
+pub(crate) use ed_signer::EdSigner;
mod ed_validator;
-pub use ed_validator::EdValidator;
+pub(crate) use ed_validator::EdValidator;
+pub mod signer;
pub mod temp_signer;
use openssl::x509::X509;
diff --git a/sdk/src/openssl/rsa_signer.rs b/sdk/src/openssl/rsa_signer.rs
@@ -214,13 +214,13 @@ mod tests {
use tempfile::tempdir;
- use crate::{openssl::temp_signer::get_signer, Signer};
+ use crate::{openssl::temp_signer::get_temp_signer, Signer};
#[test]
fn signer_from_files() {
let temp_dir = tempdir().unwrap();
- let (signer, _) = get_signer(&temp_dir.path());
+ let (signer, _) = get_temp_signer(&temp_dir.path());
let data = b"some sample content to sign";
let signature = signer.sign(data).unwrap();
diff --git a/sdk/src/openssl/signer.rs b/sdk/src/openssl/signer.rs
@@ -0,0 +1,98 @@
+use std::path::Path;
+
+use crate::{
+ error::{Error, Result},
+ openssl::{EcSigner, EdSigner, RsaSigner},
+ signer::ConfigurableSigner,
+ Signer,
+};
+
+/// Creates a signer using signcert and public key
+///
+/// Can generate a [`Signer`] instance for all supported formats.
+///
+/// # Arguments
+///
+/// * `signcert` - A buffer containing a signcert
+/// * `pkey` - A buffer containing a public key file
+/// * `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 [`Signer`] instance or Error
+
+pub fn get_signer(
+ signcert: &[u8],
+ pkey: &[u8],
+ alg: &str,
+ tsa_url: Option<String>,
+) -> Result<Box<dyn Signer>> {
+ Ok(match alg {
+ "ps256" | "ps384" | "ps512" => Box::new(RsaSigner::from_signcert_and_pkey(
+ signcert,
+ pkey,
+ alg.to_owned(),
+ tsa_url,
+ )?),
+ "es256" | "es384" | "es512" => Box::new(EcSigner::from_signcert_and_pkey(
+ signcert,
+ pkey,
+ alg.to_owned(),
+ tsa_url,
+ )?),
+ "ed25519" => Box::new(EdSigner::from_signcert_and_pkey(
+ signcert,
+ pkey,
+ alg.to_owned(),
+ tsa_url,
+ )?),
+ _ => return Err(Error::BadParam(alg.to_owned())),
+ })
+}
+
+/// Creates a signer using signcert and public key files
+///
+/// Can generate a [`Signer`] instance for all supported formats.
+///
+/// # Arguments
+///
+/// * `signcert_path` - A path to the signing cert file
+/// * `pkey_path` - A path to the public key file
+/// * `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 [`Signer`] instance or Error
+
+pub fn get_signer_from_files<P: AsRef<Path>>(
+ signcert_path: P,
+ pkey_path: P,
+ alg: &str,
+ tsa_url: Option<String>,
+) -> Result<Box<dyn Signer>> {
+ Ok(match alg {
+ "ps256" | "ps384" | "ps512" => Box::new(RsaSigner::from_files(
+ &signcert_path,
+ &pkey_path,
+ alg.to_owned(),
+ tsa_url,
+ )?),
+ "es256" | "es384" | "es512" => Box::new(EcSigner::from_files(
+ &signcert_path,
+ &pkey_path,
+ alg.to_owned(),
+ tsa_url,
+ )?),
+ "ed25519" => Box::new(EdSigner::from_files(
+ &signcert_path,
+ &pkey_path,
+ alg.to_owned(),
+ tsa_url,
+ )?),
+ _ => return Err(Error::BadParam(alg.to_owned())),
+ })
+}
diff --git a/sdk/src/openssl/temp_signer.rs b/sdk/src/openssl/temp_signer.rs
@@ -62,7 +62,7 @@ use crate::{
/// # Panics
///
/// Can panic if unable to invoke OpenSSL executable properly.
-pub fn get_signer<P: AsRef<Path>>(path: P) -> (RsaSigner, PathBuf) {
+pub fn get_temp_signer<P: AsRef<Path>>(path: P) -> (RsaSigner, PathBuf) {
let (sign_cert_path, pem_key_path) = make_key_path_pair(path, "temp_key");
create_x509_key_pair(
@@ -262,7 +262,7 @@ pub fn get_rsa_signer<P: AsRef<Path>>(
/// # Panics
///
/// Can panic if unable to invoke OpenSSL executable properly.
-pub fn get_signer_by_alg<P: AsRef<Path>>(
+pub fn get_temp_signer_by_alg<P: AsRef<Path>>(
path: P,
alg: &str,
tsa_url: Option<String>,
diff --git a/sdk/src/signer.rs b/sdk/src/signer.rs
@@ -46,7 +46,7 @@ pub trait Signer {
}
/// Trait to allow loading of signing credential from external sources
-pub trait ConfigurableSigner: Signer + Sized {
+pub(crate) trait ConfigurableSigner: Signer + Sized {
/// Create signer form credential files
fn from_files<P: AsRef<std::path::Path>>(
signcert_path: P,
@@ -64,33 +64,6 @@ pub trait ConfigurableSigner: Signer + Sized {
) -> Result<Self>;
}
-/// The `Placeholder` implementation provides a placeholder "signer" for use
-/// in testing and development contexts where a valid signature is not required.
-/// To state the obvious, claims signed using this implementation will not verify.
-pub struct Placeholder {}
-
-impl Signer for Placeholder {
- // sign the provided bytes
- fn sign(&self, _data: &[u8]) -> Result<Vec<u8>> {
- Ok(b"invalid signature".to_vec())
- }
-
- // algoritim iddentifer string for this Signer
- fn alg(&self) -> Option<String> {
- None
- }
-
- // list of certificates in der format, with last being cert that signed the claim
- fn certs(&self) -> Result<Vec<Vec<u8>>> {
- Ok(Vec::new())
- }
-
- // bytes to reserve for a fully signed claim
- fn reserve_size(&self) -> usize {
- 128
- }
-}
-
#[cfg(feature = "async_signer")]
use async_trait::async_trait;
@@ -110,22 +83,3 @@ pub trait AsyncSigner: Sync {
/// than this value.
fn reserve_size(&self) -> usize;
}
-
-/// The `AsyncPlaceholder` implementation provides a placeholder "async signer"
-/// for use in testing and development contexts where a valid signature is not
-/// required. To state the obvious, claims signed using this implementation
-/// will not verify.
-#[cfg(feature = "async_signer")]
-pub struct AsyncPlaceholder {}
-
-#[cfg(feature = "async_signer")]
-#[async_trait]
-impl AsyncSigner for AsyncPlaceholder {
- async fn sign(&self, _data: &[u8]) -> Result<Vec<u8>> {
- Ok(b"invalid signature".to_vec())
- }
-
- fn reserve_size(&self) -> usize {
- 128
- }
-}
diff --git a/sdk/src/store.rs b/sdk/src/store.rs
@@ -1695,7 +1695,7 @@ pub mod tests {
use crate::{
claim::AssertionStoreJsonFormat, jumbf_io::update_file_jumbf,
- openssl::temp_signer::get_signer, utils::patch::patch_file,
+ openssl::temp_signer::get_temp_signer, utils::patch::patch_file,
};
fn create_editing_claim(claim: &mut Claim) -> Result<&mut Claim> {
@@ -1747,7 +1747,7 @@ pub mod tests {
// Do we generate JUMBF?
let temp_dir = tempdir().unwrap();
- let (signer, _) = get_signer(&temp_dir.path());
+ let (signer, _) = get_temp_signer(&temp_dir.path());
// Test generate JUMBF
// Get labels for label test
@@ -2040,7 +2040,7 @@ pub mod tests {
// Do we generate JUMBF?
let temp_dir = tempdir().unwrap();
- let (signer, _) = get_signer(&temp_dir.path());
+ let (signer, _) = get_temp_signer(&temp_dir.path());
// 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();
@@ -2196,7 +2196,7 @@ pub mod tests {
use crate::utils::test::create_test_store;
let temp_dir = tempdir().unwrap();
- let (signer, _) = get_signer(&temp_dir.path());
+ let (signer, _) = get_temp_signer(&temp_dir.path());
// test adding to actual image
let ap = fixture_path("earth_apollo17.jpg");
@@ -2249,7 +2249,7 @@ pub mod tests {
use crate::{hashed_uri::HashedUri, utils::test::create_test_store};
let temp_dir = tempdir().unwrap();
- let (signer, _) = get_signer(&temp_dir.path());
+ let (signer, _) = get_temp_signer(&temp_dir.path());
// test adding to actual image
let ap = fixture_path("earth_apollo17.jpg");
diff --git a/sdk/tests/integration.rs b/sdk/tests/integration.rs
@@ -18,8 +18,7 @@ mod integration_1 {
use c2pa::{
assertions::{c2pa_action, Action, Actions},
- openssl::temp_signer::get_signer,
- Ingredient, Manifest, ManifestStore, Result,
+ get_temp_signer, Ingredient, Manifest, ManifestStore, Result,
};
use std::path::PathBuf;
use tempfile::tempdir;
@@ -93,7 +92,7 @@ mod integration_1 {
// sign and embed into the target file
let temp_dir = tempdir().unwrap();
- let (signer, _) = get_signer(&temp_dir.path());
+ let (signer, _) = get_temp_signer(&temp_dir.path());
manifest.embed(&output_path, &output_path, &signer)?;