如何检查公共X509Certificate是否可信

时间:2018-01-05 11:02:23

标签: x509certificate xml-dsig

我签署了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之一。感谢您的建议

1 个答案:

答案 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;
        }
    }