Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

need help understanding certificate chains

At the moment I am writing a java library to access the REST API of pointhq.com.

While developing a Android client I realized that the SSL certificate is not accepted by default so I wrote a custom TrustManager and added the pointhq.com certificate like explained in this post: Trusting all certificates using HttpClient over HTTPS

Using this Trustmanager and my imported bks file I get the following error while trying to connect: IssuerName(CN=GeoTrust Global CA, O=GeoTrust Inc., C=US) does not match SubjectName(CN=RapidSSL CA, O="GeoTrust, Inc.", C=US) of signing certificate.

So what did I do wrong? I imported the pointhq.com, rapidssl.com, geotrust.com certificates. But nothing changed. Is there a kind of sorting of certificates I have to be aware of? Am I missing a root certificate?

EDIT: Here is the list of imported certificates:

Type: BKS Provider: BC Entries: 3

Entry Alias: geotrust global ca Creation Date: 19.10.2011 15:44:35 MESZ Type: Trusted Certificate Certificates: 1

Certificate 1 of 1
Version: 3
Subject: CN=GeoTrust Global CA, O=GeoTrust Inc., C=US
Issuer: CN=GeoTrust Global CA, O=GeoTrust Inc., C=US
Serial Number: 0002 3456
Valid From: 21.05.2002 06:00:00
Valid Until: 21.05.2022 06:00:00
Public Key: RSA (2.048 bits)
Signature Algorithm: SHA1withRSA
SHA-1 Fingerprint: DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12
MD5 Fingerprint: F7:75:AB:29:FB:51:4E:B7:77:5E:FF:05:3C:99:8E:F5

Entry Alias: pointhq.com (rapidssl ca) Creation Date: 29.09.2011 18:55:12 MESZ Type: Trusted Certificate Certificates: 1

Certificate 1 of 1
Version: 3
Subject: CN=pointhq.com, OU=Domain Control Validated - RapidSSL(R), OU=See www.rapidssl.com/resources/cps (c)11, OU=GT70151377, O=pointhq.com, C=GB, SERIALNUMBER=8Dvj7qRSYLjGZiX2tHocE2FDaqAp8RwO
Issuer: CN=RapidSSL CA, O="GeoTrust, Inc.", C=US
Serial Number: 8971
Valid From: 31.01.2011 13:20:09
Valid Until: 03.02.2013 09:15:38
Public Key: RSA (2.048 bits)
Signature Algorithm: SHA1withRSA
SHA-1 Fingerprint: BB:04:D0:3E:1A:36:02:F7:C3:8C:85:99:1D:67:2A:6B:CF:C1:BC:C5
MD5 Fingerprint: 21:9D:DF:72:E6:4A:33:47:E1:BA:D6:52:86:1E:59:B4

Entry Alias: rapidssl ca (geotrust global ca) Creation Date: 29.09.2011 18:54:49 MESZ Type: Trusted Certificate Certificates: 1

Certificate 1 of 1
Version: 3
Subject: CN=RapidSSL CA, O="GeoTrust, Inc.", C=US
Issuer: CN=GeoTrust Global CA, O=GeoTrust Inc., C=US
Serial Number: 0002 36D1
Valid From: 19.02.2010 23:45:05
Valid Until: 18.02.2020 23:45:05
Public Key: RSA (2.048 bits)
Signature Algorithm: SHA1withRSA
SHA-1 Fingerprint: C0:39:A3:26:9E:E4:B8:E8:2D:00:C5:3F:A7:97:B5:A1:9E:83:6F:47
MD5 Fingerprint: 1B:EE:28:5E:8F:F8:08:5F:79:CC:60:8B:92:99:A4:53

I now wrote an SSL Test app. The results are confusing. As you can see on the attached screenshots, sometimes the ssl connection is accepted and some times its not! Even if it is the same site that I'm connecting to.

https://ssltest12.bbtest.net/ is the demo site for the RapidSSL certificate I what to use. As you can see on the Android 2.1 Screenshot the first connection get's not accepted the but the second try works perfectly fine, while the last doesn't work again. How can that happen?

BTW: Since Android 2.3.3 the RapidSSL certificate is accepted without any custom code!

Scrennshots:

  • http://jcodehq.org/Android2.1.png
  • http://jcodehq.org/Android2.2.png
  • http://jcodehq.org/Android2.3.3.png
  • http://jcodehq.org/Android4.0.png
like image 783
Matthias B Avatar asked Oct 19 '11 13:10

Matthias B


1 Answers

Yes, the order of certificates in chain matter. Basically you want certificates to be odered from yours to CA. Browsers do it for you, but Java does not. I had the issue with unordered certificates in chain and I ended up writing a simple implementation of X509TrustManager with:

    public void checkServerTrusted(X509Certificate[] certificates,String authType) throws CertificateException {
    if ((certificates != null) && LOG.isDebugEnabled()) {
        LOG.debug("Server certificate chain:");
        for (int i = 0; i < certificates.length; i++) {
            LOG.debug("X509Certificate[" + i + "]=" + certificates[i]);
        }
    }
    if ((certificates != null) && (certificates.length == 1)) {
        certificates[0].checkValidity();
    } else {
        List<X509Certificate> certs = new ArrayList<X509Certificate>();
        certs.addAll(Arrays.asList(certificates));
        X509Certificate certChain = certs.get(0);
        certs.remove(certChain);
        LinkedList<X509Certificate> chainList= new LinkedList<X509Certificate>();
        chainList.add(certChain);
        Principal certIssuer = certChain.getIssuerDN();
        Principal certSubject = certChain.getSubjectDN();
        while(!certs.isEmpty()){
            List<X509Certificate> tempcerts = new ArrayList<X509Certificate>();
            tempcerts.addAll(certs);
            for (X509Certificate cert : tempcerts){
                if(cert.getIssuerDN().equals(certSubject)){
                    chainList.addFirst(cert);
                    certSubject = cert.getSubjectDN();
                    certs.remove(cert);
                    continue;
                }

                if(cert.getSubjectDN().equals(certIssuer)){
                    chainList.addLast(cert);
                    certIssuer = cert.getIssuerDN();
                    certs.remove(cert);
                    continue;
                }
            }
        }
    standardTrustManager.checkServerTrusted(chainList.toArray(new X509Certificate[]{}),authType);

    }
}

Notice the ordering "while" cycle.

like image 186
Oleksiy Avatar answered Sep 28 '22 18:09

Oleksiy