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
26 changes: 22 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@ readme = "README.md"
roxmltree = { version = "0.21", features = ["positions"] }

# Crypto
ring = "0.17"
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 }
signature = { version = "2", optional = true }
subtle = { version = "2", optional = true }

# X.509 certificates
x509-parser = "0.18"
der = "0.8"
x509-parser = { version = "0.18", optional = true }
der = { version = "0.8", optional = true }

# Base64 encoding/decoding
base64 = "0.22"
Expand All @@ -31,6 +38,17 @@ thiserror = "2"

[features]
default = ["xmldsig", "c14n"]
xmldsig = [] # XML Digital Signatures (sign + verify)
xmldsig = [ # XML Digital Signatures (sign + verify)
"dep:der",
"dep:p256",
"dep:p384",
"dep:p521",
"dep:rsa",
"dep:sha1",
"dep:sha2",
"dep:signature",
"dep:subtle",
"dep:x509-parser",
]
xmlenc = [] # XML Encryption (encrypt + decrypt)
c14n = [] # XML Canonicalization (inclusive + exclusive)
32 changes: 12 additions & 20 deletions src/xmldsig/digest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
//! Implements [XMLDSig §6.1](https://www.w3.org/TR/xmldsig-core1/#sec-DigestMethod):
//! compute message digests over transform output bytes using SHA-family algorithms.
//!
//! All digest computation uses `ring::digest` (no custom implementations).
//! All digest computation uses RustCrypto hash implementations.

use ring::digest;
use sha1::Sha1;
use sha2::{Digest, Sha256, Sha384, Sha512};
use subtle::ConstantTimeEq;

/// Digest algorithms supported by XMLDSig.
///
Expand Down Expand Up @@ -73,24 +75,18 @@ impl DigestAlgorithm {
Self::Sha512 => 64,
}
}

/// Map to the corresponding `ring::digest` algorithm.
fn ring_algorithm(self) -> &'static digest::Algorithm {
match self {
Self::Sha1 => &digest::SHA1_FOR_LEGACY_USE_ONLY,
Self::Sha256 => &digest::SHA256,
Self::Sha384 => &digest::SHA384,
Self::Sha512 => &digest::SHA512,
}
}
}

/// Compute the digest of `data` using the specified algorithm.
///
/// Returns the raw digest bytes (not base64-encoded).
pub fn compute_digest(algorithm: DigestAlgorithm, data: &[u8]) -> Vec<u8> {
let result = digest::digest(algorithm.ring_algorithm(), data);
result.as_ref().to_vec()
match algorithm {
DigestAlgorithm::Sha1 => Sha1::digest(data).to_vec(),
DigestAlgorithm::Sha256 => Sha256::digest(data).to_vec(),
DigestAlgorithm::Sha384 => Sha384::digest(data).to_vec(),
DigestAlgorithm::Sha512 => Sha512::digest(data).to_vec(),
}
}

/// Constant-time comparison of two byte slices.
Expand All @@ -100,13 +96,9 @@ pub fn compute_digest(algorithm: DigestAlgorithm, data: &[u8]) -> Vec<u8> {
/// where they differ — preventing timing side-channel attacks on digest
/// comparison.
///
/// Uses `ring::constant_time::verify_slices_are_equal` internally.
/// Uses `subtle` constant-time equality.
pub fn constant_time_eq(a: &[u8], b: &[u8]) -> bool {
#[expect(
deprecated,
reason = "legacy ring constant-time helper is still used here"
)]
ring::constant_time::verify_slices_are_equal(a, b).is_ok()
a.ct_eq(b).into()
}

#[cfg(test)]
Expand Down
7 changes: 6 additions & 1 deletion src/xmldsig/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@ pub enum SignatureAlgorithm {
RsaSha512,
/// ECDSA P-256 with SHA-256.
EcdsaP256Sha256,
/// ECDSA P-384 with SHA-384.
/// XMLDSig `ecdsa-sha384` URI.
///
/// The variant name is historical.
///
/// Verification currently accepts this XMLDSig URI for P-384 and for the
/// donor P-521 interop case.
EcdsaP384Sha384,
}

Expand Down
Loading