Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 9 additions & 43 deletions sdk/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2852,76 +2852,42 @@ mod tests {

#[test]
fn test_redaction() {
// We use this to associate the parent ingredient with c2pa.opened action
const PARENT_LABEL: &str = "parent_ingredient";
Settings::from_toml(include_str!("../tests/fixtures/test_settings.toml")).unwrap();
//crate::utils::test::setup_logger();

// the label of the assertion we are going to redact
const ASSERTION_LABEL: &str = "stds.schema-org.CreativeWork";

let mut input = Cursor::new(TEST_IMAGE);

let parent = Reader::from_stream("image/jpeg", &mut input).expect("from_stream");
input.rewind().unwrap(); // we will use this again to add the parent ingredient
print!("{parent}");
let parent_manifest_label = parent.active_label().unwrap();
// you can extract a references any manifest and any assertion label here.

// Create a redacted uri for the assertion we are going to redact.
let redacted_uri =
crate::jumbf::labels::to_assertion_uri(parent_manifest_label, ASSERTION_LABEL);

//let parent_manifest_label = parent_manifest_label.to_owned();
let mut builder = Builder::update();

// Create a parent with a c2pa_action type assertion.
let opened_action = crate::assertions::Action::new(c2pa_action::OPENED)
.set_parameter("org.cai.ingredientIds", [PARENT_LABEL.to_string()].to_vec())
.unwrap();
builder.definition.redactions = Some(vec![redacted_uri.clone()]);

let redacted_action = crate::assertions::Action::new("c2pa.redacted")
.set_reason("testing".to_owned())
.set_parameter("redacted".to_owned(), redacted_uri.clone())
.unwrap();

let actions = crate::assertions::Actions::new()
.add_action(opened_action)
.add_action(redacted_action);

let definition = ManifestDefinition {
claim_version: Some(1),
claim_generator_info: [ClaimGeneratorInfo::default()].to_vec(),
title: Some("Redaction Test".to_string()),
redactions: Some(vec![redacted_uri]), // add the redaction
..Default::default()
};

let mut builder = Builder {
definition,
..Default::default()
};

let parent_json = json!({
"relationship": "parentOf",
"label": PARENT_LABEL,
})
.to_string();

// add the parent ingredient from the asset here
builder
.add_ingredient_from_stream(parent_json, "image/jpeg", &mut input)
.expect("add ingredient");

builder.add_assertion(Actions::LABEL, &actions).unwrap();
builder.add_action(redacted_action).unwrap();

let signer = test_signer(SigningAlg::Ps256);
// Embed a manifest using the signer.
let mut output = Cursor::new(Vec::new());
builder
.sign(signer.as_ref(), "jpeg", &mut input, &mut output)
.sign(signer.as_ref(), "image/jpeg", &mut input, &mut output)
.expect("builder sign");

output.set_position(0);

let reader = Reader::from_stream("jpeg", &mut output).expect("from_bytes");
println!("{reader}");
let reader = Reader::from_stream("image/jpeg", &mut output).expect("from_bytes");
//println!("{reader}");
let m = reader.active_manifest().unwrap();
assert_eq!(m.ingredients().len(), 1);
let parent = reader.get_manifest(parent_manifest_label).unwrap();
Expand Down
84 changes: 53 additions & 31 deletions sdk/src/claim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2500,7 +2500,7 @@ impl Claim {
// 2.d if redacted actions contains a redacted parameter if must be a resolvable reference
if action.action() == c2pa_action::REDACTED {
if let Some(params) = action.parameters() {
let mut parent_tested = None; // on exists if action actually pointed to an ingredient
let mut parent_tested = None; // only exists if action actually pointed to an ingredient
if let Some(v) = params.get("redacted") {
let redacted_uri =
value_cbor_to_type::<String>(v).ok_or_else(|| {
Expand All @@ -2522,41 +2522,63 @@ impl Claim {

if let Some(ingredient_label) = manifest_label_from_uri(&redacted_uri) {
// can we find a reference in the ingredient list
if let Some(ingredient) = svi.manifest_map.get(&ingredient_label) {
// does the assertion exist
if let Some(readaction_label) =
if let Some(ingredient_claim) =
svi.manifest_map.get(&ingredient_label)
{
// The referenced manifest exists, so far so good.
// now get the assertion label and try to resolve it.
if let Some(redaction_label) =
assertion_label_from_uri(&redacted_uri)
{
let (label, instance) =
Claim::assertion_label_from_link(&readaction_label);
parent_tested = Some(
ingredient.get_assertion(&label, instance).is_some(),
);
} else {
parent_tested = Some(false);
if ingredient_claim
.assertion_hashed_uri_from_label(&redaction_label)
.is_some()
{
// The url reference is valid, now check if it was actually redacted
parent_tested = Some(false);
// Now if the assertion is not in the assertion store we are ok.
// Todo: would a zeroed out assertion show up here? if so we need to do a zero check
if ingredient_claim
.get_claim_assertion(&redaction_label, 0)
.is_none()
{
parent_tested = Some(true); // it was redacted - all good!
}
}
}
}
}
match parent_tested {
Some(v) => parent_tested = Some(v),
None => parent_tested = Some(false), // if test fail early this is a tested failure
}
}

// will only exist if we actual tested for an ingredient
if let Some(false) = parent_tested {
log_item!(
label.clone(),
"action must have valid ingredient",
"verify_actions"
)
.validation_status(
validation_status::ASSERTION_ACTION_REDACTION_MISMATCH,
)
.failure(
validation_log,
Error::ValidationRule("action must have valid ingredient".into()),
)?;
match parent_tested {
None => {
log_item!(
label.clone(),
"redaction uri must be a valid reference",
"verify_actions"
)
.validation_status(
validation_status::ASSERTION_ACTION_REDACTION_MISMATCH,
)
.failure(
validation_log,
Error::ValidationRule(
"redaction action must have valid ingredient".into(),
),
)?;
}
Some(false) => {
log_item!(
label.clone(),
"The assertion was not redacted",
"verify_actions"
)
.validation_status(validation_status::ASSERTION_NOT_REDACTED)
.failure(
validation_log,
Error::ValidationRule("the assertion was not redacted".into()),
)?;
}
Some(true) => {}
}
}
}
Expand Down Expand Up @@ -2805,7 +2827,7 @@ impl Claim {
if parent_count > 1 {
log_item!(
claim.uri(),
"too many ingredient parentsf",
"too many ingredient parents",
"ingredient_checks"
)
.validation_status(validation_status::MANIFEST_MULTIPLE_PARENTS)
Expand Down