Skip to content

Commit 2df2f1d

Browse files
chore: Move WASM asynchronous raw signature mechanism into c2pa-crypto (#694)
1 parent 738fb61 commit 2df2f1d

File tree

16 files changed

+816
-672
lines changed

16 files changed

+816
-672
lines changed

internal/crypto/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ default-features = false
6363
features = ["now", "wasmbind"]
6464

6565
[target.'cfg(target_arch = "wasm32")'.dependencies]
66+
async-trait = { version = "0.1.77" }
6667
ecdsa = "0.16.9"
6768
ed25519-dalek = "2.1.1"
6869
p256 = "0.13.2"

internal/crypto/src/raw_signature/validator.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,15 @@ pub enum RawSignatureValidationError {
133133
/// An invalid signature value was provided.
134134
#[error("invalid signature value")]
135135
InvalidSignature,
136+
137+
/// The time stamp uses an unsupported signing or hash algorithm.
138+
#[error("signature uses an unsupported algorithm")]
139+
UnsupportedAlgorithm,
140+
141+
/// An unexpected internal error occured while requesting the time stamp
142+
/// response.
143+
#[error("internal error ({0})")]
144+
InternalError(&'static str),
136145
}
137146

138147
#[cfg(feature = "openssl")]
@@ -141,3 +150,17 @@ impl From<openssl::error::ErrorStack> for RawSignatureValidationError {
141150
Self::OpenSslError(err.to_string())
142151
}
143152
}
153+
154+
#[cfg(target_arch = "wasm32")]
155+
impl From<crate::webcrypto::WasmCryptoError> for RawSignatureValidationError {
156+
fn from(err: crate::webcrypto::WasmCryptoError) -> Self {
157+
match err {
158+
crate::webcrypto::WasmCryptoError::UnknownContext => {
159+
Self::InternalError("unknown WASM context")
160+
}
161+
crate::webcrypto::WasmCryptoError::NoCryptoAvailable => {
162+
Self::InternalError("WASM crypto unavailable")
163+
}
164+
}
165+
}
166+
}
Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
// Copyright 2024 Adobe. All rights reserved.
2+
// This file is licensed to you under the Apache License,
3+
// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
4+
// or the MIT license (http://opensource.org/licenses/MIT),
5+
// at your option.
6+
7+
// Unless required by applicable law or agreed to in writing,
8+
// this software is distributed on an "AS IS" BASIS, WITHOUT
9+
// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
10+
// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
11+
// specific language governing permissions and limitations under
12+
// each license.
13+
14+
use bcder::Oid;
15+
use rasn::types::OctetString;
16+
use wasm_bindgen_test::wasm_bindgen_test;
17+
18+
use crate::{
19+
raw_signature::RawSignatureValidationError,
20+
webcrypto::{
21+
async_validator_for_sig_and_hash_algs, async_validators::async_validator_for_signing_alg,
22+
},
23+
SigningAlg,
24+
};
25+
26+
const SAMPLE_DATA: &[u8] = b"some sample content to sign";
27+
28+
#[wasm_bindgen_test]
29+
async fn es256() {
30+
let signature = include_bytes!("../../fixtures/raw_signature/es256.raw_sig");
31+
let pub_key = include_bytes!("../../fixtures/raw_signature/es256.pub_key");
32+
33+
let validator = async_validator_for_signing_alg(SigningAlg::Es256).unwrap();
34+
35+
validator
36+
.validate_async(signature, SAMPLE_DATA, pub_key)
37+
.await
38+
.unwrap();
39+
}
40+
41+
#[wasm_bindgen_test]
42+
async fn es256_bad_signature() {
43+
let mut signature = include_bytes!("../../fixtures/raw_signature/es256.raw_sig").to_vec();
44+
assert_ne!(signature[10], 10);
45+
signature[10] = 10;
46+
47+
let pub_key = include_bytes!("../../fixtures/raw_signature/es256.pub_key");
48+
49+
let validator = async_validator_for_signing_alg(SigningAlg::Es256).unwrap();
50+
51+
assert_eq!(
52+
validator
53+
.validate_async(&signature, SAMPLE_DATA, pub_key)
54+
.await
55+
.unwrap_err(),
56+
RawSignatureValidationError::SignatureMismatch
57+
);
58+
}
59+
60+
#[wasm_bindgen_test]
61+
async fn es256_bad_data() {
62+
let signature = include_bytes!("../../fixtures/raw_signature/es256.raw_sig");
63+
let pub_key = include_bytes!("../../fixtures/raw_signature/es256.pub_key");
64+
65+
let mut data = SAMPLE_DATA.to_vec();
66+
data[10] = 0;
67+
68+
let validator = async_validator_for_signing_alg(SigningAlg::Es256).unwrap();
69+
70+
assert_eq!(
71+
validator
72+
.validate_async(signature, &data, pub_key)
73+
.await
74+
.unwrap_err(),
75+
RawSignatureValidationError::SignatureMismatch
76+
);
77+
}
78+
79+
#[wasm_bindgen_test]
80+
async fn es384() {
81+
let signature = include_bytes!("../../fixtures/raw_signature/es384.raw_sig");
82+
let pub_key = include_bytes!("../../fixtures/raw_signature/es384.pub_key");
83+
84+
let validator = async_validator_for_signing_alg(SigningAlg::Es384).unwrap();
85+
86+
validator
87+
.validate_async(signature, SAMPLE_DATA, pub_key)
88+
.await
89+
.unwrap();
90+
}
91+
92+
#[wasm_bindgen_test]
93+
async fn es512() {
94+
let signature = include_bytes!("../../fixtures/raw_signature/es512.raw_sig");
95+
let pub_key = include_bytes!("../../fixtures/raw_signature/es512.pub_key");
96+
97+
let validator = async_validator_for_signing_alg(SigningAlg::Es512).unwrap();
98+
99+
validator
100+
.validate_async(signature, SAMPLE_DATA, pub_key)
101+
.await
102+
.unwrap();
103+
}
104+
105+
#[wasm_bindgen_test]
106+
async fn ed25519() {
107+
let signature = include_bytes!("../../fixtures/raw_signature/ed25519.raw_sig");
108+
let pub_key = include_bytes!("../../fixtures/raw_signature/ed25519.pub_key");
109+
110+
let validator = async_validator_for_signing_alg(SigningAlg::Ed25519).unwrap();
111+
112+
validator
113+
.validate_async(signature, SAMPLE_DATA, pub_key)
114+
.await
115+
.unwrap();
116+
}
117+
118+
#[wasm_bindgen_test]
119+
async fn ed25519_bad_data() {
120+
let signature = include_bytes!("../../fixtures/raw_signature/ed25519.raw_sig");
121+
let pub_key = include_bytes!("../../fixtures/raw_signature/ed25519.pub_key");
122+
123+
let mut data = SAMPLE_DATA.to_vec();
124+
data[5] = 10;
125+
data[6] = 11;
126+
127+
let validator = async_validator_for_signing_alg(SigningAlg::Ed25519).unwrap();
128+
129+
assert_eq!(
130+
validator
131+
.validate_async(signature, &data, pub_key)
132+
.await
133+
.unwrap_err(),
134+
RawSignatureValidationError::SignatureMismatch
135+
);
136+
}
137+
138+
#[wasm_bindgen_test]
139+
async fn ps256() {
140+
let signature = include_bytes!("../../fixtures/raw_signature/ps256.raw_sig");
141+
let pub_key = include_bytes!("../../fixtures/raw_signature/ps256.pub_key");
142+
143+
let validator = async_validator_for_signing_alg(SigningAlg::Ps256).unwrap();
144+
145+
validator
146+
.validate_async(signature, SAMPLE_DATA, pub_key)
147+
.await
148+
.unwrap();
149+
}
150+
151+
#[wasm_bindgen_test]
152+
async fn ps256_bad_signature() {
153+
let mut signature = include_bytes!("../../fixtures/raw_signature/ps256.raw_sig").to_vec();
154+
assert_ne!(signature[10], 10);
155+
signature[10] = 10;
156+
157+
let pub_key = include_bytes!("../../fixtures/raw_signature/ps256.pub_key");
158+
159+
let validator = async_validator_for_signing_alg(SigningAlg::Ps256).unwrap();
160+
161+
assert_eq!(
162+
validator
163+
.validate_async(&signature, SAMPLE_DATA, pub_key)
164+
.await
165+
.unwrap_err(),
166+
RawSignatureValidationError::SignatureMismatch
167+
);
168+
}
169+
170+
#[wasm_bindgen_test]
171+
async fn ps256_bad_data() {
172+
let signature = include_bytes!("../../fixtures/raw_signature/ps256.raw_sig");
173+
let pub_key = include_bytes!("../../fixtures/raw_signature/ps256.pub_key");
174+
175+
let mut data = SAMPLE_DATA.to_vec();
176+
data[10] = 0;
177+
178+
let validator = async_validator_for_signing_alg(SigningAlg::Ps256).unwrap();
179+
180+
assert_eq!(
181+
validator
182+
.validate_async(signature, &data, pub_key)
183+
.await
184+
.unwrap_err(),
185+
RawSignatureValidationError::SignatureMismatch
186+
);
187+
}
188+
189+
#[wasm_bindgen_test]
190+
async fn ps384() {
191+
let signature = include_bytes!("../../fixtures/raw_signature/ps384.raw_sig");
192+
let pub_key = include_bytes!("../../fixtures/raw_signature/ps384.pub_key");
193+
194+
let validator = async_validator_for_signing_alg(SigningAlg::Ps384).unwrap();
195+
196+
validator
197+
.validate_async(signature, SAMPLE_DATA, pub_key)
198+
.await
199+
.unwrap();
200+
}
201+
202+
#[wasm_bindgen_test]
203+
async fn ps512() {
204+
let signature = include_bytes!("../../fixtures/raw_signature/ps512.raw_sig");
205+
let pub_key = include_bytes!("../../fixtures/raw_signature/ps512.pub_key");
206+
207+
let validator = async_validator_for_signing_alg(SigningAlg::Ps512).unwrap();
208+
209+
validator
210+
.validate_async(signature, SAMPLE_DATA, pub_key)
211+
.await
212+
.unwrap();
213+
}
214+
215+
// Argh. Different Oid types across different crates, so we have to construct
216+
// our own constants here.
217+
const RSA_OID: Oid = bcder::Oid(OctetString::from_static(&[
218+
42, 134, 72, 134, 247, 13, 1, 1, 1,
219+
]));
220+
221+
const SHA256_OID: Oid = bcder::Oid(OctetString::from_static(&[96, 134, 72, 1, 101, 3, 4, 2, 1]));
222+
223+
const SHA384_OID: Oid = bcder::Oid(OctetString::from_static(&[96, 134, 72, 1, 101, 3, 4, 2, 2]));
224+
225+
const SHA512_OID: Oid = bcder::Oid(OctetString::from_static(&[96, 134, 72, 1, 101, 3, 4, 2, 3]));
226+
227+
#[wasm_bindgen_test]
228+
async fn legacy_rs256() {
229+
let signature = include_bytes!("../../fixtures/raw_signature/legacy/rs256.raw_sig");
230+
let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs256.pub_key");
231+
232+
let validator = async_validator_for_sig_and_hash_algs(&RSA_OID, &SHA256_OID).unwrap();
233+
234+
validator
235+
.validate_async(signature, SAMPLE_DATA, pub_key)
236+
.await
237+
.unwrap();
238+
}
239+
240+
#[wasm_bindgen_test]
241+
async fn legacy_rs256_bad_signature() {
242+
let mut signature =
243+
include_bytes!("../../fixtures/raw_signature/legacy/rs256.raw_sig").to_vec();
244+
assert_ne!(signature[10], 10);
245+
signature[10] = 10;
246+
247+
let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs256.pub_key");
248+
249+
let validator = async_validator_for_sig_and_hash_algs(&RSA_OID, &SHA256_OID).unwrap();
250+
251+
assert_eq!(
252+
validator
253+
.validate_async(&signature, SAMPLE_DATA, pub_key)
254+
.await
255+
.unwrap_err(),
256+
RawSignatureValidationError::SignatureMismatch
257+
);
258+
}
259+
260+
#[wasm_bindgen_test]
261+
async fn legacy_rs256_bad_data() {
262+
let signature = include_bytes!("../../fixtures/raw_signature/legacy/rs256.raw_sig");
263+
let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs256.pub_key");
264+
265+
let mut data = SAMPLE_DATA.to_vec();
266+
data[10] = 0;
267+
268+
let validator = async_validator_for_sig_and_hash_algs(&RSA_OID, &SHA256_OID).unwrap();
269+
270+
assert_eq!(
271+
validator
272+
.validate_async(signature, &data, pub_key)
273+
.await
274+
.unwrap_err(),
275+
RawSignatureValidationError::SignatureMismatch
276+
);
277+
}
278+
279+
#[wasm_bindgen_test]
280+
async fn legacy_rs384() {
281+
let signature = include_bytes!("../../fixtures/raw_signature/legacy/rs384.raw_sig");
282+
let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs384.pub_key");
283+
284+
let validator = async_validator_for_sig_and_hash_algs(&RSA_OID, &SHA384_OID).unwrap();
285+
286+
validator
287+
.validate_async(signature, SAMPLE_DATA, pub_key)
288+
.await
289+
.unwrap();
290+
}
291+
292+
#[wasm_bindgen_test]
293+
async fn legacy_rs512() {
294+
let signature = include_bytes!("../../fixtures/raw_signature/legacy/rs512.raw_sig");
295+
let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs512.pub_key");
296+
297+
let validator = async_validator_for_sig_and_hash_algs(&RSA_OID, &SHA512_OID).unwrap();
298+
299+
validator
300+
.validate_async(signature, SAMPLE_DATA, pub_key)
301+
.await
302+
.unwrap();
303+
}

internal/crypto/src/tests/webcrypto/validators/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// specific language governing permissions and limitations under
1212
// each license.
1313

14+
mod async_validators;
1415
mod ecdsa_validator;
1516
mod ed25519_validator;
1617
mod rsa_legacy_validator;

0 commit comments

Comments
 (0)