Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/contentauth/c2pa-rs into as…
Browse files Browse the repository at this point in the history
…ync_sign

* 'main' of https://github.com/contentauth/c2pa-rs:
  Prepare 0.9.0 release
  (MINOR) Introduce a new `SigningAlg` enum (#76)
  Support for asynchronous signing of claims (#57)

# Conflicts:
#	sdk/src/cose_sign.rs
#	sdk/src/cose_validator.rs
#	sdk/src/openssl/temp_signer_async.rs
#	sdk/src/signer.rs
#	sdk/src/store.rs
  • Loading branch information
mauricefisher64 committed Jul 19, 2022
2 parents dd3ee52 + 4ef2f1b commit 5d501fb
Show file tree
Hide file tree
Showing 28 changed files with 662 additions and 510 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ This project adheres to [Semantic Versioning](https://semver.org), except that

Do not manually edit this file. It will be automatically updated when a new release is published.

## 0.9.0
_19 July 2022_

* (MINOR) Introduce a new `SigningAlg` enum ([#76](https://github.com/contentauth/c2pa-rs/pull/76))
* Support for asynchronous signing of claims ([#57](https://github.com/contentauth/c2pa-rs/pull/57))
* Adds an add_validation_status method to Ingredient ([#68](https://github.com/contentauth/c2pa-rs/pull/68))

## 0.8.1
_15 July 2022_

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Add this to your `Cargo.toml`:

```toml
[dependencies]
c2pa = "0.8.1"
c2pa = "0.9.0"
```

## Crate features
Expand Down
2 changes: 1 addition & 1 deletion make_test_images/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "make_test_images"
version = "0.8.1"
version = "0.9.0"
authors = ["Gavin Peacock <gpeacock@adobe.com>"]
license = "MIT OR Apache-2.0"
edition = "2018"
Expand Down
2 changes: 2 additions & 0 deletions make_test_images/src/make_test_images.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use c2pa::{
assertions::{c2pa_action, Action, Actions, CreativeWork, SchemaDotOrgPerson},
create_signer, jumbf_io, Error, Ingredient, IngredientOptions, Manifest, ManifestStore, Signer,
SigningAlg,
};

use anyhow::{Context, Result};
Expand All @@ -36,6 +37,7 @@ fn get_signer_with_alg(alg: &str) -> c2pa::Result<Box<dyn Signer>> {
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));
let alg: SigningAlg = alg.parse().map_err(|_| c2pa::Error::UnsupportedType)?;
create_signer::from_files(signcert_path, pkey_path, alg, None)
}

Expand Down
2 changes: 1 addition & 1 deletion sdk/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "c2pa"
version = "0.8.1"
version = "0.9.0"
description = "Rust SDK for C2PA (Coalition for Content Provenance and Authenticity) implementors"
authors = ["Maurice Fisher <mfisher@adobe.com>", "Gavin Peacock <gpeacock@adobe.com>", "Eric Scouten <scouten@adobe.com>", "Leonard Rosenthol <lrosenth@adobe.com>", "Dave Kozma <dkozma@adobe.com>"]
license = "MIT OR Apache-2.0"
Expand Down
4 changes: 2 additions & 2 deletions sdk/examples/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use anyhow::Result;

use c2pa::{
assertions::{c2pa_action, labels, Action, Actions, CreativeWork, SchemaDotOrgPerson},
create_signer, Ingredient, Manifest, ManifestStore,
create_signer, Ingredient, Manifest, ManifestStore, SigningAlg,
};
use std::path::PathBuf;

Expand Down Expand Up @@ -111,7 +111,7 @@ pub fn main() -> Result<()> {
// sign and embed into the target file
let signcert_path = "../sdk/tests/fixtures/certs.ps256.pem";
let pkey_path = "../sdk/tests/fixtures/certs.ps256.pub";
let signer = create_signer::from_files(signcert_path, pkey_path, "ps256", None)?;
let signer = create_signer::from_files(signcert_path, pkey_path, SigningAlg::Ps256, None)?;

manifest.embed(&source, &dest, &*signer)?;

Expand Down
158 changes: 79 additions & 79 deletions sdk/src/cose_sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,79 +25,8 @@ use crate::{
cose_validator::verify_cose,
status_tracker::OneShotStatusTracker,
time_stamp::{cose_timestamp_countersign, make_cose_timestamp},
Error, Result, Signer,
Error, Result, Signer, SigningAlg,
};
fn build_unprotected_header(
data: &[u8],
alg: &str,
certs: Vec<Vec<u8>>,
ta_url: Option<String>,
ocsp_val: Option<Vec<u8>>,
) -> Result<(Header, Header)> {
let alg_id = match alg {
"ps256" => HeaderBuilder::new()
.algorithm(iana::Algorithm::PS256)
.build(),
"ps384" => HeaderBuilder::new()
.algorithm(iana::Algorithm::PS384)
.build(),
"ps512" => HeaderBuilder::new()
.algorithm(iana::Algorithm::PS512)
.build(),
"es256" => HeaderBuilder::new()
.algorithm(iana::Algorithm::ES256)
.build(),
"es384" => HeaderBuilder::new()
.algorithm(iana::Algorithm::ES384)
.build(),
"es512" => HeaderBuilder::new()
.algorithm(iana::Algorithm::ES512)
.build(),
"ed25519" => HeaderBuilder::new()
.algorithm(iana::Algorithm::EdDSA)
.build(),
_ => return Err(Error::UnsupportedType),
};

let sc_der_array_or_bytes = match certs.len() {
1 => Value::Bytes(certs[0].clone()), // single cert
_ => {
let mut sc_der_array: Vec<Value> = Vec::new();
for cert in certs {
sc_der_array.push(Value::Bytes(cert));
}
Value::Array(sc_der_array) // provide vec of certs when required
}
};

let mut unprotected = if let Some(url) = ta_url {
let cts = cose_timestamp_countersign(data, alg, &url)?;
let sigtst_vec = serde_cbor::to_vec(&make_cose_timestamp(&cts))?;
let sigtst_cbor = serde_cbor::from_slice(&sigtst_vec)?;

HeaderBuilder::new()
.text_value("x5chain".to_string(), sc_der_array_or_bytes)
.text_value("sigTst".to_string(), sigtst_cbor)
} else {
HeaderBuilder::new().text_value("x5chain".to_string(), sc_der_array_or_bytes)
};

// set the ocsp responder response if available
if let Some(ocsp) = ocsp_val {
let mut ocsp_vec: Vec<Value> = Vec::new();
let mut r_vals: Vec<(Value, Value)> = vec![];

ocsp_vec.push(Value::Bytes(ocsp));
r_vals.push((Value::Text("ocspVals".to_string()), Value::Array(ocsp_vec)));

unprotected = unprotected.text_value("rVals".to_string(), Value::Map(r_vals));
}

// build complete header
let unprotected_header = unprotected.build();

Ok((alg_id, unprotected_header))
}

/// Generate a COSE signature for a block of bytes which must be a valid C2PA
/// claim structure.
Expand All @@ -117,15 +46,15 @@ fn build_unprotected_header(
/// 3. Verifies that the signature is valid COSE. Will respond with an error
/// if unable to validate.
pub fn sign_claim(claim_bytes: &[u8], signer: &dyn Signer, box_size: usize) -> Result<Vec<u8>> {
// must be a valid Claim
// Must be a valid claim.
let label = "dummy_label";
let _claim = Claim::from_data(label, claim_bytes)?;

// generate and verify a CoseSign1 representation of the data
// Generate and verify a CoseSign1 representation of the data.
cose_sign(signer, claim_bytes, box_size).and_then(|sig| {
// Sanity check: Ensure that this signature is valid.

let mut cose_log = OneShotStatusTracker::new();

match verify_cose(&sig, claim_bytes, b"", false, &mut cose_log) {
Ok(_) => Ok(sig),
Err(err) => Err(err),
Expand Down Expand Up @@ -158,12 +87,12 @@ pub(crate) fn cose_sign(signer: &dyn Signer, data: &[u8], box_size: usize) -> Re
string.
*/

let alg = signer.alg().ok_or(Error::UnsupportedType)?;
let alg = signer.alg();

// build complete header
let (alg_id, unprotected_header) = build_unprotected_header(
data,
&alg,
alg,
signer.certs()?,
signer.time_authority_url(),
signer.ocsp_val(),
Expand Down Expand Up @@ -216,12 +145,12 @@ pub async fn cose_sign_async(
string.
*/

let alg = signer.alg().ok_or(Error::UnsupportedType)?;
let alg = signer.alg();

// build complete header
let (alg_id, unprotected_header) = build_unprotected_header(
data,
&alg,
alg,
signer.certs()?,
signer.time_authority_url(),
signer.ocsp_val(),
Expand Down Expand Up @@ -254,6 +183,77 @@ pub async fn cose_sign_async(
Ok(c2pa_sig_data)
}

fn build_unprotected_header(
data: &[u8],
alg: SigningAlg,
certs: Vec<Vec<u8>>,
ta_url: Option<String>,
ocsp_val: Option<Vec<u8>>,
) -> Result<(Header, Header)> {
let alg_id = match alg {
SigningAlg::Ps256 => HeaderBuilder::new()
.algorithm(iana::Algorithm::PS256)
.build(),
SigningAlg::Ps384 => HeaderBuilder::new()
.algorithm(iana::Algorithm::PS384)
.build(),
SigningAlg::Ps512 => HeaderBuilder::new()
.algorithm(iana::Algorithm::PS512)
.build(),
SigningAlg::Es256 => HeaderBuilder::new()
.algorithm(iana::Algorithm::ES256)
.build(),
SigningAlg::Es384 => HeaderBuilder::new()
.algorithm(iana::Algorithm::ES384)
.build(),
SigningAlg::Es512 => HeaderBuilder::new()
.algorithm(iana::Algorithm::ES512)
.build(),
SigningAlg::Ed25519 => HeaderBuilder::new()
.algorithm(iana::Algorithm::EdDSA)
.build(),
};

let sc_der_array_or_bytes = match certs.len() {
1 => Value::Bytes(certs[0].clone()), // single cert
_ => {
let mut sc_der_array: Vec<Value> = Vec::new();
for cert in certs {
sc_der_array.push(Value::Bytes(cert));
}
Value::Array(sc_der_array) // provide vec of certs when required
}
};

let mut unprotected = if let Some(url) = ta_url {
let cts = cose_timestamp_countersign(data, alg, &url)?;
let sigtst_vec = serde_cbor::to_vec(&make_cose_timestamp(&cts))?;
let sigtst_cbor = serde_cbor::from_slice(&sigtst_vec)?;

HeaderBuilder::new()
.text_value("x5chain".to_string(), sc_der_array_or_bytes)
.text_value("sigTst".to_string(), sigtst_cbor)
} else {
HeaderBuilder::new().text_value("x5chain".to_string(), sc_der_array_or_bytes)
};

// set the ocsp responder response if available
if let Some(ocsp) = ocsp_val {
let mut ocsp_vec: Vec<Value> = Vec::new();
let mut r_vals: Vec<(Value, Value)> = vec![];

ocsp_vec.push(Value::Bytes(ocsp));
r_vals.push((Value::Text("ocspVals".to_string()), Value::Array(ocsp_vec)));

unprotected = unprotected.text_value("rVals".to_string(), Value::Map(r_vals));
}

// build complete header
let unprotected_header = unprotected.build();

Ok((alg_id, unprotected_header))
}

const PAD: &str = "pad";
const PAD2: &str = "pad2";
const PAD_OFFSET: usize = 7;
Expand Down
Loading

0 comments on commit 5d501fb

Please sign in to comment.