нужна помощь в понимании цепочек сертификатов - PullRequest
11 голосов
/ 19 октября 2011

В данный момент я пишу библиотеку Java для доступа к REST API pointhq.com.

При разработке клиента Android я понял, что сертификат SSL не принимается по умолчанию, поэтому я написал собственный TrustManager и добавил сертификат pointhq.com, как описано в этом посте: Доверие всем сертификатам с использованием HttpClient через HTTPS

Используя этот Trustmanager и мой импортированный файл bks, я получаю следующую ошибку при попытке подключения: 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.

Так, что я сделал не так? Я импортировал сертификаты pointhq.com, rapidssl.com, geotrust.com. Но ничего не изменилось. Есть ли какая-то сортировка сертификатов, о которой я должен знать? Мне не хватает корневого сертификата?

РЕДАКТИРОВАТЬ: Вот список импортированных сертификатов:

Тип: BKS Провайдер: BC Записи: 3

Псевдоним входа: geotrust global ca Дата создания: 19.10.2011 15:44:35 MESZ Тип: доверенный сертификат Сертификаты: 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

Псевдоним ввода: pointhq.com (rapidssl ca) Дата создания: 29.09.2011 18:55:12 MESZ Тип: доверенный сертификат Сертификаты: 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

Псевдоним ввода: rapidssl ca (geotrust global ca) Дата создания: 29.09.2011 18:54:49 MESZ Тип: доверенный сертификат Сертификаты: 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

Я сейчас написал приложение SSL Test. Результаты сбивают с толку. Как вы можете видеть на прикрепленных скриншотах, иногда соединение ssl принимается, а иногда нет! Даже если это тот же сайт, к которому я подключаюсь.

https://ssltest12.bbtest.net/ является демонстрационным сайтом для сертификата RapidSSL I, что использовать. Как вы можете видеть на скриншоте Android 2.1, первое соединение не принимается, но вторая попытка работает отлично, в то время как последнее снова не работает. Как это может произойти?

Кстати: начиная с Android 2.3.3, сертификат RapidSSL принимается без какого-либо специального кода!

Scrennshots:

1 Ответ

6 голосов
/ 02 апреля 2012

Да, порядок сертификатов в цепочке имеет значение.По сути, вы хотите, чтобы сертификаты передавались от вашего к CA.Браузеры делают это за вас, а Java - нет.У меня возникла проблема с неупорядоченными сертификатами в цепочке, и я закончил тем, что написал простую реализацию X509TrustManager с:

    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);

    }
}

Обратите внимание на последовательность заказа while.

...