xml_sec/xmldsig/mod.rs
1//! XML Digital Signatures (XMLDSig).
2//!
3//! Implements [XML Signature Syntax and Processing](https://www.w3.org/TR/xmldsig-core1/).
4//!
5//! ## Current Status
6//!
7//! - URI dereference: same-document references (`""`, `#id`, `#xpointer(/)`, `#xpointer(id('...'))`)
8//! - ID attribute resolution with configurable attribute names
9//! - Exact element, attribute, and namespace node sets for transform processing
10//! - Enveloped, canonicalization, Base64, XPath 1.0, and XPath Filter 2.0 transforms
11//!
12//! ## Signing and verification
13//!
14//! Build an enveloped signature with a modern algorithm, then verify it with
15//! the embedded certificate. New signatures must use SHA-256 or stronger;
16//! SHA-1 remains verification-only for legacy interoperability.
17//!
18//! ```no_run
19//! use xml_sec::c14n::{C14nAlgorithm, C14nMode};
20//! use xml_sec::xmldsig::{
21//! DefaultKeyResolver, DigestAlgorithm, ReferenceBuilder, RsaSigningKey,
22//! SignContext, SignatureAlgorithm, SignatureBuilder, Transform, VerifyContext,
23//! X509CertificateKeyInfoWriter,
24//! };
25//!
26//! # fn example(private_key_pem: &str, certificate_pem: &str) -> Result<(), Box<dyn std::error::Error>> {
27//! let c14n = C14nAlgorithm::new(C14nMode::Exclusive1_0, false);
28//! let template = SignatureBuilder::new(c14n.clone(), SignatureAlgorithm::RsaSha256)
29//! .add_reference(
30//! ReferenceBuilder::new(DigestAlgorithm::Sha256)
31//! .uri("#message")
32//! .transform(Transform::Enveloped)
33//! .transform(Transform::C14n(c14n)),
34//! )
35//! .key_info(true)
36//! .build_template()?;
37//! let xml = xml_sec::xmldsig::mutation::append_signature_to_root(
38//! "<Message ID=\"message\">hello</Message>",
39//! &template,
40//! )?;
41//! let signing_key = RsaSigningKey::from_pkcs8_pem(private_key_pem)?;
42//! let key_info = X509CertificateKeyInfoWriter::from_pem(certificate_pem)?;
43//! let signed = SignContext::new(&signing_key)
44//! .key_info_writer(&key_info)
45//! .sign_template(&xml)?;
46//!
47//! let resolver = DefaultKeyResolver::default();
48//! let result = VerifyContext::new().key_resolver(&resolver).verify(&signed)?;
49//! assert!(matches!(result.status, xml_sec::xmldsig::DsigStatus::Valid));
50//! # Ok(())
51//! # }
52//! ```
53#![doc = include_str!("../../docs/xmldsig.md")]
54
55pub mod builder;
56pub mod digest;
57pub mod keys;
58pub mod mutation;
59pub mod parse;
60pub mod sign;
61pub mod signature;
62pub mod transforms;
63pub mod types;
64pub mod uri;
65pub mod verify;
66pub(crate) mod whitespace;
67pub mod x509;
68mod xpath;
69
70pub use builder::{ReferenceBuilder, SignatureBuilder, SignatureBuilderError};
71pub use digest::{DigestAlgorithm, compute_digest, compute_digest_with_provider, constant_time_eq};
72pub use keys::{
73 DefaultKeyResolver, HmacSha1VerificationKey, KeyResolutionError, KeyResolverConfig,
74 VerificationKey,
75};
76pub use parse::{
77 KeyInfo, KeyInfoSource, KeyValueInfo, ParseError, Reference, RetrievalMethodTransforms,
78 SignatureAlgorithm, SignedInfo, X509DataInfo, find_signature_node, parse_key_info,
79 parse_reference, parse_signed_info, x509_certificate_matches_selectors,
80};
81pub use sign::{
82 ComputedReferenceDigest, EcdsaP256SigningKey, EcdsaP384SigningKey, KeyInfoWriteError,
83 KeyInfoWriter, RsaSigningKey, SignContext, SignatureTemplateSelection, SigningDigestError,
84 SigningError, SigningKey, SigningKeyError, SigningPublicKeyInfo, X509CertificateKeyInfoWriter,
85 compute_reference_digest_values, fill_reference_digest_values, validate_signing_key,
86};
87pub use signature::{
88 SignatureVerificationError, verify_dsa_signature_spki, verify_ecdsa_signature_pem,
89 verify_ecdsa_signature_spki, verify_rsa_signature_pem, verify_rsa_signature_spki,
90};
91pub use transforms::{
92 BASE64_TRANSFORM_URI, DEFAULT_IMPLICIT_C14N_URI, ENVELOPED_SIGNATURE_URI, Transform,
93 XPATH_FILTER2_TRANSFORM_URI, XPATH_TRANSFORM_URI, XPathExpression, XPathFilter,
94 XPathFilterOperation, XPathHereSemantics, execute_transforms, parse_transforms,
95};
96pub use types::{NodeSet, TransformData, TransformError};
97pub use verify::{
98 DsigError, DsigStatus, FailureReason, KeyResolver, ReferenceProcessingError, ReferenceResult,
99 ReferenceSet, ReferencesResult, SignatureSelection, UriTypeSet, VerifyContext, VerifyResult,
100 VerifyingKey, process_all_references, process_reference, verify_signature_with_pem_key,
101};
102pub use x509::{X509ChainError, X509ChainOptions, verify_x509_certificate_chain};