{"id":1793,"library":"xmlsec","title":"Python XML Security Library Bindings","description":"The `xmlsec` library provides Python bindings for the XML Security Library, enabling XML digital signatures, encryption, and other security operations on XML documents. It is actively maintained with frequent updates, often focused on ensuring compatibility with specific versions of the underlying `lxml` and `libxml2` libraries. The current version is 1.3.17.","status":"active","version":"1.3.17","language":"en","source_language":"en","source_url":"https://github.com/mehcode/python-xmlsec","tags":["xml","security","signature","encryption","lxml"],"install":[{"cmd":"pip install xmlsec","lang":"bash","label":"Install `xmlsec`"}],"dependencies":[{"reason":"Crucial for processing XML and generating/verifying signatures. Binary wheels for `xmlsec` have strict `lxml` version requirements due to shared underlying `libxml2`.","package":"lxml","optional":false}],"imports":[{"symbol":"xmlsec","correct":"import xmlsec"},{"note":"While `xmlsec` can sometimes work with `xml.etree.ElementTree`, its full functionality, especially for signature context operations, is designed for `lxml.etree` elements.","symbol":"etree","correct":"from lxml import etree"}],"quickstart":{"code":"import xmlsec\nfrom lxml import etree\nimport os\n\n# Initialize xmlsec library\nxmlsec.init()\n\n# Define paths for key and certificate files\n# In a real application, replace these with your actual key and cert paths.\n# For this example to run, ensure these files exist or create dummy ones:\n# Example: openssl genrsa -out private_key.pem 2048\n# Example: openssl req -new -x509 -key private_key.pem -out certificate.pem -days 365\nkey_file = os.environ.get('XMLSEC_PRIVATE_KEY_PATH', 'private_key.pem')\ncert_file = os.environ.get('XMLSEC_CERTIFICATE_PATH', 'certificate.pem')\n\n# Basic check for dummy files for quickstart execution\nif not os.path.exists(key_file) or not os.path.exists(cert_file):\n    print(f\"Warning: '{key_file}' and '{cert_file}' not found. \"\n          \"Please generate dummy key/cert files for this quickstart to run.\")\n    # Minimal dummy content for illustration, DO NOT USE IN PRODUCTION\n    with open(key_file, 'w') as f: f.write(\"-----BEGIN PRIVATE KEY-----\\n...\\n-----END PRIVATE KEY-----\\n\")\n    with open(cert_file, 'w') as f: f.write(\"-----BEGIN CERTIFICATE-----\\n...\\n-----END CERTIFICATE-----\\n\")\n\ntry:\n    # Create an XML document using lxml\n    root = etree.Element(\"Data\")\n    etree.SubElement(root, \"Item\", id=\"item1\").text = \"Value1\"\n    \n    # Add a signature template to the root element\n    signature_node = xmlsec.template.add_signature(root, xmlsec.constants.TransformExclC14N)\n    \n    # Add SignedInfo element, reference the entire document\n    signed_info_node = xmlsec.template.ensure_signed_info(signature_node, \n                                                            xmlsec.constants.TransformExclC14N, \n                                                            xmlsec.constants.TransformRsaSha1)\n    xmlsec.template.add_reference(signed_info_node, xmlsec.constants.TransformSha1, uri=\"#xpointer(/)\")\n    \n    # Add KeyInfo element with certificate\n    key_info_node = xmlsec.template.ensure_key_info(signature_node)\n    xmlsec.template.add_x509_data(key_info_node)\n    xmlsec.template.add_x509_certificate(key_info_node) # Include the certificate itself\n    \n    # Create a KeysManager and load the private key for signing\n    manager = xmlsec.KeysManager()\n    signing_key = xmlsec.Key.from_file(key_file, xmlsec.KeyFormatPEM)\n    # Add the certificate to the key object for inclusion in KeyInfo\n    signing_key.add_cert_from_file(cert_file, xmlsec.KeyFormatPEM)\n    manager.add_key(signing_key)\n\n    # Create a SignatureContext and set the signing key\n    ctx = xmlsec.SignatureContext(manager)\n    ctx.key = signing_key\n    \n    # Sign the XML document\n    print(\"Signing XML document...\")\n    ctx.sign(signature_node)\n    \n    signed_xml_str = etree.tostring(root, pretty_print=True, encoding='unicode')\n    print(\"Signed XML:\\n\", signed_xml_str)\n\n    # Verify the signature\n    print(\"\\nVerifying signature...\")\n    verify_ctx = xmlsec.SignatureContext(manager) # Use the same manager with loaded key/cert\n    \n    if verify_ctx.verify(signature_node):\n        print(\"Signature is valid!\")\n    else:\n        print(\"Signature verification FAILED.\")\n\nfinally:\n    # Shutdown xmlsec library\n    xmlsec.shutdown()","lang":"python","description":"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."},"warnings":[{"fix":"Consult 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.","message":"Binary 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.","severity":"breaking","affected_versions":"All versions 1.3.16+"},{"fix":"Install 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`.","message":"When 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.","severity":"gotcha","affected_versions":"All versions when building from source"},{"fix":"Always 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.","message":"It 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.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}