我正在尝试使用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?我的验证技术出了什么问题?
答案 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)