1

我正在尝试使用 M2Crypto 来验证从我的 django/python 应用程序中的 SSO/SAML 提供程序返回的 XML 响应中包含的签名,但我似乎无法让它工作。

我的 XML 响应看起来有点像这里的第二个示例。

ETA:我的实际 XML 的粘贴箱。

我正在使用这样的代码来尝试验证:

def verify_signature(signed_info, cert, signature):
    from M2Crypto import EVP, RSA, X509

    x509 = X509.load_cert_string(base64.decodestring(cert), X509.FORMAT_DER)
    pubkey = x509.get_pubkey().get_rsa()
    verify_EVP = EVP.PKey()
    verify_EVP.assign_rsa(pubkey)
    verify_EVP.reset_context(md='sha1')
    verify_EVP.verify_init()

    verify_EVP.verify_update(signature.decode('base64'))
    result = verify_EVP.verify_final(signed_info)

    return result

我可以从响应中成功获取 NameID,并且我知道我已成功加载证书,因为我可以从中拉出颁发者等。

不过,至于签名,我尝试过对传入的 XML 进行散列处理,对各种片段进行编码/不编码,并为signed_info参数(SignedInfo 标记、响应标记、整个东西)传入各种 XML 位,然后我'已经尝试使用 ElementTree/ ElementC14N.py来确保 XML 完全规范化,正如转换所暗示的那样,应该完成,但我没有得到积极的结果。

我在这里想念什么?我是否试图针对错误的 XML 进行验证?我的验证技术有问题吗?

4

2 回答 2

2

你离得太近了!您应该将已签名信息传递给 verify_update,然后将签名传递给 verify_final。

在验证签名之前,您确实需要确保您的 signed_info 已正确规范化。

下面是正确的方法:

def verify_signature(signed_info, cert, signature):
    from M2Crypto import EVP, RSA, X509

    x509 = X509.load_cert_string(base64.decodestring(cert), X509.FORMAT_DER)
    pubkey = x509.get_pubkey().get_rsa()
    verify_EVP = EVP.PKey()
    verify_EVP.assign_rsa(pubkey)
    verify_EVP.reset_context(md='sha1')
    verify_EVP.verify_init()

    verify_EVP.verify_update(signed_info)
    result = verify_EVP.verify_final(signature.decode('base64'))

    return result
于 2013-06-28T20:12:41.330 回答
1

仅供参考,我遇到了和你一样的问题,并没有发现在 Python 中验证 XML 签名的有用软件,所以我写了一个新库:https ://github.com/kislyuk/signxml 。

from lxml import etree
from signxml import xmldsig

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

root = ElementTree.fromstring(signature_data)
xmldsig(root).verify(x509_cert=cert)
于 2014-10-03T19:04:34.513 回答