-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validation errors inconsistent through tools #125
Comments
Hi Clément, What signing algorithm are you using? Unfortunately the JavaScript SDK doesn't support Ed25519 at the moment due to WebCrypto's lack of support for it, so I'm wondering if this is causing the issue. |
It's es256. Please note that I am not generating this image. I took an image sample from truepic. "signature": {
"alg": "es256",
"issuer": "Truepic",
"time": "2023-03-20T14:29:27+00:00"
} Also, I can verify it there: https://contentcredentials.org/verify. I'm not sure which library is used there, but it seems to accept it. |
Hi @clementh59, what version of |
Hi @emensch, that's |
@clementh59 Verify uses the open source c2pa-js under the hood. I made a minimal repro case in CodeSandbox showing the image loading from your server and showing the claim info. What browser/version are you trying this on? |
Thanks a lot for the answer. The issue probably comes from our end then. I am on Chrome, but that's probably not linked to my browser/version as all the people that tried our service (which is a chrome extension) had the same issue. We'll investigate on our end to try to find the root of the issue. Thanks. |
@clementh59 if you'd like to post sample code—specifically anything about reading c2pa data and passing it to the web components—we might be able to help debug. There are a couple potential pitfalls that we don't do a great job of detailing in our docs at the moment 🙂 |
@emensch @dkozma Here is the code I tried: const sampleImage = 'https://truepic.com/wp-content/uploads/2023/03/transparency_original-capture.jpg';
(async () => {
const libraryUrl = './lib-temp/c2pa.esm.js';
// Initialize the c2pa-js SDK
const { createC2pa } = await import(libraryUrl);
const c2pa = await createC2pa({
wasmSrc: './lib-temp/toolkit_bg.wasm',
workerSrc: './lib-temp/c2pa.worker.min.js',
});
// Read in our sample image and get a manifest store
try {
const { manifestStore } = await c2pa.read(sampleImage);
console.log('errors from site reading: ', manifestStore.validationStatus);
} catch (err) {
console.error('Error reading image:', err);
}
})(); This code works in a very basic web app, where I don't have any validation error. However, the same code, with the same libraries (0.17.6) does not work in a very basic chrome extension (it says one of the signature mismatches). We'll continue to investigate on our side, but if you have any idea of what could be the issue, that would be super helpful. Thanks a lot |
It seems to come from this function that returns a validation error when fetching the manifest store data: It might be the case only when it is run in a special environment (i.e a chrome extension). What is surprising is that it is only the case for a small set of images, most of them are validated without any issue. |
@clementh59 I'm not sure if your browser extension also runs in a Firefox or Safari environment but if so I'm curious as to if the same problem exists in those browsers, or if this is localized to Chrome. |
Good point. It only runs on Chrome for now, so I can't help on that point, sorry |
No problem - let us try to replicate on a minimal browser extension environment and see if there is anything we can find. |
✅ Jira issue https://jira.corp.adobe.com/browse/CAI-5271 is successfully created for this GitHub issue. |
@clementh59 Are you running the c2pa-js code in a content script or a background script in your extension? |
@dkozma Feel free to ask any questions or help regarding the integration into an extension, I am happy to help! |
Hi @dkozma, I created a minimalist extension that showcases the bug: https://github.com/digimarc-corp/c2pa-content-credentials-extension/tree/minimalist-extension Here are the steps to have it work: Then, load the extension in chrome (https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world#load-unpacked) I hope it will make the debug as easy as possible on your side! :) Feel free to ask if you have any questions. I'm happy to jump on a call if you think it could be valuable. |
Thanks, this is very helpful - will give this a try Monday or Tuesday. |
@clementh59 Still looking into this. Will update when I have more - the minimal repro example you provided definitely makes things easier. |
Hi @dkozma any news on the issue? Also do let us know if we can do anything to help, anything you'd like us to explore. The extension is gaining quite a bit of momentum and we are eager to make sure it validates things correctly. |
Hi @dkozma, We continued to dig on our side to make it as easy as possible for you to debug it and here are some information that might be useful:
For you to debug, it might be useful to have actual data, so here it is. That's the data I get inside log::info!("Current alg: {:?}", alg);
// build result structure
let mut result = ValidationInfo::default();
log::info!("Result: {:?}", result);
// get the cert chain
let certs = get_sign_certs(&sign1)?;
log::info!("Certs: {:?}", certs);
sign1.payload = Some(data.clone()); // restore payload
log::info!("signature payload: {:?}", sign1.payload);
let tbs = sig_structure_data(
coset::SignatureContext::CoseSign1,
p_header,
None,
&additional_data,
sign1.payload.as_ref().unwrap_or(&vec![]),
); // get "to be signed" bytes
log::info!("TBS: {:?}", tbs);
[...]
log::info!("result2: {:?}", result);
Ok(result) I provided a JSON with all the values printed so that you can reproduce it in Also, here is the validation log: [
"LogItem"{
"label":"self#jumbf=/c2pa/adobe:urn:uuid:0ca37023-3dc5-4fee-8541-299998fb6b70/c2pa.signature",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1148",
"description":"claim signature valid",
"err_val":"None",
"validation_status":"Some(""claimSignature.validated"")"
},
"LogItem"{
"label":"self#jumbf=c2pa.assertions/c2pa.thumbnail.claim.jpeg",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=c2pa.assertions/c2pa.thumbnail.claim.jpeg",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
},
"LogItem"{
"label":"self#jumbf=c2pa.assertions/c2pa.thumbnail.ingredient.jpeg",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=c2pa.assertions/c2pa.thumbnail.ingredient.jpeg",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
},
"LogItem"{
"label":"self#jumbf=c2pa.assertions/c2pa.ingredient",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=c2pa.assertions/c2pa.ingredient",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
},
"LogItem"{
"label":"self#jumbf=c2pa.assertions/stds.schema-org.CreativeWork",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=c2pa.assertions/stds.schema-org.CreativeWork",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
},
"LogItem"{
"label":"self#jumbf=c2pa.assertions/c2pa.actions",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=c2pa.assertions/c2pa.actions",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
},
"LogItem"{
"label":"self#jumbf=c2pa.assertions/c2pa.hash.data",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=c2pa.assertions/c2pa.hash.data",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
},
"LogItem"{
"label":"self#jumbf=/c2pa/adobe:urn:uuid:0ca37023-3dc5-4fee-8541-299998fb6b70/c2pa.assertions/c2pa.hash.data",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1311",
"description":"data hash valid",
"err_val":"None",
"validation_status":"Some(""assertion.dataHash.match"")"
},
"LogItem"{
"label":"self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.signature",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1139",
"description":"claim signature is not valid",
"err_val":"Some(""CoseSignature"")",
"validation_status":"Some(""claimSignature.mismatch"")"
},
"LogItem"{
"label":"self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/com.truepic.libc2pa",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/com.truepic.libc2pa",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
},
"LogItem"{
"label":"self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/stds.exif",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/stds.exif",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
},
"LogItem"{
"label":"self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/stds.exif__1",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/stds.exif__1",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
},
"LogItem"{
"label":"self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/stds.exif__2",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/stds.exif__2",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
},
"LogItem"{
"label":"self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/c2pa.thumbnail.claim.jpeg",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/c2pa.thumbnail.claim.jpeg",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
},
"LogItem"{
"label":"self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/com.truepic.custom.odometry",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/com.truepic.custom.odometry",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
},
"LogItem"{
"label":"self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/com.truepic.custom.blur",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/com.truepic.custom.blur",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
},
"LogItem"{
"label":"self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/c2pa.hash.data",
"file":"/Users/clement-hecquet-evt/Documents/clement/tempo/c2pa-rs/sdk/src/claim.rs",
"function":"verify_internal",
"line":"1235",
"description":"hashed uri matched: self#jumbf=/c2pa/Truepic Lens SDK libc2pa vv1.0.0.182:urn:uuid:d6adaa79-0708-4b7a-9af0-10c7c42a21e5/c2pa.assertions/c2pa.hash.data",
"err_val":"None",
"validation_status":"Some(""assertion.hashedURI.match"")"
}
] It seems that only the COSE signature is problematic. I hope it helps! |
@clementh59 Thank you for digging into this - I'll go over this with the Rust team shortly. |
@clementh59 Looking into this further, it looks like SubtleCrypto.importKey() cannot be found during verification: I'm not sure if this is an issue with the extension running this in a web worker - I tried calling these functions manually in the extension console and they seem to work, so I'm not sure what is failing in this context. |
@dkozma I tried to call this function: async function importKey(rawKey) {
try {
const key = await window.crypto.subtle.importKey(
"raw", // format of the key to import
rawKey, // the key in ArrayBuffer format
{ // algorithm the key will be used with
name: "AES-CBC",
},
false, // whether the key is extractable
["encrypt", "decrypt"] // usages the key can be used for
);
console.log("Key imported successfully:", key);
return key;
} catch (error) {
console.error("Error importing key:", error);
}
} In the same function as I call the c2pa verifications and the function runs correctly. So the issue doesn't seem to be linked to the fact that it is being executed in a web worker... |
Hi @dkozma, we finally found a workaround for not using the library in a sandbox, which means we are not impacted by this bug anymore. |
Thanks for being persistent. We are a small team an do not have access to all possible build targets and platforms. |
Hi,
When validating the manifest of this image: https://truepic.com/wp-content/uploads/2023/03/transparency_original-capture.jpg with the library, I get this issue:
However, when validating with c2patool, it accepts the signature:
Do you know where it could come from?
Thanks,
Clément
The text was updated successfully, but these errors were encountered: