跳转到主要内容

Python XML签名和XAdES库

项目描述

SignXML是W3CXML签名标准的Python实现。此标准(也称为“XMLDSig”)用于提供SAML 2.0XAdESWS-Security等用途中的有效载荷安全。该标准在W3C推荐 XML签名语法和处理版本1.1中定义。SignXML实现了1.1版本标准的所有必需组件以及大多数推荐组件。其功能包括

  • 使用基于libxml2的XML解析器,在验证签名时配置为防御常见的XML攻击

  • 扩展以允许使用X.509证书链进行签名和验证,包括主机名/CN验证

  • 扩展以签名和验证XAdES签名

  • 支持具有包容性前缀的独占XML规范化(包容性命名空间前缀列表,某些SAML实现生成的签名所需的验证)

  • 现代Python兼容性(3.7-3.11+和PyPy)

  • 广泛支持、便携、可靠的依赖项: lxmlcryptography

  • 全面测试(包括XMLDSig互操作性套件)和持续集成

  • 简单界面,具有实用、人体工程学和安全的默认值(无网络调用、XSLT或XPath转换)

  • 紧凑性、可读性和可扩展性

安装

pip install signxml

概要

SignXML使用lxml ElementTree API来处理XML数据。

from lxml import etree
from signxml import XMLSigner, XMLVerifier

data_to_sign = "<Test/>"
cert = open("cert.pem").read()
key = open("privkey.pem").read()
root = etree.fromstring(data_to_sign)
signed_root = XMLSigner().sign(root, key=key, cert=cert)
verified_data = XMLVerifier().verify(signed_root).signed_xml

为了使此示例在测试目的上自给自足

  • 使用以下命令生成测试证书和密钥:openssl req -x509 -nodes -subj "/CN=test" -days 1 -newkey rsa -keyout privkey.pem -out cert.pem(如果找不到openssl可执行文件,请运行apt-get install opensslyum install opensslbrew install openssl)。

  • x509_cert=cert关键字参数传递给XMLVerifier.verify()。在生产环境中,请确保用正确的配置替换此配置,以信任CA或证书 - 这决定了你的应用程序信任哪些签名。)

验证SAML断言

假设metadata.xml包含断言源的SAML元数据

from lxml import etree
from base64 import b64decode
from signxml import XMLVerifier

with open("metadata.xml", "rb") as fh:
    cert = etree.parse(fh).find("//ds:X509Certificate").text

assertion_data = XMLVerifier().verify(b64decode(assertion_body), x509_cert=cert).signed_xml

XML签名构造方法:封装、非封装、封装

XML签名规范定义了三种组合签名的数据签名的三种方式:封装、分离和封装签名。封装是默认方法。要指定要生成的签名类型,请将method参数传递给sign()

signed_root = XMLSigner(method=signxml.methods.detached).sign(root, key=key, cert=cert)
verified_data = XMLVerifier().verify(signed_root).signed_xml

对于分离签名,上述代码将使用rootIdID属性来生成一个相对URI(<Reference URI="#value">)。您还可以通过将reference_uri参数传递给sign()来覆盖URI的值。要验证引用外部实体的分离签名,请将可调用的解析器传递给XMLVerifier().verify(data, uri_resolver=...)

有关更多详细信息,请参阅API文档

XML表示细节:配置命名空间前缀和空白

某些应用程序需要特定的命名空间前缀配置 - 例如,许多应用程序假定http://www.w3.org/2000/09/xmldsig#命名空间被设置为默认的无前缀命名空间,而不是使用习惯的ds:前缀。虽然在实际使用中命名空间前缀命名是一个不重要的表示细节,但在某些XML规范化签名配置中可能很重要。在生成签名时配置命名空间前缀映射,请设置XMLSigner.namespaces属性

signer = signxml.XMLSigner(...)
signer.namespaces = {None: signxml.namespaces.ds}
signed_root = signer.sign(...)

同样,签名文档中的空白对XML规范化和签名目的也很重要。在生成签名后不要美化打印XML,因为这可能会不幸地使签名无效。

XML解析安全性和与xml.etree.ElementTree的兼容性

SignXML使用lxml ElementTree库,而不是Python标准库中的ElementTree,来处理XML。由于lxml具有优异的抵抗XML攻击的能力,以及XML规范化和命名空间组织功能,因此使用lxml。建议在进一步解析之前直接将XML字符串输入传递给signxml,并通常使用lxml处理不受信任的XML输入。如果您确实将xml.etree.ElementTree对象传递给SignXML,您应该意识到这两个库之间XML命名空间处理的不同之处。有关更多信息,请参阅以下参考资料

XAdES签名

XAdES(“XML高级电子签名”)是用于将元数据附加到XML签名对象的规范。该规范得到了欧盟的认可,作为其实施其电子签名法规的规范。

SignXML支持使用XAdES签名进行文档的签名和验证

from signxml import DigestAlgorithm
from signxml.xades import (XAdESSigner, XAdESVerifier, XAdESVerifyResult,
                           XAdESSignaturePolicy, XAdESDataObjectFormat)
signature_policy = XAdESSignaturePolicy(
    Identifier="MyPolicyIdentifier",
    Description="Hello XAdES",
    DigestMethod=DigestAlgorithm.SHA256,
    DigestValue="Ohixl6upD6av8N7pEvDABhEL6hM=",
)
data_object_format = XAdESDataObjectFormat(
    Description="My XAdES signature",
    MimeType="text/xml",
)
signer = XAdESSigner(
    signature_policy=signature_policy,
    claimed_roles=["signer"],
    data_object_format=data_object_format,
    c14n_algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315",
)
signed_doc = signer.sign(doc, key=private_key, cert=certificate)
verifier = XAdESVerifier()
verify_results = verifier.verify(
    signed_doc, x509_cert=certificate, expect_references=3, expect_signature_policy=signature_policy
)
for verify_result in verify_results:
    if isinstance(verify_result, XAdESVerifyResult):
        verify_result.signed_properties  # use this to access parsed XAdES properties

作者

许可证

版权所有 2014-2023,Andrey Kislyuk 和 SignXML 贡献者。根据 Apache 许可证 2.0 版本 许可。根据 Apache 许可证的规定,分发此包和衍生作品的源代码副本时,必须分发 LICENSE 和 NOTICE 文件。

https://github.com/XML-Security/signxml/workflows/Test%20suite/badge.svg https://codecov.io/github/XML-Security/signxml/coverage.svg?branch=master https://img.shields.io/pypi/v/signxml.svg https://img.shields.io/pypi/l/signxml.svg

项目详情


发布历史 发布通知 | RSS 源

下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源代码分发

signxml-4.0.2.tar.gz (59.6 kB 查看哈希值

上传时间 源代码

构建分发

signxml-4.0.2-py3-none-any.whl (58.3 kB 查看哈希值

上传时间 Python 3

由以下支持