我签署了XML,我通过以下代码验证
<ThreeDSecure>
<Message id="pareq_1514467844949">
<PARes id="WkTyB5IWvmwx1d846aVCTg">
<version>1.0.2</version>
<Merchant>
<acqBIN>454589</acqBIN>
<merID>P2P_WEB</merID>
</Merchant>
<Purchase>
<xid>MTUxNDQ2Nzg0NDk0OTAwMDAwMDA=</xid>
<date>20171228 16:30:44</date>
<purchAmount>1000</purchAmount>
<currency>810</currency>
<exponent>2</exponent>
</Purchase>
<pan>0000000000002635</pan>
<TX>
<time>20171228 13:31:04</time>
<status>Y</status>
<cavv>AAABB3YieEkDliVhUyJ4AAAAAAA=</cavv>
<eci>05</eci>
<cavvAlgorithm>2</cavvAlgorithm>
</TX>
</PARes>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod>
<Reference URI="#WkTyB5IWvmwx1d846aVCTg">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
<DigestValue>vjiyJgkYUPKeX79NBcvZNcZuH7g=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>LcITisdhnjQSLaQnL/VPg8EWCFbmfDhDpOLo8xGntbcCiubVCi6o+luhu38JA2Vo8G8fcSTH/2GvkFm1NTeOyzHDlqV5LCKXY+gNX8U+Toot+TYux9QQ0Ro1D5T2152Sn86SARNyOsnOxSzf7I0+/sAfaCD2kjbNyZb5YWPNvezM9iMaJVgLhZmAZCUmnb9vBP9HXAgEm5E2pSUhdiaXSLcp3hnccbNsqQUlRejOCOixXPbIExiwguaqYg4XbGx9mnHTin6shHPVqfZ2MvTMjTEkf+S5+yMiXVa1Sjzt7q2iJcDoDAKu5RYrC/zxjZqlNxWzeMqHbeFARUA3eRaQwQ==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIFOjCCBCKgAwIBAgIQd/2aPtSfIJO8W8DTHLSRPTANBgkqhkiG9w0BAQsFADBxMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xIjAgBgNVBAMTGVZpc2EgZUNvbW1lcmNlIElzc3VpbmcgQ0EwHhcNMTYxMTAyMjAwNjIxWhcNMTgxMTAyMjAwNjIxWjBsMQ8wDQYDVQQHEwZNb3Njb3cxDzANBgNVBAgTBlJ1c3NpYTELMAkGA1UEBhMCUlUxEDAOBgNVBAoTB0JJTkJBTksxEDAOBgNVBAsTB0JJTkJBTksxFzAVBgNVBAMTDlZlcmlmaWVkQnlWaXNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7eXO8hN2IQh26zBkJ7zh4ckR3kTLK613smqmVggNJ4GweXHuMEhhlc+cYcOAO6pniMlzaWxDyexXg+2JSVrbvW15bsHYbYHaot2ZndOvvELL79SNe3pPv3vMuZLeXwJ4KNsV26/PIbK2Mc+Eo9FlkQbl5E1kY07N/5g4K/+/o7WjcsVizdp467AJebGduO9xYyQbG17SzXUjzwICBzBPRsgsan3PJuYctJjHbTIwoNnNr82ZYVkeRE7yOo/QroB5sDeNnVTgSOUYaM4qHbbGVUy3Zc+qyq4p6Km+EcKCRjxGpShPRZPKKvyHlUOgwlMk/oX7BQ4sDJ3EmnH1uaLVCQIDANfJo4IB0TCCAc0wZQYIKwYBBQUHAQEEWTBXMCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC52aXNhLmNvbS9vY3NwMC4GCCsGAQUFBzAChiJodHRwOi8vZW5yb2xsLnZpc2FjYS5jb20vZWNvbW0uY2VyMB8GA1UdIwQYMBaAFN/DKlUuL0I6ekCdkqD3R3nXj4eKMAwGA1UdEwEB/wQCMAAwgcoGA1UdHwSBwjCBvzAooCagJIYiaHR0cDovL0Vucm9sbC52aXNhY2EuY29tL2VDb21tLmNybDCBkqCBj6CBjIaBiWxkYXA6Ly9FbnJvbGwudmlzYWNhLmNvbTozODkvY249VmlzYSBlQ29tbWVyY2UgSXNzdWluZyBDQSxjPVVTLG91PVZpc2EgSW50ZXJuYXRpb25hbCBTZXJ2aWNlIEFzc29jaWF0aW9uLG89VklTQT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0MA4GA1UdDwEB/wQEAwIHgDAdBgNVHQ4EFgQUm3YBohISsKwqb9YvSJ3ponmhTyowOQYDVR0gBDIwMDAuBgVngQMBATAlMCMGCCsGAQUFBwIBFhdodHRwOi8vd3d3LnZpc2EuY29tL3BraTANBgkqhkiG9w0BAQsFAAOCAQEABJhweDeYad6xAwRkYEbh1aFNzjKA0U/pHcFHUx1EQlcMcdi0G3sl6TrVh9GMi5DIe4uuoH8d3uBPS/AOGtvo/9Qnx7O423bAKkD56G5xJZYGrgTeh97SbIRdsiltnECehCGfUdtyiAirWzs7kcWgmMFDaGjk/GPra7dAkfCTuH68zwv79ae/z855/xoqbyeXu/B1oJ0ccd1YFNa+HwKcgkjOPFWrL1MEMRFK986Ic7ipnoooKBe1PyQCUc0hIUZ52tKy2pbNp/JoxpspNO+XJvCe6fa5lxAht70/V2xIh1xXOv77dkgnWfMP3aNPoj+HhMpBudNcxlCqlnoG5rd2WQ==</X509Certificate><X509Certificate>MIIFGzCCBAOgAwIBAgIRANLvVGMwl5OFbHV13pkMjIUwDQYJKoZIhvcNAQEFBQAwazELMAkGA1UEBhMCVVMxDTALBgNVBAoTBFZJU0ExLzAtBgNVBAsTJlZpc2EgSW50ZXJuYXRpb25hbCBTZXJ2aWNlIEFzc29jaWF0aW9uMRwwGgYDVQQDExNWaXNhIGVDb21tZXJjZSBSb290MB4XDTExMDMyMTE3MzMzN1oXDTIyMDYyMjIzMTYzN1owcTELMAkGA1UEBhMCVVMxDTALBgNVBAoTBFZJU0ExLzAtBgNVBAsTJlZpc2EgSW50ZXJuYXRpb25hbCBTZXJ2aWNlIEFzc29jaWF0aW9uMSIwIAYDVQQDExlWaXNhIGVDb21tZXJjZSBJc3N1aW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArkmC50Q+GkmQyZ29kKxp1d+nJ43JwXhGZ7aFF1PiM5SlCESQ22qV/lBA3wHYYP8i17/GQQYNBiF3u4r6juXIHFwjwvKyFMF6kmBYXvcQa8Pd75FC1n3ffIrhEj+ldbmxidzK0hPfYyXEZqDpHhkunmvD7qz1BEWKE7NUYVFREfopViflKiVZcYrHi7CJAeBNY7dygvmIMnHUeH4NtDS5qf/n9DQQffVyn5hJWi5PeB87nTlty8zdji2tj7nA2+Y3PLKRJU3y1IbchqGlnXqxaaKfkTLNsiZq9PTwKaryH+um3tXf5u4mulzRGOWh2U+Uk4LntmMFCb/LqJkWnUVe+wIDAQABo4IBsjCCAa4wHwYDVR0jBBgwFoAUFTiDDz8sP3AzHs1G/geMIODXw7cwEgYDVR0TAQH/BAgwBgEB/wIBADA5BgNVHSAEMjAwMC4GBWeBAwEBMCUwIwYIKwYBBQUHAgEWF2h0dHA6Ly93d3cudmlzYS5jb20vcGtpMIIBCwYDVR0fBIIBAjCB/zA2oDSgMoYwaHR0cDovL0Vucm9sbC52aXNhY2EuY29tL1Zpc2FDQWVDb21tZXJjZVJvb3QuY3JsMDygOqA4hjZodHRwOi8vd3d3LmludGwudmlzYWNhLmNvbS9jcmwvVmlzYUNBZUNvbW1lcmNlUm9vdC5jcmwwgYaggYOggYCGfmxkYXA6Ly9FbnJvbGwudmlzYWNhLmNvbTozODkvY249VmlzYSBlQ29tbWVyY2UgUm9vdCxvPVZJU0Esb3U9VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFN/DKlUuL0I6ekCdkqD3R3nXj4eKMA0GCSqGSIb3DQEBBQUAA4IBAQAl3lDasc/q3yjspKOIgONgNnAgX3JCOqFtapWU1LJHLVyV47RhgKV7/Kj2m3vYFsyp+Uwis4aQM6sA7w3CHoJoWDg6OjhWUuhoIbMNR8BnNmN+ic3+IG9rUm2eFNz8r/QoUDFRPQGFD/NtIqvx9m+hk+8p7HS8aLaOPxNjPzmes96qIjBD+n0xJSu+F+3gWx7b5B6qTHq3jsA5kji2K5pSLN+v/bJriS5GNkTLzLSSWLNaKQ8fPmhlJnO4Z1x9zuZTKsepiNDA6TrpUaYDyzR15aWiO+rdElFEjl8BhDtMVK+3ncfcFV7BVZ75CGp/gzopwUtT8ORhW3+o7jrfu7zK</X509Certificate><X509Certificate>MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8 bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt398znM/jra6O1I7mT1GvFpLgXPYHDw==</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Message>
</ThreeDSecure>
验证xml签名
private void getSignature (String xmlDoc){
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder builder = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xmlDoc));
Document doc = builder.parse(is);
NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
if (nl.getLength() == 0) {
throw new Exception("Cannot find Signature element");
}
// Overwrite ID
NodeList elList = doc.getElementsByTagName("PARes");
if (elList != null && elList.getLength() > 0 && ((Element)elList.item(0)).hasAttribute("id")) {
Attr id = ((Element)elList.item(0)).getAttributeNode("id");
((Element)elList.item(0)).setIdAttributeNode(id, true);
}
DOMValidateContext valContext = new DOMValidateContext(new X509KeySelector(), nl.item(0));
XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM");
// Unmarshal the XMLSignature.
XMLSignature signature = factory.unmarshalXMLSignature(valContext);
// Validate the XMLSignature.
boolean coreValidity = signature.validate(valContext);
log.error("Validated :" + (coreValidity?"True":"False"));
} catch (Exception e){
log.error("Exception : "+e.getMessage());
}
}
public class X509KeySelector extends KeySelector {
public KeySelectorResult select(KeyInfo keyInfo,
KeySelector.Purpose purpose,
AlgorithmMethod method,
XMLCryptoContext context)
throws KeySelectorException {
Iterator ki = keyInfo.getContent().iterator();
while (ki.hasNext()) {
XMLStructure info = (XMLStructure) ki.next();
if (!(info instanceof X509Data))
continue;
X509Data x509Data = (X509Data) info;
Iterator xi = x509Data.getContent().iterator();
while (xi.hasNext()) {
Object o = xi.next();
if (!(o instanceof X509Certificate))
continue;
final PublicKey key = ((X509Certificate)o).getPublicKey();
// Make sure the algorithm is compatible
// with the method.
if (algEquals(method.getAlgorithm(), key.getAlgorithm())) {
return new KeySelectorResult() {
public Key getKey() {
return key;
}
};
}
}
}
throw new KeySelectorException("No key found!");
}
private static boolean algEquals(String algURI, String algName) {
if ((algName.equalsIgnoreCase("DSA") &&
algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) ||
(algName.equalsIgnoreCase("RSA") &&
algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1))) {
return true;
} else {
return false;
}
}
一切都很好,但是我应该检查公钥是否可信.XML是由不同的发行人签署的。我有jssecacerts包含14根CA.如何验证此公钥是否已签署此CA之一。感谢您的建议
答案 0 :(得分:0)
我已经找到了决定
private boolean checkServerTrusted(X509Certificate cert) throws KeySelectorException {
try {
final File file = new File("C:\\TMP\\jssecacerts");
InputStream inStream = new FileInputStream(file);
KeyStore keystore = KeyStore.getInstance("JKS");
//String password = "";
//keystore.load(inStream, password.toCharArray());
keystore.load(inStream, null);
X509Certificate[] certs = new X509Certificate[keystore.size()];
int i = 0;
Enumeration<String> alias = keystore.aliases();
while (alias.hasMoreElements()) {
certs[i++] = (X509Certificate) keystore.getCertificate(alias
.nextElement());
}
return validateKeyChain(cert, certs);
} catch (Exception e){
throw new KeySelectorException ("Key verify exception reason :"+ e.getMessage());
}
}
/**
* Validate keychain
* @param client is the client X509Certificate
* @param trustedCerts is Array containing all trusted X509Certificate
* @return true if validation until root certificate success, false otherwise
* @throws CertificateException
* @throws InvalidAlgorithmParameterException
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
private boolean validateKeyChain(X509Certificate client,
X509Certificate... trustedCerts) throws CertificateException,
InvalidAlgorithmParameterException, NoSuchAlgorithmException,
NoSuchProviderException {
boolean found = false;
int i = trustedCerts.length;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
TrustAnchor anchor;
Set anchors;
CertPath path;
List list;
PKIXParameters params;
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
while (!found && i > 0) {
anchor = new TrustAnchor(trustedCerts[--i], null);
anchors = Collections.singleton(anchor);
list = Arrays.asList(new Certificate[] { client });
path = cf.generateCertPath(list);
params = new PKIXParameters(anchors);
params.setRevocationEnabled(false);
if (client.getIssuerDN().equals(trustedCerts[i].getSubjectDN())) {
try {
validator.validate(path, params);
if (isSelfSigned(trustedCerts[i])) {
// found root ca
found = true;
System.out.println("validating root" + trustedCerts[i].getSubjectX500Principal().getName());
} else if (!client.equals(trustedCerts[i])) {
// find parent ca
System.out.println("validating via:" + trustedCerts[i].getSubjectX500Principal().getName());
found = validateKeyChain(trustedCerts[i], trustedCerts);
}
} catch (CertPathValidatorException e) {
// validation fail, check next certificate in the trustedCerts array
}
}
}
return found;
}
/**
*
* @param cert is X509Certificate that will be tested
* @return true if cert is self signed, false otherwise
* @throws CertificateException
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
private boolean isSelfSigned(X509Certificate cert)
throws CertificateException, NoSuchAlgorithmException,
NoSuchProviderException {
try {
PublicKey key = cert.getPublicKey();
cert.verify(key);
return true;
} catch (SignatureException sigEx) {
return false;
} catch (InvalidKeyException keyEx) {
return false;
}
}