1

I am referring Validate X.509 certificate against CA in Java this post.

My implementation of checkServerTrusted look like:

@Override
            public void checkServerTrusted(X509Certificate[] certs, String authType) throws  CertificateException{
                 InputStream inStream;
                try {
                        inStream = new FileInputStream("E:\\Desktop\\cert\\domain.crt");
                        CertificateFactory cf = CertificateFactory.getInstance("X.509");
                        X509Certificate Mycert = (X509Certificate)cf.generateCertificate(inStream);
                        inStream.close();      

                        if (certs == null || certs.length == 0 || authType == null
                                || authType.length() == 0) {
                            throw new IllegalArgumentException("null or zero-length parameter");
                        }

                         for (X509Certificate cert : certs) {
                             cert.verify(Mycert.getPublicKey());
                         }


                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    throw new CertificateException("error in validating certificate" , e);
                }

            }

file domain.crt is exported from browser after opening website. certificate path look like enter image description here.

If i open this file in notepad only one BEGIN CERTIFICATE and END CERTIFICATE is their so its not chain of certificate.

If I debug code then, in for loop @ LOC cert.verify(Mycert.getPublicKey()); at the very first cert[0] certificate I got exception as java.security.SignatureException: Signature does not match.

Where I am doing wrong?

Community
  • 1
  • 1
Amogh
  • 4,453
  • 11
  • 45
  • 106

1 Answers1

0

It doesn't make sense to try to verify all the certificates in the chain against a single public key. Most of them won't have been signed by it, so the procedure is bound to fail, and throw an exception to the caller.

You need to review what it is you're supposed to do in this method. See the Javadoc. You're trying to establish a certificate path from this chain to a trusted root certificate.

In this case the trusted root certificate is presumably the one you loaded from the file.

What you should be doing therefore is:

  1. Look for that certificate in the chain, and if not found
  2. Verify the last certificate in the chain against this public key, as that is the topmost signer, and that's the only one you need to trust. The rest of them are trusted by their respective sucessors in the chain, and none of their successors are this trusted root certificate, by (1).
  3. If the certificate is found in the chain, verify the previous certificate. i.e. the one signed by this certificate, with this public key.

It isn't clear to me whether you need to also verify each certificate in the chain, except the last, with the next one's public key, but it can't hurt.

EDIT You should also implement the suggestion in this answer.

Community
  • 1
  • 1
user207421
  • 305,947
  • 44
  • 307
  • 483
  • I have seen that I got only 2 certificates in `X509Certificate[] certs` so as per 2nd point you want to say it's okay to check `certs[1].verify(Mycert.getPublicKey())`, am I getting correctly? – Amogh Jan 29 '15 at 06:47
  • Correct. However I'm wondering whether it's safe to assume that the certificates are presented in the order stated. You might have to reorder them. – user207421 Jan 29 '15 at 07:14
  • I tried with `certs[1].verify(Mycert.getPublicKey())` but that is also throwing `java.security.SignatureException: Signature does not match.`. Means certs[0] and certs[1] both throwing the exception. – Amogh Jan 29 '15 at 07:17
  • So neither of the certificates was signed with your domain certificate. Do you have any reason to believe otherwise? – user207421 Jan 29 '15 at 07:19
  • The file `domain.crt` is exported from mozila browser as image attached in question certificate path is up to my domain i.e url.esb.com in this case i am getting exception as said in previous comment. Now i tried with exporting certificate up to `COMODO RSA Domain Validation Secure Server CA` certificate path (just prior to domain) and if i check with certs[0] it get successful but not with certs[1] – Amogh Jan 29 '15 at 07:50
  • Ok, so as soon as you can find a certificate in the chain that verifies with your public key you have a success. – user207421 Jan 29 '15 at 08:53
  • The javadoc for TrustManager/X509TrustManager doesn't actually say that certs[0] is guaranteed to be signed by certs[1] before checkServerTrusted(). The contract for checkServerTrusted() seems to be very fuzzy. – arnt Apr 07 '16 at 10:07