diff --git a/internal/crypto/Cargo.toml b/internal/crypto/Cargo.toml
index 3d7540a26..7c55915c7 100644
--- a/internal/crypto/Cargo.toml
+++ b/internal/crypto/Cargo.toml
@@ -31,6 +31,7 @@ rustdoc-args = ["--cfg", "docsrs"]
[features]
json_schema = ["dep:schemars"]
+rust_native_crypto = ["dep:ed25519-dalek"]
[dependencies]
asn1-rs = "0.6.2"
@@ -43,6 +44,7 @@ c2pa-status-tracker = { path = "../status-tracker", version = "0.2.0" }
ciborium = "0.2.2"
const-hex = "1.14"
coset = "0.3.1"
+ed25519-dalek = { version = "2.1.1", features = ["alloc", "digest", "pem", "pkcs8"], optional = true }
getrandom = { version = "0.2.7", features = ["js"] }
hex = "0.4.3"
nom = "7.1.3"
@@ -101,8 +103,12 @@ web-sys = { version = "0.3.58", features = [
getrandom = { version = "0.2.7", features = ["js"] }
js-sys = "0.3.58"
+[dev-dependencies]
+ed25519-dalek = { version = "2.1.1", features = ["alloc", "digest", "pem", "pkcs8"] }
+
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
actix = "0.13.1"
+ed25519-dalek = { version = "2.1.1", features = ["alloc", "digest", "pem", "pkcs8"] }
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wasm-bindgen-test = "0.3.31"
diff --git a/internal/crypto/README.md b/internal/crypto/README.md
index 75f91760f..a57f5315c 100644
--- a/internal/crypto/README.md
+++ b/internal/crypto/README.md
@@ -4,6 +4,61 @@
This crate contains some of the internal cryptography implementation that is shared between the [c2pa crate](https://crates.io/crates/c2pa) and the [CAWG identity SDK crate](https://crates.io/crates/cawg-identity). It is not intended to be used directly in most cases.
+## Crate features
+
+This crate has two features, neither of which are enabled by default:
+
+* `json_schema`: Used by c2pa-rs documentation code to generate JSON schema for types defined in this crate.
+* `rust_native_crypto`: Where available, prefer Rust-native cryptography libraries for raw signature and validation implementations. (Experimental)
+
+## Cryptographic library support
+
+`c2pa-crypto` will use different cryptography libraries depending on which platform and feature flags are used:
+
+### Signing (synchronous or asynchronous)
+
+| C2PA `SigningAlg` | Default (*) | `feature = "rust_native_crypto"` (*) | WASM |
+| --- | --- | --- | --- |
+| `es256` | OpenSSL | OpenSSL | ❌ |
+| `es384` | OpenSSL | OpenSSL | ❌ |
+| `es512` | OpenSSL | OpenSSL | ❌ |
+| `ed25519` | OpenSSL | `ed25519-dalek` | `ed25519-dalek` |
+| `ps256` | OpenSSL | OpenSSL | ❌ |
+| `ps384` | OpenSSL | OpenSSL | ❌ |
+| `ps512` | OpenSSL | OpenSSL | ❌ |
+
+(*) Applies to all supported platforms except WASM
+❌ = not supported
+
+### Validation (synchronous)
+
+| C2PA `SigningAlg` | Default (*) | `feature = "rust_native_crypto"` (*) | WASM |
+| --- | --- | --- | --- |
+| `es256` | OpenSSL | OpenSSL | `p256` |
+| `es384` | OpenSSL | OpenSSL | `p384` |
+| `es512` | OpenSSL | OpenSSL | ❌ |
+| `ed25519` | OpenSSL | `ed25519-dalek` | `ed25519-dalek` |
+| `ps256` | OpenSSL | OpenSSL | `rsa` |
+| `ps384` | OpenSSL | OpenSSL | `rsa` |
+| `ps512` | OpenSSL | OpenSSL | `rsa` |
+
+(*) Applies to all supported platforms except WASM
+❌ = not supported
+
+### Validation (asynchronous)
+
+| C2PA `SigningAlg` | Default (*) | `feature = "rust_native_crypto"` (*) | WASM |
+| --- | --- | --- | --- |
+| `es256` | OpenSSL | OpenSSL | WebCrypto |
+| `es384` | OpenSSL | OpenSSL | WebCrypto |
+| `es512` | OpenSSL | OpenSSL | WebCrypto |
+| `ed25519` | OpenSSL | `ed25519-dalek` | `ed25519-dalek` |
+| `ps256` | OpenSSL | OpenSSL | `rsa` |
+| `ps384` | OpenSSL | OpenSSL | `rsa` |
+| `ps512` | OpenSSL | OpenSSL | `rsa` |
+
+(*) Applies to all supported platforms except WASM
+
### Contributions and feedback
We welcome contributions to this project. For information on contributing, providing feedback, and about ongoing work, see [Contributing](https://github.com/contentauth/c2pa-rs/blob/main/CONTRIBUTING.md). For additional information on nightly builds and testing, see [Contributing to the project](docs/project-contributions.md).
diff --git a/internal/crypto/src/raw_signature/mod.rs b/internal/crypto/src/raw_signature/mod.rs
index e28f61542..c5caf309f 100644
--- a/internal/crypto/src/raw_signature/mod.rs
+++ b/internal/crypto/src/raw_signature/mod.rs
@@ -18,6 +18,9 @@ pub(crate) mod oids;
#[cfg(not(target_arch = "wasm32"))]
pub(crate) mod openssl;
+#[cfg(any(target_arch = "wasm32", feature = "rust_native_crypto", test))]
+pub(crate) mod rust_native;
+
pub(crate) mod signer;
pub use signer::{
async_signer_from_cert_chain_and_private_key, signer_from_cert_chain_and_private_key,
diff --git a/internal/crypto/src/raw_signature/openssl/mod.rs b/internal/crypto/src/raw_signature/openssl/mod.rs
index 7cbff7d7a..98aec396f 100644
--- a/internal/crypto/src/raw_signature/openssl/mod.rs
+++ b/internal/crypto/src/raw_signature/openssl/mod.rs
@@ -21,8 +21,8 @@
mod cert_chain;
mod ffi_mutex;
-pub use ffi_mutex::{OpenSslMutex, OpenSslMutexUnavailable};
+pub(crate) use ffi_mutex::{OpenSslMutex, OpenSslMutexUnavailable};
pub(crate) mod check_certificate_trust;
pub(crate) mod signers;
-pub mod validators;
+pub(crate) mod validators;
diff --git a/internal/crypto/src/raw_signature/rust_native/mod.rs b/internal/crypto/src/raw_signature/rust_native/mod.rs
new file mode 100644
index 000000000..dce099230
--- /dev/null
+++ b/internal/crypto/src/raw_signature/rust_native/mod.rs
@@ -0,0 +1,24 @@
+// Copyright 2025 Adobe. All rights reserved.
+// This file is licensed to you under the Apache License,
+// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+// or the MIT license (http://opensource.org/licenses/MIT),
+// at your option.
+
+// Unless required by applicable law or agreed to in writing,
+// this software is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
+// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
+// specific language governing permissions and limitations under
+// each license.
+
+#![allow(unused)] // Not used on all platforms or all configs
+
+//! Experimental support for synchronous raw signatures using Rust-native
+//! crates. Intended mostly for the synchronous use cases on WASM, but may
+//! eventually be used on all platforms.
+//!
+//! At the moment, does not offer support for all C2PA-supported cryptography
+//! algorithms.
+
+pub(crate) mod signers;
+pub(crate) mod validators;
diff --git a/internal/crypto/src/raw_signature/webcrypto/signers/ed25519_signer.rs b/internal/crypto/src/raw_signature/rust_native/signers/ed25519_signer.rs
similarity index 100%
rename from internal/crypto/src/raw_signature/webcrypto/signers/ed25519_signer.rs
rename to internal/crypto/src/raw_signature/rust_native/signers/ed25519_signer.rs
diff --git a/internal/crypto/src/raw_signature/webcrypto/signers/mod.rs b/internal/crypto/src/raw_signature/rust_native/signers/mod.rs
similarity index 88%
rename from internal/crypto/src/raw_signature/webcrypto/signers/mod.rs
rename to internal/crypto/src/raw_signature/rust_native/signers/mod.rs
index 29d195f65..3e6904cea 100644
--- a/internal/crypto/src/raw_signature/webcrypto/signers/mod.rs
+++ b/internal/crypto/src/raw_signature/rust_native/signers/mod.rs
@@ -1,4 +1,4 @@
-// Copyright 2024 Adobe. All rights reserved.
+// Copyright 2025 Adobe. All rights reserved.
// This file is licensed to you under the Apache License,
// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
// or the MIT license (http://opensource.org/licenses/MIT),
@@ -11,6 +11,9 @@
// specific language governing permissions and limitations under
// each license.
+//! This module binds Rust native logic for generating raw signatures to this
+//! crate's [`RawSigner`] trait.
+
use crate::raw_signature::{RawSigner, RawSignerError, SigningAlg};
mod ed25519_signer;
@@ -39,7 +42,7 @@ pub(crate) fn signer_from_cert_chain_and_private_key(
)),
_ => Err(RawSignerError::InternalError(format!(
- "unsupported algorithm: {alg}"
+ "unsupported signing algorithm {alg}"
))),
}
}
diff --git a/internal/crypto/src/raw_signature/webcrypto/validators/ed25519_validator.rs b/internal/crypto/src/raw_signature/rust_native/validators/ed25519_validator.rs
similarity index 92%
rename from internal/crypto/src/raw_signature/webcrypto/validators/ed25519_validator.rs
rename to internal/crypto/src/raw_signature/rust_native/validators/ed25519_validator.rs
index f38556280..b4cc795db 100644
--- a/internal/crypto/src/raw_signature/webcrypto/validators/ed25519_validator.rs
+++ b/internal/crypto/src/raw_signature/rust_native/validators/ed25519_validator.rs
@@ -27,7 +27,7 @@ impl RawSignatureValidator for Ed25519Validator {
data: &[u8],
public_key: &[u8],
) -> Result<(), RawSignatureValidationError> {
- let (_, public_key) = SubjectPublicKeyInfo::from_der(&public_key)
+ let (_, public_key) = SubjectPublicKeyInfo::from_der(public_key)
.map_err(|_| RawSignatureValidationError::InvalidPublicKey)?;
let public_key = public_key
@@ -43,7 +43,7 @@ impl RawSignatureValidator for Ed25519Validator {
}
let mut public_key_slice: [u8; PUBLIC_KEY_LENGTH] = Default::default();
- public_key_slice.copy_from_slice(&public_key);
+ public_key_slice.copy_from_slice(public_key);
let vk = VerifyingKey::from_bytes(&public_key_slice)
.map_err(|_| RawSignatureValidationError::InvalidPublicKey)?;
@@ -51,7 +51,7 @@ impl RawSignatureValidator for Ed25519Validator {
let ed_sig = Signature::from_slice(sig)
.map_err(|_| RawSignatureValidationError::InvalidSignature)?;
- match vk.verify(&data, &ed_sig) {
+ match vk.verify(data, &ed_sig) {
Ok(_) => Ok(()),
Err(_) => Err(RawSignatureValidationError::SignatureMismatch),
}
diff --git a/internal/crypto/src/raw_signature/rust_native/validators/mod.rs b/internal/crypto/src/raw_signature/rust_native/validators/mod.rs
new file mode 100644
index 000000000..5264993e0
--- /dev/null
+++ b/internal/crypto/src/raw_signature/rust_native/validators/mod.rs
@@ -0,0 +1,30 @@
+// Copyright 2025 Adobe. All rights reserved.
+// This file is licensed to you under the Apache License,
+// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+// or the MIT license (http://opensource.org/licenses/MIT),
+// at your option.
+
+// Unless required by applicable law or agreed to in writing,
+// this software is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
+// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
+// specific language governing permissions and limitations under
+// each license.
+
+//! This module binds Rust native logic for generating raw signatures to this
+//! crate's [`RawSignatureValidator`] trait.
+
+use bcder::Oid;
+
+use crate::raw_signature::{oids::*, RawSignatureValidator, SigningAlg};
+
+mod ed25519_validator;
+pub use ed25519_validator::Ed25519Validator;
+
+/// Return a validator for the given signing algorithm.
+pub fn validator_for_signing_alg(alg: SigningAlg) -> Option> {
+ match alg {
+ SigningAlg::Ed25519 => Some(Box::new(Ed25519Validator {})),
+ _ => None,
+ }
+}
diff --git a/internal/crypto/src/raw_signature/signer.rs b/internal/crypto/src/raw_signature/signer.rs
index 37957fd56..f5f7c1bac 100644
--- a/internal/crypto/src/raw_signature/signer.rs
+++ b/internal/crypto/src/raw_signature/signer.rs
@@ -165,19 +165,23 @@ pub fn signer_from_cert_chain_and_private_key(
alg: SigningAlg,
time_stamp_service_url: Option,
) -> Result, RawSignerError> {
- #[cfg(not(target_arch = "wasm32"))]
+ #[cfg(any(target_arch = "wasm32", feature = "rust_native_crypto"))]
{
- return crate::raw_signature::openssl::signers::signer_from_cert_chain_and_private_key(
+ match crate::raw_signature::rust_native::signers::signer_from_cert_chain_and_private_key(
cert_chain,
private_key,
alg,
- time_stamp_service_url,
- );
+ time_stamp_service_url.clone(),
+ ) {
+ Ok(signer) => return Ok(signer),
+ Err(RawSignerError::InternalError(_)) => (),
+ Err(err) => return Err(err),
+ }
}
- #[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
+ #[cfg(not(target_arch = "wasm32"))]
{
- return crate::raw_signature::webcrypto::signers::signer_from_cert_chain_and_private_key(
+ return crate::raw_signature::openssl::signers::signer_from_cert_chain_and_private_key(
cert_chain,
private_key,
alg,
diff --git a/internal/crypto/src/raw_signature/validator.rs b/internal/crypto/src/raw_signature/validator.rs
index caab5948b..0e597e1ac 100644
--- a/internal/crypto/src/raw_signature/validator.rs
+++ b/internal/crypto/src/raw_signature/validator.rs
@@ -65,6 +65,15 @@ pub trait AsyncRawSignatureValidator {
/// Which validators are available may vary depending on the platform and
/// which crate features were enabled.
pub fn validator_for_signing_alg(alg: SigningAlg) -> Option> {
+ #[cfg(any(target_arch = "wasm32", feature = "rust_native_crypto"))]
+ {
+ if let Some(validator) =
+ crate::raw_signature::rust_native::validators::validator_for_signing_alg(alg)
+ {
+ return Some(validator);
+ }
+ }
+
#[cfg(not(target_arch = "wasm32"))]
if let Some(validator) =
crate::raw_signature::openssl::validators::validator_for_signing_alg(alg)
diff --git a/internal/crypto/src/raw_signature/webcrypto/async_validators/ed25519_validator.rs b/internal/crypto/src/raw_signature/webcrypto/async_validators/ed25519_validator.rs
index db1656d5e..73cf95017 100644
--- a/internal/crypto/src/raw_signature/webcrypto/async_validators/ed25519_validator.rs
+++ b/internal/crypto/src/raw_signature/webcrypto/async_validators/ed25519_validator.rs
@@ -31,7 +31,7 @@ impl AsyncRawSignatureValidator for Ed25519Validator {
) -> Result<(), RawSignatureValidationError> {
// Sync and async cases are identical for Ed25519.
- let sync_validator = crate::raw_signature::webcrypto::validators::Ed25519Validator {};
+ let sync_validator = crate::raw_signature::rust_native::validators::Ed25519Validator {};
sync_validator.validate(sig, data, public_key)
}
}
diff --git a/internal/crypto/src/raw_signature/webcrypto/mod.rs b/internal/crypto/src/raw_signature/webcrypto/mod.rs
index ec62a2f1a..874f80e40 100644
--- a/internal/crypto/src/raw_signature/webcrypto/mod.rs
+++ b/internal/crypto/src/raw_signature/webcrypto/mod.rs
@@ -25,8 +25,7 @@ pub(crate) use async_validators::{
};
pub(crate) mod check_certificate_trust;
-pub(crate) mod signers;
-pub mod validators;
+pub(crate) mod validators;
mod window_or_worker;
pub use window_or_worker::{WasmCryptoError, WindowOrWorker};
diff --git a/internal/crypto/src/raw_signature/webcrypto/validators/mod.rs b/internal/crypto/src/raw_signature/webcrypto/validators/mod.rs
index 679e83c0c..2c28218f1 100644
--- a/internal/crypto/src/raw_signature/webcrypto/validators/mod.rs
+++ b/internal/crypto/src/raw_signature/webcrypto/validators/mod.rs
@@ -21,9 +21,6 @@ use crate::raw_signature::{oids::*, RawSignatureValidator, SigningAlg};
mod ecdsa_validator;
pub use ecdsa_validator::EcdsaValidator;
-mod ed25519_validator;
-pub use ed25519_validator::Ed25519Validator;
-
mod rsa_legacy_validator;
pub(crate) use rsa_legacy_validator::RsaLegacyValidator;
@@ -36,10 +33,10 @@ pub fn validator_for_signing_alg(alg: SigningAlg) -> Option Some(Box::new(EcdsaValidator::Es256)),
SigningAlg::Es384 => Some(Box::new(EcdsaValidator::Es384)),
SigningAlg::Es512 => None, /* why is this unimplemented? */
- SigningAlg::Ed25519 => Some(Box::new(Ed25519Validator {})),
SigningAlg::Ps256 => Some(Box::new(RsaValidator::Ps256)),
SigningAlg::Ps384 => Some(Box::new(RsaValidator::Ps384)),
SigningAlg::Ps512 => Some(Box::new(RsaValidator::Ps512)),
+ _ => None,
}
}
diff --git a/internal/crypto/src/tests/raw_signature/mod.rs b/internal/crypto/src/tests/raw_signature/mod.rs
index 0981a4dce..287dcc213 100644
--- a/internal/crypto/src/tests/raw_signature/mod.rs
+++ b/internal/crypto/src/tests/raw_signature/mod.rs
@@ -13,5 +13,6 @@
mod async_signers;
mod async_validators;
+mod rust_native;
mod signers;
mod validators;
diff --git a/internal/crypto/src/tests/raw_signature/rust_native/mod.rs b/internal/crypto/src/tests/raw_signature/rust_native/mod.rs
new file mode 100644
index 000000000..0ee060244
--- /dev/null
+++ b/internal/crypto/src/tests/raw_signature/rust_native/mod.rs
@@ -0,0 +1,15 @@
+// Copyright 2025 Adobe. All rights reserved.
+// This file is licensed to you under the Apache License,
+// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+// or the MIT license (http://opensource.org/licenses/MIT),
+// at your option.
+
+// Unless required by applicable law or agreed to in writing,
+// this software is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
+// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
+// specific language governing permissions and limitations under
+// each license.
+
+mod signers;
+mod validators;
diff --git a/internal/crypto/src/tests/raw_signature/rust_native/signers.rs b/internal/crypto/src/tests/raw_signature/rust_native/signers.rs
new file mode 100644
index 000000000..381dac4c8
--- /dev/null
+++ b/internal/crypto/src/tests/raw_signature/rust_native/signers.rs
@@ -0,0 +1,180 @@
+// Copyright 2025 Adobe. All rights reserved.
+// This file is licensed to you under the Apache License,
+// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+// or the MIT license (http://opensource.org/licenses/MIT),
+// at your option.
+
+// Unless required by applicable law or agreed to in writing,
+// this software is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
+// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
+// specific language governing permissions and limitations under
+// each license.
+
+#[cfg(target_arch = "wasm32")]
+use wasm_bindgen_test::wasm_bindgen_test;
+
+use crate::raw_signature::{rust_native, SigningAlg};
+
+/* Not implemented in rust_native yet.
+#[test]
+// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn es256() {
+ let cert_chain = include_bytes!("../../fixtures/raw_signature/es256.pub");
+ let private_key = include_bytes!("../../fixtures/raw_signature/es256.priv");
+
+ let signer =
+ rust_native::signer_from_cert_chain_and_private_key(cert_chain, private_key, SigningAlg::Es256, None)
+ .unwrap();
+
+ let data = b"some sample content to sign";
+ let signature = signer.sign(data).unwrap();
+
+ println!("signature len = {}", signature.len());
+ assert!(signature.len() <= signer.reserve_size());
+
+ let pub_key = include_bytes!("../../fixtures/raw_signature/es256.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Es256).unwrap();
+ validator.validate(&signature, data, pub_key).unwrap();
+}
+
+#[test]
+// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn es384() {
+ let cert_chain = include_bytes!("../../fixtures/raw_signature/es384.pub");
+ let private_key = include_bytes!("../../fixtures/raw_signature/es384.priv");
+
+ let signer =
+ rust_native::signer_from_cert_chain_and_private_key(cert_chain, private_key, SigningAlg::Es384, None)
+ .unwrap();
+
+ let data = b"some sample content to sign";
+ let signature = signer.sign(data).unwrap();
+
+ println!("signature len = {}", signature.len());
+ assert!(signature.len() <= signer.reserve_size());
+
+ let pub_key = include_bytes!("../../fixtures/raw_signature/es384.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Es384).unwrap();
+ validator.validate(&signature, data, pub_key).unwrap();
+}
+
+#[test]
+// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn es512() {
+ let cert_chain = include_bytes!("../../fixtures/raw_signature/es512.pub");
+ let private_key = include_bytes!("../../fixtures/raw_signature/es512.priv");
+
+ let signer =
+ rust_native::signer_from_cert_chain_and_private_key(cert_chain, private_key, SigningAlg::Es512, None)
+ .unwrap();
+
+ let data = b"some sample content to sign";
+ let signature = signer.sign(data).unwrap();
+
+ println!("signature len = {}", signature.len());
+ assert!(signature.len() <= signer.reserve_size());
+
+ let pub_key = include_bytes!("../../fixtures/raw_signature/es512.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Es512).unwrap();
+ validator.validate(&signature, data, pub_key).unwrap();
+}
+*/
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn ed25519() {
+ let cert_chain = include_bytes!("../../fixtures/raw_signature/ed25519.pub");
+ let private_key = include_bytes!("../../fixtures/raw_signature/ed25519.priv");
+
+ let signer = rust_native::signers::signer_from_cert_chain_and_private_key(
+ cert_chain,
+ private_key,
+ SigningAlg::Ed25519,
+ None,
+ )
+ .unwrap();
+
+ let data = b"some sample content to sign";
+ let signature = signer.sign(data).unwrap();
+
+ println!("signature len = {}", signature.len());
+ assert!(signature.len() <= signer.reserve_size());
+
+ let pub_key = include_bytes!("../../fixtures/raw_signature/ed25519.pub_key");
+
+ let validator =
+ rust_native::validators::validator_for_signing_alg(SigningAlg::Ed25519).unwrap();
+ validator.validate(&signature, data, pub_key).unwrap();
+}
+
+/* Not implemented in rust_native yet.
+#[test]
+// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn ps256() {
+ let cert_chain = include_bytes!("../../fixtures/raw_signature/ps256.pub");
+ let private_key = include_bytes!("../../fixtures/raw_signature/ps256.priv");
+
+ let signer =
+ rust_native::signer_from_cert_chain_and_private_key(cert_chain, private_key, SigningAlg::Ps256, None)
+ .unwrap();
+
+ let data = b"some sample content to sign";
+ let signature = signer.sign(data).unwrap();
+
+ println!("signature len = {}", signature.len());
+ assert!(signature.len() <= signer.reserve_size());
+
+ let pub_key = include_bytes!("../../fixtures/raw_signature/ps256.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Ps256).unwrap();
+ validator.validate(&signature, data, pub_key).unwrap();
+}
+
+#[test]
+// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn ps384() {
+ let cert_chain = include_bytes!("../../fixtures/raw_signature/ps384.pub");
+ let private_key = include_bytes!("../../fixtures/raw_signature/ps384.priv");
+
+ let signer =
+ rust_native::signer_from_cert_chain_and_private_key(cert_chain, private_key, SigningAlg::Ps384, None)
+ .unwrap();
+
+ let data = b"some sample content to sign";
+ let signature = signer.sign(data).unwrap();
+
+ println!("signature len = {}", signature.len());
+ assert!(signature.len() <= signer.reserve_size());
+
+ let pub_key = include_bytes!("../../fixtures/raw_signature/ps384.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Ps384).unwrap();
+ validator.validate(&signature, data, pub_key).unwrap();
+}
+
+#[test]
+// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn ps512() {
+ let cert_chain = include_bytes!("../../fixtures/raw_signature/ps512.pub");
+ let private_key = include_bytes!("../../fixtures/raw_signature/ps512.priv");
+
+ let signer =
+ rust_native::signer_from_cert_chain_and_private_key(cert_chain, private_key, SigningAlg::Ps512, None)
+ .unwrap();
+
+ let data = b"some sample content to sign";
+ let signature = signer.sign(data).unwrap();
+
+ println!("signature len = {}", signature.len());
+ assert!(signature.len() <= signer.reserve_size());
+
+ let pub_key = include_bytes!("../../fixtures/raw_signature/ps512.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Ps512).unwrap();
+ validator.validate(&signature, data, pub_key).unwrap();
+}
+*/
diff --git a/internal/crypto/src/tests/raw_signature/rust_native/validators.rs b/internal/crypto/src/tests/raw_signature/rust_native/validators.rs
new file mode 100644
index 000000000..a58ec18af
--- /dev/null
+++ b/internal/crypto/src/tests/raw_signature/rust_native/validators.rs
@@ -0,0 +1,288 @@
+// Copyright 2024 Adobe. All rights reserved.
+// This file is licensed to you under the Apache License,
+// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+// or the MIT license (http://opensource.org/licenses/MIT),
+// at your option.
+
+// Unless required by applicable law or agreed to in writing,
+// this software is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
+// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
+// specific language governing permissions and limitations under
+// each license.
+
+#[cfg(target_arch = "wasm32")]
+use wasm_bindgen_test::wasm_bindgen_test;
+
+use crate::raw_signature::{rust_native, RawSignatureValidationError, SigningAlg};
+
+const SAMPLE_DATA: &[u8] = b"some sample content to sign";
+
+/* Not implemented in rust_native yet.
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn es256() {
+ let signature = include_bytes!("../../fixtures/raw_signature/es256.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/es256.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Es256).unwrap();
+
+ validator.validate(signature, SAMPLE_DATA, pub_key).unwrap();
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn es256_bad_signature() {
+ let mut signature = include_bytes!("../../fixtures/raw_signature/es256.raw_sig").to_vec();
+ assert_ne!(signature[10], 10);
+ signature[10] = 10;
+
+ let pub_key = include_bytes!("../../fixtures/raw_signature/es256.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Es256).unwrap();
+
+ assert_eq!(
+ validator
+ .validate(&signature, SAMPLE_DATA, pub_key)
+ .unwrap_err(),
+ RawSignatureValidationError::SignatureMismatch
+ );
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn es256_bad_data() {
+ let signature = include_bytes!("../../fixtures/raw_signature/es256.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/es256.pub_key");
+
+ let mut data = SAMPLE_DATA.to_vec();
+ data[10] = 0;
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Es256).unwrap();
+
+ assert_eq!(
+ validator.validate(signature, &data, pub_key).unwrap_err(),
+ RawSignatureValidationError::SignatureMismatch
+ );
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn es384() {
+ let signature = include_bytes!("../../fixtures/raw_signature/es384.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/es384.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Es384).unwrap();
+
+ validator.validate(signature, SAMPLE_DATA, pub_key).unwrap();
+}
+
+#[test]
+// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] // ES512 not
+// implemented
+fn es512() {
+ let signature = include_bytes!("../../fixtures/raw_signature/es512.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/es512.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Es512).unwrap();
+
+ validator.validate(signature, SAMPLE_DATA, pub_key).unwrap();
+}
+*/
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn ed25519() {
+ let signature = include_bytes!("../../fixtures/raw_signature/ed25519.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/ed25519.pub_key");
+
+ let validator =
+ rust_native::validators::validator_for_signing_alg(SigningAlg::Ed25519).unwrap();
+
+ validator.validate(signature, SAMPLE_DATA, pub_key).unwrap();
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn ed25519_bad_data() {
+ let signature = include_bytes!("../../fixtures/raw_signature/ed25519.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/ed25519.pub_key");
+
+ let mut data = SAMPLE_DATA.to_vec();
+ data[5] = 10;
+ data[6] = 11;
+
+ let validator =
+ rust_native::validators::validator_for_signing_alg(SigningAlg::Ed25519).unwrap();
+
+ assert_eq!(
+ validator.validate(signature, &data, pub_key).unwrap_err(),
+ RawSignatureValidationError::SignatureMismatch
+ );
+}
+
+/* Not implemented in rust_native yet.
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn ps256() {
+ let signature = include_bytes!("../../fixtures/raw_signature/ps256.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/ps256.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Ps256).unwrap();
+
+ validator.validate(signature, SAMPLE_DATA, pub_key).unwrap();
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn ps256_bad_signature() {
+ let mut signature = include_bytes!("../../fixtures/raw_signature/ps256.raw_sig").to_vec();
+ assert_ne!(signature[10], 10);
+ signature[10] = 10;
+
+ let pub_key = include_bytes!("../../fixtures/raw_signature/ps256.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Ps256).unwrap();
+
+ assert_eq!(
+ validator
+ .validate(&signature, SAMPLE_DATA, pub_key)
+ .unwrap_err(),
+ RawSignatureValidationError::SignatureMismatch
+ );
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn ps256_bad_data() {
+ let signature = include_bytes!("../../fixtures/raw_signature/ps256.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/ps256.pub_key");
+
+ let mut data = SAMPLE_DATA.to_vec();
+ data[10] = 0;
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Ps256).unwrap();
+
+ assert_eq!(
+ validator.validate(signature, &data, pub_key).unwrap_err(),
+ RawSignatureValidationError::SignatureMismatch
+ );
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn ps384() {
+ let signature = include_bytes!("../../fixtures/raw_signature/ps384.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/ps384.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Ps384).unwrap();
+
+ validator.validate(signature, SAMPLE_DATA, pub_key).unwrap();
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn ps512() {
+ let signature = include_bytes!("../../fixtures/raw_signature/ps512.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/ps512.pub_key");
+
+ let validator = rust_native::validators::validator_for_signing_alg(SigningAlg::Ps512).unwrap();
+
+ validator.validate(signature, SAMPLE_DATA, pub_key).unwrap();
+}
+
+// Argh. Different Oid types across different crates, so we have to construct
+// our own constants here.
+const RSA_OID: Oid = bcder::Oid(OctetString::from_static(&[
+ 42, 134, 72, 134, 247, 13, 1, 1, 1,
+]));
+
+const SHA256_OID: Oid = bcder::Oid(OctetString::from_static(&[96, 134, 72, 1, 101, 3, 4, 2, 1]));
+
+const SHA384_OID: Oid = bcder::Oid(OctetString::from_static(&[96, 134, 72, 1, 101, 3, 4, 2, 2]));
+
+const SHA512_OID: Oid = bcder::Oid(OctetString::from_static(&[96, 134, 72, 1, 101, 3, 4, 2, 3]));
+
+const SHA1_OID: Oid = bcder::Oid(OctetString::from_static(&[43, 14, 3, 2, 26]));
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn legacy_rs256() {
+ let signature = include_bytes!("../../fixtures/raw_signature/legacy/rs256.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs256.pub_key");
+
+ let validator = validator_for_sig_and_hash_algs(&RSA_OID, &SHA256_OID).unwrap();
+
+ validator.validate(signature, SAMPLE_DATA, pub_key).unwrap();
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn legacy_rs256_bad_signature() {
+ let mut signature = include_bytes!("../../fixtures/raw_signature/legacy/rs256.raw_sig").to_vec();
+ assert_ne!(signature[10], 10);
+ signature[10] = 10;
+
+ let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs256.pub_key");
+
+ let validator = validator_for_sig_and_hash_algs(&RSA_OID, &SHA256_OID).unwrap();
+
+ assert_eq!(
+ validator
+ .validate(&signature, SAMPLE_DATA, pub_key)
+ .unwrap_err(),
+ RawSignatureValidationError::SignatureMismatch
+ );
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn legacy_rs256_bad_data() {
+ let signature = include_bytes!("../../fixtures/raw_signature/legacy/rs256.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs256.pub_key");
+
+ let mut data = SAMPLE_DATA.to_vec();
+ data[10] = 0;
+
+ let validator = validator_for_sig_and_hash_algs(&RSA_OID, &SHA256_OID).unwrap();
+
+ assert_eq!(
+ validator.validate(signature, &data, pub_key).unwrap_err(),
+ RawSignatureValidationError::SignatureMismatch
+ );
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn rs384() {
+ let signature = include_bytes!("../../fixtures/raw_signature/legacy/rs384.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs384.pub_key");
+
+ let validator = validator_for_sig_and_hash_algs(&RSA_OID, &SHA384_OID).unwrap();
+
+ validator.validate(signature, SAMPLE_DATA, pub_key).unwrap();
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn rs512() {
+ let signature = include_bytes!("../../fixtures/raw_signature/legacy/rs512.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs512.pub_key");
+
+ let validator = validator_for_sig_and_hash_algs(&RSA_OID, &SHA512_OID).unwrap();
+
+ validator.validate(signature, SAMPLE_DATA, pub_key).unwrap();
+}
+
+#[test]
+// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] // SHA1 not
+// implemented
+fn sha1() {
+ let signature = include_bytes!("../../fixtures/raw_signature/legacy/sha1.raw_sig");
+ let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/sha1.pub_key");
+
+ let validator = validator_for_sig_and_hash_algs(&RSA_OID, &SHA1_OID).unwrap();
+
+ validator.validate(signature, SAMPLE_DATA, pub_key).unwrap();
+}
+*/