Skip to main content

xml_sec/
lib.rs

1//! # xml-sec — Pure Rust XML Security
2//!
3//! Drop-in replacement for libxmlsec1. XMLDSig, XMLEnc, C14N — no C dependencies.
4//!
5//! ## Features
6//!
7//! - **C14N** — XML Canonicalization (inclusive + exclusive)
8//! - **XMLDSig** — XML Digital Signatures (sign + verify)
9//! - **XMLEnc** — XML Encryption (encrypt + decrypt)
10//! - **X.509** — Certificate-based key extraction
11//!
12//! ## Quick Start
13//!
14//! ```rust
15//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
16//! use xml_sec::c14n::{C14nAlgorithm, C14nMode, canonicalize_xml};
17//!
18//! let xml = b"<root b=\"2\" a=\"1\"><empty/></root>";
19//! let algo = C14nAlgorithm::new(C14nMode::Inclusive1_0, false);
20//! let canonical = canonicalize_xml(xml, &algo)?;
21//! assert_eq!(
22//!     String::from_utf8(canonical)?,
23//!     "<root a=\"1\" b=\"2\"><empty></empty></root>"
24//! );
25//! # Ok(())
26//! # }
27//! ```
28
29#![deny(unsafe_code)]
30#![deny(clippy::unwrap_used)]
31#![warn(missing_docs)]
32
33extern crate alloc;
34#[cfg(feature = "xmldsig")]
35#[macro_use]
36extern crate peresil;
37
38#[cfg(not(any(feature = "xml-backend-xmloxide", feature = "xml-backend-roxmltree")))]
39compile_error!(
40    "compile at least one XML backend: `xml-backend-xmloxide` or `xml-backend-roxmltree`"
41);
42
43#[cfg(feature = "benchmark-internals")]
44#[doc(hidden)]
45pub mod benchmark_support;
46pub mod c14n;
47pub mod document;
48pub mod encoding;
49pub mod error;
50mod hard_limits;
51#[cfg(feature = "xmldsig")]
52pub mod rsa_encoding;
53#[cfg(feature = "xmldsig")]
54#[path = "rustcrypto_sha3/lib.rs"]
55mod rustcrypto_sha3;
56// Checksum-pinned RustCrypto ML-DSA with checked expanded-key import. Keep it
57// inside the published package: Cargo patches do not propagate to consumers.
58#[cfg(feature = "experimental-pq")]
59#[allow(dead_code, unused_imports, missing_docs)]
60#[cfg_attr(test, allow(clippy::unwrap_used, deprecated))]
61#[path = "rustcrypto_ml_dsa/lib.rs"]
62mod rustcrypto_ml_dsa;
63#[cfg(feature = "xmldsig")]
64// The same sources also build as standalone crates for the XSLT workspace member.
65// Only their XPath-facing surface is used by this package.
66#[doc(hidden)]
67#[allow(dead_code, unused_imports, missing_docs)]
68#[cfg_attr(test, allow(clippy::unwrap_used))]
69#[path = "sxd_document/lib.rs"]
70mod sxd_document;
71#[cfg(feature = "xmldsig")]
72#[doc(hidden)]
73#[allow(dead_code, unused_imports, missing_docs)]
74#[cfg_attr(test, allow(clippy::unwrap_used))]
75#[path = "sxd_xpath/lib.rs"]
76mod sxd_xpath;
77#[path = "xml_input/shared.rs"]
78// The internal xml-input crate also compiles this source for XSLT's wider API.
79#[allow(dead_code)]
80mod xml_input_shared;
81/// Bounded XML input decoding and lexical helpers.
82///
83/// [`decode_xml_bounded`] accepts trusted encoding metadata and a caller-supplied
84/// decoded-byte limit. The unbounded internal helpers are not public.
85///
86/// ```compile_fail
87/// use xml_sec::xml_input::decode_xml;
88/// ```
89pub mod xml_input {
90    pub use crate::xml_input_shared::{Error, decode_xml_bounded, lexical};
91}
92#[cfg(all(test, feature = "xmldsig"))]
93pub(crate) use sxd_document::{Package, QName, dom};
94#[cfg(feature = "xmldsig")]
95pub(crate) use sxd_document::{StorageRequirements, XML_NS_PREFIX, XML_NS_URI, str, string_pool};
96#[cfg(all(test, feature = "xmldsig"))]
97pub(crate) use sxd_xpath::{Context, Factory};
98#[cfg(feature = "xmldsig")]
99pub(crate) use sxd_xpath::{
100    LiteralValue, OwnedPrefixedName, OwnedQName, ParseBudget, Value, axis, context, expression,
101    function, node_test, node_to_num_with_context, nodeset, parser, str_to_num, token, tokenizer,
102};
103#[cfg(feature = "xmldsig")]
104pub mod key_establishment;
105#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
106mod operation;
107#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
108pub mod policy;
109#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
110pub mod provider;
111mod xml;
112
113pub use xml::IdAttributeRegistration;
114pub use xml::dom::{
115    Ancestors, Attribute, Attributes, Children, Descendants, Document, Document as XmlDomDocument,
116    ExpandedName, Namespace, Namespaces, Node, Node as XmlDomNode, NodeId, NodeId as XmlDomNodeId,
117    NodeType, PI, ParseError, ParseError as XmlDomParseError, ParsingOptions,
118    ParsingOptions as XmlDomParsingOptions, XmlBackend, XmlIdError,
119};
120
121#[cfg(feature = "xmldsig")]
122pub mod key_manager;
123#[cfg(feature = "xmldsig")]
124pub mod xmldsig;
125
126#[cfg(feature = "xmlenc")]
127pub mod xmlenc;
128
129#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
130pub use document::XmlDocumentPolicy;
131pub use document::{
132    AttributeIdentity, DocumentIdentity, DocumentView, NamespaceIdentity, NodeIdentity,
133    SemanticOrder, XmlDocument, XmlDocumentError,
134};
135pub use error::XmlSecError;