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#[path = "xml_input/shared.rs"]
91// The internal xml-input crate also compiles this source for XSLT's wider API.
92#[allow(dead_code)]
93mod xml_input_shared;
94/// Bounded XML input decoding and lexical helpers.
95///
96/// [`decode_xml_bounded`] accepts trusted encoding metadata and a caller-supplied
97/// decoded-byte limit. The unbounded internal helpers are not public.
98///
99/// ```compile_fail
100/// use xml_sec::xml_input::decode_xml;
101/// ```
102pub mod xml_input {
103    pub use crate::xml_input_shared::{Error, decode_xml_bounded, lexical};
104}
105#[cfg(all(test, feature = "xmldsig"))]
106pub(crate) use sxd_document::{Package, QName, dom};
107#[cfg(feature = "xmldsig")]
108pub(crate) use sxd_document::{StorageRequirements, XML_NS_PREFIX, XML_NS_URI, str, string_pool};
109#[cfg(all(test, feature = "xmldsig"))]
110pub(crate) use sxd_xpath::{Context, Factory};
111#[cfg(feature = "xmldsig")]
112pub(crate) use sxd_xpath::{
113    LiteralValue, OwnedPrefixedName, OwnedQName, ParseBudget, Value, axis, context, expression,
114    function, node_test, node_to_num_with_context, nodeset, parser, runtime, str_to_num, token,
115    tokenizer,
116};
117#[cfg(feature = "xmldsig")]
118pub mod key_establishment;
119#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
120mod operation;
121#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
122pub mod policy;
123#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
124pub mod provider;
125mod xml;
126
127pub use xml::IdAttributeRegistration;
128pub use xml::dom::{
129    Ancestors, Attribute, Attributes, Children, Descendants, Document, Document as XmlDomDocument,
130    ExpandedName, Namespace, Namespaces, Node, Node as XmlDomNode, NodeId, NodeId as XmlDomNodeId,
131    NodeType, PI, ParseError, ParseError as XmlDomParseError, ParsingOptions,
132    ParsingOptions as XmlDomParsingOptions, XmlBackend, XmlIdError,
133};
134
135#[cfg(feature = "xmldsig")]
136pub mod key_manager;
137#[cfg(feature = "xmldsig")]
138pub mod xmldsig;
139
140#[cfg(feature = "xmlenc")]
141pub mod xmlenc;
142
143#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
144pub use document::XmlDocumentPolicy;
145pub use document::{
146    AttributeIdentity, DocumentIdentity, DocumentView, NamespaceIdentity, NodeIdentity,
147    SemanticOrder, XmlDocument, XmlDocumentError,
148};
149pub use error::XmlSecError;