我正在尝试对使用OpenSAML从身份提供商处获得的SAML2响应进行签名验证。我试图从本地文件系统读取响应。
这是我的代码:
DefaultBootstrap.bootstrap();
BasicParserPool ppMgr = new BasicParserPool();
ppMgr.setNamespaceAware(true);
//Read file from the filesystem
File file1=new File("F:/Softwares/Assertion.xml");
InputStream inCommonSaml=new FileInputStream(file1);
// Parse file
Document inCommonSamlDoc = ppMgr.parse(inCommonSaml);
Element metadataRoot = inCommonSamlDoc.getDocumentElement();
UnmarshallerFactory unmarshallerFactory=configuration.getUnmarshallerFactory();
Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(metadataRoot);
Response inCommonSamlRes = (Response) unmarshaller.unmarshall(metadataRoot);
//Get certificate
SignatureValidator signatureValidator = new SignatureValidator(cert);
Signature signature=inCommonSamlRes.getSignature();
signatureValidator.validate(signature);
try {
BasicX509Credential credential = new BasicX509Credential();
File file2=new File("F:/Softwares/publicKey.crt");
InputStream samlCertificate=new FileInputStream(file2);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
//
@SuppressWarnings("deprecation")
java.security.cert.X509Certificate certificate = (java.security.cert.X509Certificate) certificateFactory.generateCertificate(samlCertificate);
//
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec((certificate).getPublicKey().getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey key = keyFactory.generatePublic(publicKeySpec);
credential.setPublicKey(key);
Object obj = (credential).getPublicKey();
if (obj instanceof RSAPublicKey) {
BigInteger modulus = ((RSAPublicKey) obj).getModulus();
BigInteger exponent = ((RSAPublicKey) obj).getPublicExponent();
System.out.println("modulus");
System.out.println (org.apache.commons.codec.binary.Base64.encodeBase64String(modulus.toByteArray()));
System.out.println("public exponent:");
System.out.println (org.apache.commons.codec.binary.Base64.encodeBase64String(exponent.toByteArray()));
}
// System.out.println ("public key is: //n//r"+ credential.getPublicKey());
return credential;
} catch (Exception e) {
throw e; //Throws a 'Signature did not validate against the credential's key' exception
}
注意:我也使用相同的证书(publicKey.crt)来签署断言 我收到以下错误: 签名加密验证不成功。
请告诉我哪里错了?错误是什么意思?它是说公钥和私钥是一样的吗?
谢谢, aswini J
答案 0 :(得分:0)
我认为您需要从IdP(身份提供商)服务器获取.jks文件。此外,当您从IDP获取POST的SAMLResponse时,此SAMLResponse应包含Signature(FYI - 将是一个编码字符串,您可以使用Open SAML库进行解码和读取,可在Maven Central Repository上获得)。 获得签名后,您可以使用OpenSAML
进行验证sigValidator.validate(response.getSignature());
如果一切正常,此方法将为您提供meesage。参考消息"签名使用提供的凭证中的密钥进行验证"
您可以点击以下链接:http://sureshatt.blogspot.in/2012/11/how-to-read-saml-20-response-with.html获取签名和
(IMP):您的IDP(身份提供商)应该发送(可能是通过HTTP POST),以便您可以从中获取NameID,即ClinetId
答案 1 :(得分:0)
此答案适用于收到此错误并在Google上搜索的传入人。
就我而言,我面临同样的错误:“错误:签名加密验证不成功”,案例略有不同。我将 SimpleSamlPHP 验证为 SP ,将 CAS 验证为 IDP 。
问题在于我的 SP 使用一个(自签名)证书对SPP进行验证,另一个证书用于Apache中的SP以允许SSL(这样我可以使用https)< / p>
使用两个单独的证书可能适用于许多进程,如登录和元数据验证,但是如果有注销这样的错误,就会发生上述错误。
解决方案是两个进程只使用一个证书,我的错误消失了。