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// These XML parser kernels are checksum-pinned in scripts/import-xml-backends.sh.
52// Embedding the maintained sources also preserves the patch for package users.
53// Upstream navigation/construction APIs not used by this adapter stay private.
54#[cfg(feature = "xml-backend-roxmltree")]
55#[allow(dead_code, unused_imports, missing_docs)]
56#[cfg_attr(test, allow(clippy::unwrap_used))]
57#[path = "parser_roxmltree/lib.rs"]
58mod parser_roxmltree;
59#[cfg(feature = "xml-backend-xmloxide")]
60#[allow(dead_code, unused_imports, missing_docs)]
61#[cfg_attr(test, allow(clippy::unwrap_used))]
62#[path = "parser_xmloxide/lib.rs"]
63mod parser_xmloxide;
64#[cfg(feature = "xmldsig")]
65pub mod rsa_encoding;
66#[cfg(feature = "xmldsig")]
67#[path = "rustcrypto_sha3/lib.rs"]
68mod rustcrypto_sha3;
69// Checksum-pinned RustCrypto ML-DSA with checked expanded-key import. Keep it
70// inside the published package: Cargo patches do not propagate to consumers.
71#[cfg(feature = "experimental-pq")]
72#[allow(dead_code, unused_imports, missing_docs)]
73#[cfg_attr(test, allow(clippy::unwrap_used, deprecated))]
74#[path = "rustcrypto_ml_dsa/lib.rs"]
75mod rustcrypto_ml_dsa;
76#[cfg(feature = "xmldsig")]
77// The same sources also build as standalone crates for the XSLT workspace member.
78// Only their XPath-facing surface is used by this package.
79#[doc(hidden)]
80#[allow(dead_code, unused_imports, missing_docs)]
81#[cfg_attr(test, allow(clippy::unwrap_used))]
82#[path = "sxd_document/lib.rs"]
83mod sxd_document;
84#[cfg(feature = "xmldsig")]
85#[doc(hidden)]
86#[allow(dead_code, unused_imports, missing_docs)]
87#[cfg_attr(test, allow(clippy::unwrap_used))]
88#[path = "sxd_xpath/lib.rs"]
89mod sxd_xpath;
90// The same sources build the standalone XSLT workspace crate and its conformance suite.
91#[path = "xml_input/shared.rs"]
92// The internal xml-input crate also compiles this source for XSLT's wider API.
93#[allow(dead_code)]
94mod xml_input_shared;
95#[cfg(feature = "xslt")]
96#[doc(hidden)]
97#[allow(dead_code, unused_imports, missing_docs)]
98#[path = "xslt/lib.rs"]
99mod xslt;
100/// Bounded XML input decoding and lexical helpers.
101///
102/// [`decode_xml_bounded`](xml_input::decode_xml_bounded) accepts trusted encoding metadata and a caller-supplied
103/// decoded-byte limit. The unbounded internal helpers are not public.
104///
105/// ```compile_fail
106/// use xml_sec::xml_input::decode_xml;
107/// ```
108pub mod xml_input {
109    pub use crate::xml_input_shared::{Error, decode_xml_bounded, lexical};
110}
111#[cfg(all(test, feature = "xmldsig"))]
112pub(crate) use sxd_document::{Package, QName, dom};
113#[cfg(feature = "xmldsig")]
114pub(crate) use sxd_document::{StorageRequirements, XML_NS_PREFIX, XML_NS_URI, str, string_pool};
115#[cfg(all(test, feature = "xmldsig"))]
116pub(crate) use sxd_xpath::{Context, Factory};
117#[cfg(feature = "xmldsig")]
118pub(crate) use sxd_xpath::{
119    LiteralValue, OwnedPrefixedName, OwnedQName, ParseBudget, Value, axis, context, expression,
120    function, node_test, node_to_num_with_context, nodeset, parser, runtime, str_to_num, token,
121    tokenizer,
122};
123#[cfg(feature = "xmldsig")]
124pub mod key_establishment;
125#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
126mod operation;
127#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
128pub mod policy;
129#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
130pub mod provider;
131mod xml;
132
133pub use xml::IdAttributeRegistration;
134pub use xml::dom::{
135    Ancestors, Attribute, Attributes, Children, Descendants, Document, Document as XmlDomDocument,
136    ExpandedName, Namespace, Namespaces, Node, Node as XmlDomNode, NodeId, NodeId as XmlDomNodeId,
137    NodeType, PI, ParseError, ParseError as XmlDomParseError, ParsingOptions,
138    ParsingOptions as XmlDomParsingOptions, XmlBackend, XmlIdError,
139};
140
141#[cfg(feature = "xmldsig")]
142pub mod key_manager;
143#[cfg(feature = "xmldsig")]
144pub mod xmldsig;
145
146#[cfg(feature = "xmlenc")]
147pub mod xmlenc;
148
149#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
150pub use document::XmlDocumentPolicy;
151pub use document::{
152    AttributeIdentity, DocumentIdentity, DocumentView, NamespaceIdentity, NodeIdentity,
153    SemanticOrder, XmlDocument, XmlDocumentError,
154};
155pub use error::XmlSecError;