【问题标题】:Verifying SAML signature with Python Flask使用 Python Flask 验证 SAML 签名
【发布时间】:2024-01-14 17:41:01
【问题描述】:

我有一个 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.

【问题讨论】:

  • 欢迎来到 Stack Overflow!你遇到了什么错误?
  • 我没有收到错误消息。一切都成功,但验证总是失败。即:is_valid 总是返回零。我有 sha256 签名的 SAML 响应。

标签: python digital-signature saml m2crypto okta


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    我想指导您了解我们对 Python 应用程序的说明:http://developer.okta.com/docs/guides/pysaml2 此外,请在此处按照 PySAML2 的示例进行操作: https://github.com/jpf/okta-pysaml2-example 你有处理注销请求的方法吗?

    【讨论】:

    • 我的应用程序使用 pysaml2 运行。我还尝试手动执行使用上述代码的签名验证。但它总是失败。