使用Python Flask验证SAML签名

时间:2016-07-19 01:34:35

标签: python digital-signature saml m2crypto okta

我有一个Python Flask网络应用程序。我正在将OKTA SAML集成到此应用程序中进行身份验证。

我已按照以下步骤操作:

然而,验证总是失败。当我运行verify_signature()时,它总是会给我0

我的代码:

def verify_signature(signed_info, cert, signature):
    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='sha256')
    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.fromstring(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 = str(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

# Main Function
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)
print is_valid # ALWAYS PRINTS 0.

2 个答案:

答案 0 :(得分:1)

除非您牢牢掌握XML解析,XML Signature规范,加密散列和公钥加密,否则我强烈敦促您不要编写自己的SAML验证例程。

对于正确解析SAML有多困难的一些具体例子,我建议阅读" On Breaking SAML: Be Whoever You Want to Be"这是一篇优秀的学术论文,涵盖了可以绕过SAML验证的各种方法。此外,最近一个大型公司获得SAML验证错误的例子是" The road to hell is paved with SAML Assertions"。

在高层次上,我建议努力学习已建立的SAML验证库(如PySAML2)的特性,这样您就可以从其他人为避免SAML中的常见安全性错误所做的工作中受益。对于PySAML2,saml2/sigver.py文件中的validate_signature方法是一个很好的起点。

如果您仍然有兴趣在我的所有警告后进行自己的SAML验证,那么我建议您查看signxml库,或直接使用xmlsec1二进制文件。

答案 1 :(得分:0)

我想引导您完成我们对Python应用的说明:http://developer.okta.com/docs/guides/pysaml2 另外,请按照PySAML2的示例: https://github.com/jpf/okta-pysaml2-example 您是否有处理注销请求的方法?