采用AES、RSA双加密的ADFS SAML Response如何用Python解密
Python实现SAML加密响应解密
加密逻辑说明
你遇到的是SAML2.0标准的混合加密机制:
- 身份提供商随机生成AES256密钥加密断言原文
- 用你提供的RSA公钥加密该AES密钥,加密后的AES密钥存储在响应的
EncryptedKey节点中 - 最终返回的响应中
EncryptedData节点存储的是AES加密后的断言内容
解密只需要按逆序操作即可,不需要额外实现底层加密算法逻辑。
前置准备
你需要提前准备好和提交给身份提供商的RSA公钥对应的**RSA私钥文件(PEM格式)。
步骤1:安装依赖包
pip install pysaml2 cryptography lxml
步骤2:解密代码实现
from saml2.config import Config from saml2.response import Response import base64 from lxml import etree # 1. 配置参数 # 你的SP实体ID,和IDP侧配置的一致 SP_ENTITY_ID = "你的服务提供商实体ID" # RSA私钥文件路径,如有密码可后续在配置中指定密码 PRIVATE_KEY_PATH = "your_private_key.pem" # 可选:SP公钥证书路径 CERT_PATH = "your_sp_cert.pem" # 2. 加载SAML响应内容 # 情况1:响应是HTTP POST参数传递的Base64编码内容 # saml_resp_raw = base64.b64decode("你的Base64编码的SAML响应字符串") # 情况2:响应是原始XML文件 with open("saml_response.xml", "rb") as f: saml_resp_raw = f.read() # 3. 初始化SAML配置 conf = Config() conf.load({ "entityid": SP_ENTITY_ID, "key_file": PRIVATE_KEY_PATH, "cert_file": CERT_PATH, # 私钥有密码的话取消下面的注释,替换为你的私钥密码 # "key_file_passwd": "你的私钥密码" }) # 4. 解析并解密响应 resp = Response(conf) resp.loads(saml_resp_raw.decode("utf-8")) # 取第一个解密后的断言 decrypted_assertion = resp.assertions[0] # 打印解密后的明文断言 print(etree.tostring(decrypted_assertion, pretty_print=True).decode("utf-8"))
常见问题排查
- 如果不想依赖pysaml2的方案无法满足你的定制需求,可以手动用cryptography库实现:先解密
EncryptedKey节点的密文得到AES密钥,再用AES-256-CBC模式解密EncryptedData节点的密文,注意处理AES的IV偏移量即可 - 解密失败优先排查私钥是否和提交给IDP的公钥配对,其次检查实体ID、加密算法配置是否和IDP侧一致
内容的提问来源于stack exchange,提问作者Kadhiresh Gajendiran
相关产品推荐
相关产品推荐

