使用Python / M2Crypto进行SAML签名验证

时间:2012-03-14 15:30:24

标签: python m2crypto saml-2.0

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

我的XML响应看起来有点像第二个例子here

ETA:here's我的实际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参数传递各种XML(SignedInfo标记,Response标记) ,整个事情),我已经尝试使用ElementTree / ElementC14N.py来确保XML是完全规范化的,因为转换暗示应该完成,但我没有得到积极的结果。

我在这里缺少什么?我是否尝试验证错误的XML?我的验证技术出了什么问题?

2 个答案:

答案 0 :(得分:2)

你太近了!您应该传递给verify_update signed_info,然后传递给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

答案 1 :(得分: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)