java - 验证 SAML 响应的签名

标签 java digital-signature saml public-key-encryption shibboleth

我正在尝试遵循以下规范来验证 SAML 响应的签名:https://www.w3.org/TR/xmldsig-core/#sec-PKCS1

这是我的工作流程:我收到 SAML 响应。我摆脱了签名信封,将其规范化,检查摘要,然后检查签名。我能够成功计算转换后的 SAML 响应的 SHA1 摘要并验证它。然而,RSA-SHA1 签名检查仍然让我望而却步。

SAML 响应包括签名方法算法:http://www.w3.org/2000/09/xmldsig#rsa-sha1

我有这个方法来检查签名:

public static boolean verifySignature(String signatureType, PublicKey publicKey, byte[] contentBytes, byte[] sigBytes) {
    try {
        Signature sig = Signature.getInstance(signatureType);
        sig.initVerify(publicKey);
        sig.update(contentBytes);
        return sig.verify(sigBytes);
    } catch (Exception e) {
        Logger.log(e);
        return false;
    }
}

我做了这样的事情来调用它:

String publicKeyStr =  "MIIDNDCCAhwCCQCEk14scLMSGjANBgkqhkiG9w0BAQsFADBcMR8wHQYDVQQDDBZhdXRoLnJldHJvZmljaWVuY3kuY29tMQ4wDAYDVQQKDAVSZXRybzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk1BMQ8wDQYDVQQHDAZCb3N0b24wHhcNMTYwMzAyMTU1NTQ4WhcNMTcwMzAyMTU1NTQ4WjBcMR8wHQYDVQQDDBZhdXRoLnJldHJvZmljaWVuY3kuY29tMQ4wDAYDVQQKDAVSZXRybzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk1BMQ8wDQYDVQQHDAZCb3N0b24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDwUlZ+qOA61kYh0MGHKTe4JtSL1qJVT/8/i6sWFqbAiGdV33pxSm8iBpqLNPG+fr8aZKugik8mN3y0kZEDwD+EATXGUpqT1v1R6Wr4rRUwsC0wl6d6EiWfdSsu66T11hdrugXF/psjyy4mmvIMMU4RlSaZmT2+gpe57IWPO522Y1HqbuvSvKJgjdyrlhIKLmw7HvZ1ZrQ1j01Hd3/rdK41+zWpSCLuSellHowiDmOzNnyFpTw+SZA0GKE+cm3BOTj/cM36GR2XJd0kIRqj1qqu29cGMlBjQ3cMleG6HoHR9oPNFwYtW1fDTHG6MnxRXYCfZiPeBdX3eBDSuz7GQAv5AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAEuQEPhpWdAGg46PSbE20bNt4YH+PjiIzPaXzN5UmpJjyl2kbR18HYXZHEtAXc+ItrYnK+oe+6FhwJ9aiwlrf1/p+U61iyvA9/HWzyW4vflaLWRQ8FxNhAJiVu57IQObjZ13EQfu1O8RK4wzNUVJhOz+pp9toqTHn8wmUPApzqMIl0KpDCPy1TNrwItaiy/gzWQngBMgIcrDeycR8wK2EH6txT8BzI+aqdIc3gBXsn/kS90lelbvYreXqF7VHoMs8fVEPN5fTRjqT9oZb60b1DxcniiTEknZtqprYuMpgEzpOHrzmlbCoNU2yBHuNTQWBz3lG+XtSMtgh16v5Vm48ag=";
PublicKey publicKey = Security.getPublicKey(publicKeyStr); // uses Certificate class
String sig = "QfAcRJM2P65JucyBpqn6j48/zd1oSLPBJ0lYI1grH5/xenwBEh0D4Eh0S1J3535OUmldpW7D+G7DW6eAT5N8TdoqUvMXuIAUpFHHDR45KZykPXJPUtli+z2rwlCCHypZWnniT/wrcQYdpp1zzNJBBtKdkaqQg0NMktPSQ/0ti+ruMI3qwfTaL9kDQ3Zyi/a2J3RCAPA0RfviLnDLlid0PthiV1NEbs0AvnguDi57fWXAILk0L1Cx20sliQckxlFQ9u4OaHeMscXdjh3SfESkM9m0Y9PppisZWTrCYzGmvDwsZTCBPD3f/ZFIit+Smgh2fi1u8/gZq0yizPyacR3Y/A==";
String newXMLToOperateOn = "<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="_420cc1a25a3890bd5df1f4c04bd7e986" ...";

boolean sign = Security.verifySignature("SHA1withRSA", pk, newXMLToOperateOn.getBytes(), Util.base64DecodeAsBytes(sig));
// SIGN IS FALSE!!!!

newXMLToOperateOn 是 SAMLResponse 的正确规范化字符串 XML。这就是我用来生成正确的 SHA1 摘要的方法。 Security.verify() 工作正常,因为我使用它进行 OpenID SSO 检查并且工作正常。

我还尝试用要检查的数据而不是整个 XML 替换为 SHA1 摘要的字节,但也没有用。 验证(算法,pk,sha1Digest.getBytes(),sig.getBytes()

有人可以告诉我在检查签名时我是否做错了什么吗?上面链接的规范告诉我签名方法是这样做的:

   CRYPT (PAD (ASN.1 (OID, DIGEST (data))))

当我验证签名时,这对我没有太大帮助。我无法重新创建签名,因为我找不到他们在示例中使用的私钥。

感谢您的帮助。

最佳答案

您只需要验证 XML 的“SignedInfo”部分

关于java - 验证 SAML 响应的签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36204141/

相关文章:

asp.net - 配置 IIS 以进行 SAML 身份验证

java - 支持 ETags、If-Modified-Since 的 Android 图像加载器库

java - 在两个形状的交点之间绘制线

c# - 创建 rsa-sha512 签名时算法无效

python - 从哪里获取 SSLSocket 的签名算法名称?

single-sign-on - SSO - SAML,成功登录后将用户重定向到指定的登录页面

java - 对两个整数的 ArrayList 进行排序

当我在命令中指定目录时,Java 类路径问题

Android jar 使用有效的 keystore 未签名,需要 SHA1 证书吗?

用于创建加密 SAML 断言的 Java 代码