我需要使用saml2在python中从第三方实现身份验证。我已经调查了pysaml2发现这很令人困惑,并决定在我通过M2Crypto找到this question后给Ennael一个机会。
我收到的saml令牌can be found here。我已经从Assertion
标记(用户的ssn、ip和saml令牌到期窗口)提取了所需的所有信息,但无法从ennael获取verify_signature
函数(从revised code获取Ezra Nugroho函数)以返回true。我也尝试过将verify_EVP.reset_context(md='sha1')
改为verify_EVP.reset_context(md='sha256')
,但这也不起作用。
我想我的错误一定是在签名信息部分。对于那个部分,我要传递给verify_signature
什么?我需要以任何方式对它进行预处理吗?我一直在寻找转换标签,但不知道下一步也在哪里。
任何帮助都将不胜感激。如果有人在混淆之前需要XML来测试和帮助我只是PM我。
编辑这是我的代码(非常类似于我链接到的东西)。主要功能在底部):
def verify_signature(signed_info, cert, signature):
from M2Crypto import EVP, RSA, X509, m2
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)
return verify_EVP.verify_final(signature.decode('base64'))
def decode_response(resp):
return base64.b64decode(resp)
def get_xmldoc(xmlstring):
return XML(xmlstring)
def get_signature(doc):
return doc.find('{http://www.w3.org/2000/09/xmldsig#}Signature')
def get_signed_info(signature):
signed_info = signature.find(
'{http://www.w3.org/2000/09/xmldsig#}SignedInfo')
signed_info_str = tostring(signed_info)
# return parse(StringIO(signed_info_str))
return signed_info_str
def get_cert(signature):
ns = '{http://www.w3.org/2000/09/xmldsig#}'
keyinfo = signature.find('{}KeyInfo'.format(ns))
keydata = keyinfo.find('{}X509Data'.format(ns))
certelem = keydata.find('{}X509Certificate'.format(ns))
return certelem.text
def get_signature_value(signature):
return signature.find(
'{http://www.w3.org/2000/09/xmldsig#}SignatureValue').text
def parse_saml(saml):
dec_resp = decode_response(saml)
xml = get_xmldoc(dec_resp)
signature = get_signature(xml)
signed_info = get_signed_info(signature)
cert = get_cert(signature)
signature_value = get_signature_value(signature)
is_valid = verify_signature(signed_info, cert, signature_value)
更新:是否有可能我需要一些来自第三方认证提供商的更多信息?我需要私钥吗?
最佳答案
我也面临同样的问题,不得不为它开发一个模块:https://github.com/kislyuk/signxml。我选择只依赖pycrypto和pyopenssl,因为m2crypto不太流行,维护也不好,这对兼容性(例如pypy)和安全性都是一种危害。我还使用lxml进行规范化(c14n)。从signxml文档:
from signxml import xmldsig
cert = open("example.pem").read()
key = open("example.key").read()
root = ElementTree.fromstring(data)
xmldsig(root).verify()