Install & Compatibility
Where this runs
tested against v1.3.17 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.056s · 41.7MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 2.2s · import 0.050s · 42MB
40MB installed
● package 40MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
etree
✓ from lxml import etree
While `xmlsec` can sometimes work with `xml.etree.ElementTree`, its full functionality, especially for signature context operations, is designed for `lxml.etree` elements.
This quickstart demonstrates how to digitally sign an XML document and then verify its signature using `xmlsec` and `lxml`. It involves creating an XML structure, adding a signature template, loading a private key and certificate, signing the document, and finally verifying the signature. Make sure to replace `private_key.pem` and `certificate.pem` with your actual key and certificate files in a production environment.
import xmlsec
from lxml import etree
import os
# Initialize xmlsec library
xmlsec.init()
# Define paths for key and certificate files
# In a real application, replace these with your actual key and cert paths.
# For this example to run, ensure these files exist or create dummy ones:
# Example: openssl genrsa -out private_key.pem 2048
# Example: openssl req -new -x509 -key private_key.pem -out certificate.pem -days 365
key_file = os.environ.get('XMLSEC_PRIVATE_KEY_PATH', 'private_key.pem')
cert_file = os.environ.get('XMLSEC_CERTIFICATE_PATH', 'certificate.pem')
# Basic check for dummy files for quickstart execution
if not os.path.exists(key_file) or not os.path.exists(cert_file):
print(f"Warning: '{key_file}' and '{cert_file}' not found. "
"Please generate dummy key/cert files for this quickstart to run.")
# Minimal dummy content for illustration, DO NOT USE IN PRODUCTION
with open(key_file, 'w') as f: f.write("-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n")
with open(cert_file, 'w') as f: f.write("-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n")
try:
# Create an XML document using lxml
root = etree.Element("Data")
etree.SubElement(root, "Item", id="item1").text = "Value1"
# Add a signature template to the root element
signature_node = xmlsec.template.add_signature(root, xmlsec.constants.TransformExclC14N)
# Add SignedInfo element, reference the entire document
signed_info_node = xmlsec.template.ensure_signed_info(signature_node,
xmlsec.constants.TransformExclC14N,
xmlsec.constants.TransformRsaSha1)
xmlsec.template.add_reference(signed_info_node, xmlsec.constants.TransformSha1, uri="#xpointer(/)")
# Add KeyInfo element with certificate
key_info_node = xmlsec.template.ensure_key_info(signature_node)
xmlsec.template.add_x509_data(key_info_node)
xmlsec.template.add_x509_certificate(key_info_node) # Include the certificate itself
# Create a KeysManager and load the private key for signing
manager = xmlsec.KeysManager()
signing_key = xmlsec.Key.from_file(key_file, xmlsec.KeyFormatPEM)
# Add the certificate to the key object for inclusion in KeyInfo
signing_key.add_cert_from_file(cert_file, xmlsec.KeyFormatPEM)
manager.add_key(signing_key)
# Create a SignatureContext and set the signing key
ctx = xmlsec.SignatureContext(manager)
ctx.key = signing_key
# Sign the XML document
print("Signing XML document...")
ctx.sign(signature_node)
signed_xml_str = etree.tostring(root, pretty_print=True, encoding='unicode')
print("Signed XML:\n", signed_xml_str)
# Verify the signature
print("\nVerifying signature...")
verify_ctx = xmlsec.SignatureContext(manager) # Use the same manager with loaded key/cert
if verify_ctx.verify(signature_node):
print("Signature is valid!")
else:
print("Signature verification FAILED.")
finally:
# Shutdown xmlsec library
xmlsec.shutdown()
Debug
Known issues
breakingBinary wheels for `xmlsec` have strict version requirements for `lxml` due to shared underlying `libxml2`. Installing incompatible versions will lead to runtime errors like `ImportError: cannot import name _xmlsec from lxml.etree` or segfaults.fixConsult the `xmlsec` release notes for the exact `lxml` version required for your `xmlsec` version. For `xmlsec==1.3.17`, `lxml` must be `>= 6.0.2`. Pin `lxml` in your `requirements.txt` (e.g., `lxml>=6.0.2,<7.0`) to avoid conflicts.
affects: All versions 1.3.16+
gotchaWhen installing `xmlsec` from source (e.g., if no wheel is available for your platform/Python version), it requires the C libraries `libxml2` and `libxmlsec1` (including their development headers) to be installed on your system. Failure to do so will result in build errors.fixInstall the necessary system packages. For Debian/Ubuntu: `sudo apt-get install libxml2-dev libxmlsec1-dev`. For Fedora/RHEL/CentOS: `sudo dnf install libxml2-devel xmlsec1-devel`.
affects: All versions when building from source
gotchaIt is crucial to initialize the `xmlsec` library by calling `xmlsec.init()` at the start of your application and to properly clean up resources by calling `xmlsec.shutdown()` before your application exits. Failing to do so can lead to memory leaks or undefined behavior.fixAlways enclose your `xmlsec` operations within `xmlsec.init()` and `xmlsec.shutdown()` calls, ideally using a `try...finally` block to ensure `shutdown()` is called even if errors occur.
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'xmlsec'
The `xmlsec` Python package is not installed in the active Python environment, or its installation failed previously due to missing system dependencies.
fixInstall `xmlsec` using `pip install xmlsec`. If compilation errors occur, first install required system development packages (e.g., `sudo apt-get install libxml2-dev libxmlsec1-dev pkg-config` on Debian/Ubuntu, `sudo yum install libxml2-devel xmlsec1-devel pkgconfig` on RHEL/CentOS, or `brew install libxml2 xmlsec1` on macOS).
xmlsec/src/xmlsec.h:4:10: fatal error: libxml/tree.h: No such file or directory
The `xmlsec` Python package requires the `libxml2` development headers to be installed on the system for compilation, specifically `libxml/tree.h`.
fixInstall the system-level development package for `libxml2` (e.g., `libxml2-dev` on Debian/Ubuntu, `libxml2-devel` on RHEL/CentOS, or `libxml2` on macOS via Homebrew). A common installation command for Linux is `sudo apt-get install libxml2-dev libxmlsec1-dev pkg-config`.
xmlsec/src/xmlsec.h:5:10: fatal error: xmlsec/xmlsec.h: No such file or directory
The `xmlsec` Python package requires the `libxmlsec1` development headers to be installed on the system for compilation, specifically `xmlsec/xmlsec.h`.
fixInstall the system-level development package for `libxmlsec1` (e.g., `libxmlsec1-dev` on Debian/Ubuntu, `xmlsec1-devel` on RHEL/CentOS, or `xmlsec1` on macOS via Homebrew). A common installation command for Linux is `sudo apt-get install libxml2-dev libxmlsec1-dev pkg-config`.
ImportError: cannot import name 'init' from 'xmlsec'
The functions `init` and `constants` (among others) were moved from the top-level `xmlsec` module to `xmlsec.core` in newer versions of the library.
fixUpdate your import statements to import `init` (and `constants`) from `xmlsec.core`.
```python
# Before (incorrect)
# from xmlsec import init
# from xmlsec import constants
# After (correct)
from xmlsec.core import init
from xmlsec.core import constants
```
xmlsec.XMLSigError: XML Security Library is not initialized
The underlying XML Security Library has not been initialized by calling `xmlsec.core.init()` before performing any cryptographic operations.
fixCall `xmlsec.core.init()` once at the start of your application before any other `xmlsec` operations.
```python
import xmlsec
from xmlsec.core import init, shutdown
init()
try:
# Your xmlsec operations here
pass
finally:
shutdown() # Optional, but good practice if explicitly managing resources
``` Upgrade
Version history
1.3.17latest on PyPI · released Nov 11, 2025
Audit
Dependencies
lxmlrequiredCrucial for processing XML and generating/verifying signatures. Binary wheels for `xmlsec` have strict `lxml` version requirements due to shared underlying `libxml2`.