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
14 changes: 8 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,19 @@ roxmltree = { version = "0.21", features = ["positions"] }
quick-xml = "0.38"

# Crypto
rsa = { version = "0.9", optional = true }
sha1 = { version = "0.10", features = ["oid"], optional = true }
sha2 = { version = "0.10", features = ["oid"], optional = true }
p256 = { version = "0.13", features = ["ecdsa"], optional = true }
p384 = { version = "0.13", features = ["ecdsa"], optional = true }
p521 = { version = "0.13", features = ["ecdsa"], optional = true }
rsa = { version = "0.10.0-rc.18", optional = true }
sha1 = { version = "0.11", features = ["oid"], optional = true }
sha2 = { version = "0.11", features = ["oid"], optional = true }
p256 = { version = "0.14", features = ["ecdsa"], optional = true }
p384 = { version = "0.14.0-rc.15", features = ["ecdsa"], optional = true }
p521 = { version = "0.14.0-rc.15", features = ["ecdsa"], optional = true }
signature = { version = "3", optional = true }
subtle = { version = "2", optional = true }

# X.509 certificates
x509-parser = { version = "0.18", features = ["verify"], optional = true }
der = { version = "0.8", optional = true }
crypto-bigint = { version = "0.7", optional = true }

# Base64 encoding/decoding
base64 = "0.22"
Expand All @@ -45,6 +46,7 @@ time = "0.3.53"
default = ["xmldsig", "c14n"]
xmldsig = [ # XML Digital Signatures (sign + verify)
"dep:der",
"dep:crypto-bigint",
"dep:p256",
"dep:p384",
"dep:p521",
Expand Down
26 changes: 17 additions & 9 deletions src/xmldsig/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

use std::{collections::HashMap, time::SystemTime};

use p256::pkcs8::EncodePublicKey;
use crypto_bigint::BoxedUint;
use p256::pkcs8::EncodePublicKey as P256EncodePublicKey;
use x509_parser::{
prelude::{FromDer, X509Certificate},
public_key::PublicKey,
Expand Down Expand Up @@ -398,8 +399,8 @@ fn rsa_key_value_to_spki_der(
exponent: &[u8],
) -> Result<Vec<u8>, KeyResolutionError> {
let key = rsa::RsaPublicKey::new(
rsa::BigUint::from_bytes_be(modulus),
rsa::BigUint::from_bytes_be(exponent),
BoxedUint::from_be_slice_vartime(modulus),
BoxedUint::from_be_slice_vartime(exponent),
)
.map_err(|_| KeyResolutionError::InvalidPublicKey)?;
key.to_public_key_der()
Expand Down Expand Up @@ -527,6 +528,13 @@ mod tests {
format!("{}{}{}", &xml[..start], replacement, &xml[end..])
}

fn rsa_key_value_parts(public_key: &rsa::RsaPublicKey) -> (String, String) {
(
STANDARD.encode(public_key.n().to_be_bytes_trimmed_vartime()),
STANDARD.encode(public_key.e().to_be_bytes_trimmed_vartime()),
)
}

fn x509_signature_with_leaf_subject() -> String {
replace_unprefixed_key_info(
X509_DIGEST_SIGNATURE,
Expand Down Expand Up @@ -850,10 +858,10 @@ mod tests {
// Embedded CryptoBinary parameters must verify the original RSA-2048 donor signature.
let public_key = rsa::RsaPublicKey::from_public_key_pem(RSA_PUBLIC_KEY)
.expect("fixture must contain an RSA public key");
let (modulus, exponent) = rsa_key_value_parts(&public_key);
let key_info = format!(
"<KeyInfo><KeyValue><RSAKeyValue><Modulus>{}</Modulus><Exponent>{}</Exponent></RSAKeyValue></KeyValue></KeyInfo>",
STANDARD.encode(public_key.n().to_bytes_be()),
STANDARD.encode(public_key.e().to_bytes_be()),
modulus, exponent,
);
let xml = replace_unprefixed_key_info(RSA_KEY_VALUE_SIGNATURE, &key_info);
let resolver = DefaultKeyResolver::default();
Expand Down Expand Up @@ -885,10 +893,10 @@ mod tests {
// Embedded RSA parameters must not be relabeled for an ECDSA SignatureMethod.
let public_key = rsa::RsaPublicKey::from_public_key_pem(RSA_PUBLIC_KEY)
.expect("fixture must contain an RSA public key");
let (modulus, exponent) = rsa_key_value_parts(&public_key);
let key_info = format!(
"<ds:KeyInfo><ds:KeyValue><ds:RSAKeyValue><ds:Modulus>{}</ds:Modulus><ds:Exponent>{}</ds:Exponent></ds:RSAKeyValue></ds:KeyValue></ds:KeyInfo>",
STANDARD.encode(public_key.n().to_bytes_be()),
STANDARD.encode(public_key.e().to_bytes_be()),
modulus, exponent,
);
let xml = replace_key_info(SIGNED_SAML, &key_info);
let resolver = DefaultKeyResolver::default();
Expand Down Expand Up @@ -949,10 +957,10 @@ mod tests {
// Mixed KeyInfo should keep scanning after an incompatible ECKeyValue source.
let public_key = rsa::RsaPublicKey::from_public_key_pem(RSA_PUBLIC_KEY)
.expect("fixture must contain an RSA public key");
let (modulus, exponent) = rsa_key_value_parts(&public_key);
let key_info = format!(
r#"<KeyInfo xmlns:dsig11="http://www.w3.org/2009/xmldsig11#"><KeyValue><dsig11:ECKeyValue><dsig11:NamedCurve URI="urn:oid:1.2.840.10045.3.1.7"/><dsig11:PublicKey>BJ/yaXNlq4FRObyJCBhb5jAz8GVzinK3bBGLjSDfjbJwNfydtgjnlS4EsDmxSRhWyJWq6GIqy5wvnaiARK04uB4=</dsig11:PublicKey></dsig11:ECKeyValue></KeyValue><KeyValue><RSAKeyValue><Modulus>{}</Modulus><Exponent>{}</Exponent></RSAKeyValue></KeyValue></KeyInfo>"#,
STANDARD.encode(public_key.n().to_bytes_be()),
STANDARD.encode(public_key.e().to_bytes_be()),
modulus, exponent,
);
let xml = replace_unprefixed_key_info(RSA_KEY_VALUE_SIGNATURE, &key_info);
let resolver = DefaultKeyResolver::default();
Expand Down
1 change: 1 addition & 0 deletions src/xmldsig/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
pub mod builder;
pub mod digest;
pub mod keys;
pub mod mutation;
pub mod parse;
pub mod signature;
pub mod transforms;
Expand Down
Loading