解密SAML 2 Assertion报Data decryption key may not be null错误如何解决
SAML加密断言解密报错解决方案
待解密SAML响应
<saml:EncryptedAssertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="ED-13b5261b-6429-4fc6-9df4-00ba4c956df4" Type="http://www.w3.org/2001/04/xmlenc#Element"> <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/> <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <xenc:EncryptedKey Id="EK-cde830f3-5741-440c-a6a3-03d7fc29bec7"> <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> </xenc:EncryptionMethod> <ds:KeyInfo> <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <ds:X509Data> <ds:X509IssuerSerial> <ds:X509IssuerName>CN=Foo,OU=Ba,O=Foobaa,C=AU </ds:X509IssuerName> <ds:X509SerialNumber>161...39233</ds:X509SerialNumber> </ds:X509IssuerSerial> </ds:X509Data> </wsse:SecurityTokenReference> </ds:KeyInfo> <xenc:CipherData> <xenc:CipherValue> OrjesuK...lOQ== </xenc:CipherValue> </xenc:CipherData> </xenc:EncryptedKey> </ds:KeyInfo> <xenc:CipherData> <xenc:CipherValue> RHkpDrgRX0AJprMr...k62Q== </xenc:CipherValue> </xenc:CipherData> </xenc:EncryptedData> </saml:EncryptedAssertion>
现有解密代码
// Given here a EncryptedAssertion type populated from the above xml // Open and initialise the Keystore KeyStore ks = KeyStore.getInstance("PKCS12"); try (FileInputStream fileInputStream = new FileInputStream("keystoreUrl")) { ks.load(fileInputStream, config.getBAMKeystorePassword().toCharArray()); } PrivateKey certificate= (PrivateKey) ks.getKey("privateKeyAlias", null); // Decrypt the encrypted assertion BasicX509Credential cred = new BasicX509Credential(); cred.setPrivateKey(certificate); StaticKeyInfoCredentialResolver resolver = new StaticKeyInfoCredentialResolver(cred); Decrypter decrypter = new Decrypter(resolver, resolver, new InlineEncryptedKeyResolver()); decrypter.setRootInNewDocument(true); Assertion decrypted = decrypter.decrypt(encryptedAssertion);
报错信息
java.lang.IllegalArgumentException: Data decryption key may not be null
问题原因与修复方案
Data decryption key may not be null报错的核心原因是OpenSAML的解密器未能成功获取到可用的解密密钥,无法解密响应中内嵌的AES256加密密钥,最终没有密钥可用于解密断言本身。具体问题排查和修复步骤如下:
- 核心错误:
BasicX509Credential仅填充了私钥,缺少对应的X509证书实体。OpenSAML的密钥匹配逻辑会校验SAML响应中X509IssuerSerial信息和传入凭证的证书信息是否匹配,仅传私钥的凭证会直接被匹配逻辑过滤,导致解密器拿不到可用密钥。
修复代码如下:
// 从keystore同时取出私钥和对应证书 KeyStore ks = KeyStore.getInstance("PKCS12"); char[] storePass = config.getBAMKeystorePassword().toCharArray(); // 如果私钥有单独密码替换为对应密码即可 char[] keyPass = storePass; try (FileInputStream fileInputStream = new FileInputStream("keystoreUrl")) { ks.load(fileInputStream, storePass); } PrivateKey privateKey = (PrivateKey) ks.getKey("privateKeyAlias", keyPass); X509Certificate cert = (X509Certificate) ks.getCertificate("privateKeyAlias"); // 完整填充凭证 BasicX509Credential cred = new BasicX509Credential(); cred.setPrivateKey(privateKey); cred.setEntityCertificate(cert); // 多证书场景下建议补充填充证书链 // cred.setEntityCertificateChain(Collections.singletonList(cert)); StaticKeyInfoCredentialResolver resolver = new StaticKeyInfoCredentialResolver(cred); Decrypter decrypter = new Decrypter(null, resolver, new InlineEncryptedKeyResolver()); decrypter.setRootInNewDocument(true); Assertion decrypted = decrypter.decrypt(encryptedAssertion);
- 其他排查点:
- 确认JRE开启了无限制加密权限:AES256加密需要JCE无限制权限策略支持,JDK8u151及以上版本可通过代码
Security.setProperty("crypto.policy", "unlimited")开启,更低版本需要下载对应JDK的JCE无限制权限包替换JRE目录下的policy文件。 - 确认keystore中对应证书的颁发者名称、序列号和SAML响应中
X509IssuerName、X509SerialNumber的取值完全一致,否则匹配逻辑会过滤掉传入的凭证。 - 确认私钥密码正确:如果私钥设置了独立于keystore的密码,
ks.getKey方法的第二个参数需要传入私钥的密码,不能传null,否则取到的私钥为null。
- 确认JRE开启了无限制加密权限:AES256加密需要JCE无限制权限策略支持,JDK8u151及以上版本可通过代码
内容的提问来源于stack exchange,提问作者Michael Betterton
相关产品推荐
相关产品推荐

