Поведение Java trustmanager по истекшим сертификатам

Является ли реализация java TrustManager игнорировать, если срок действия сертификата истек?
Я попробовал следующее:
 - Используя keytool и параметр -startdate "1970/01/01 00:00:00", я создал хранилище ключей P12 с сертификатом с истекшим сроком действия.
- Я экспортировал сертификат:

Keystore type: PKCS12
Keystore provider: SunJSSE

Your keystore contains 1 entry

Alias name: fake
Creation date: 5 ╠ά± 2011
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Malicious, OU=Mal, O=Mal, L=Fake, ST=GR, C=GR
Issuer: CN=Malicious, OU=Mal, O=Mal, L=Fake, ST=GR, C=GR
Serial number: -1c20
Valid from: Thu Jan 01 00:00:00 EET 1970 until: Fri Jan 02 00:00:00 EET 1970
Certificate fingerprints:
         MD5:  A9:BE:3A:3D:45:24:1B:4F:3C:9B:2E:02:E3:57:86:11
         SHA1: 21:9D:E1:04:09:CF:10:58:73:C4:62:3C:46:4C:76:A3:81:56:88:4D
         Signature algorithm name: SHA1withRSA
         Version: 3


*******************************************

Я использовал этот сертификат в качестве сертификата сервера для Tomcat.
Затем, используя apache httpClient, я подключился к tomcat, но сначала я добавил сертификат с истекшим сроком в клиентское хранилище доверия (используя TrustManager

TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

и загрузить сертификат с истекшим сроком действия).
Я ожидал, что соединение потерпит неудачу.
Вместо этого соединение будет успешным.
Использование System.setProperty("javax.net.debug", "ssl");
Я вижу:

***
Found trusted certificate:
[
[
  Version: V3
  Subject: CN=Malicious, OU=Mal, O=Mal, L=Fake, ST=GR, C=GR
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

  Key:  Sun RSA public key, 1024 bits
  modulus: 10350555024148635338735220482157687267055139906998169922552357357346372886164908067983097037540922519808845662295379579697361784480052371935565129553860304254832565723373586277732296157572040989796830623403187557540749531267846797324326299709274902019299
  public exponent: 65537
  Validity: [From: Thu Jan 01 00:00:00 EET 1970,
               To: Fri Jan 02 00:00:00 EET 1970]
  Issuer: CN=Malicious, OU=Mal, O=Mal, L=Fake, ST=GR, C=GR
  SerialNumber: [   -1c20]

]

Я вижу, что в рукопожатии TLS сертификат с истекшим сроком отправляется соединителем Tomcat.
Но клиент (т.е. TrustManager) не отклоняет соединение.
Это поведение по умолчанию? Я полагаю, чтобы настроить доверительный управляющий как-то проверить на истечение срока?

UPDATE:
Я обнаружил, что фактическим TrustManager является X509TrustManagerImpl. Здесь X509TrustManagerImpl говорит, что этот класс имеет минимальную логику. Может быть, я использую неверный TrustManager?

UPDATE2: Из javadoc X509TrustManager неясно, проверяет ли он срок действия сертификата

void checkServerTrusted(X509Certificate[] chain,String authType)
                                throws CertificateException  

Учитывая частичное или полное цепочку сертификатов, предоставленную создать путь сертификата к доверенный корень и возврат, если он может быть проверено и доверено серверу Идентификация SSL на основе тип аутентификации. Аутентификация type - это алгоритм обмена ключами часть наборов шифров представленный как строка, например "RSA", "DHE_DSS". Примечание: для некоторых экспортируемые шифровальные пакеты, ключ алгоритм обмена определяется на время выполнения во время рукопожатия. Для например, для TLS_RSA_EXPORT_WITH_RC4_40_MD5, authType должен быть RSA_EXPORT, когда эфемерный ключ RSA используется для ключа обмена и RSA, когда ключ от используется сертификат сервера. Проверка чувствительна к регистру.

Спасибо

Ответ 1

Я не пробовал ваш пример, но теперь мне регулярно приходится регенерировать сертификаты сервера (для нашего сервера разработки), так как их сертификаты имеют довольно короткое время действия.

В нашем случае клиент не имеет самих сертификатов сервера в доверенности, а только сертификат нашего ЦС (с большей достоверностью), а когда клиент пытается подключиться к серверу, обе стороны получают SSLException (который могут быть завернуты в другое исключение в вашем случае).

Я предполагаю, что менеджер доверия предполагает нечто вроде "если вы дадите мне истекшие сертификаты, чтобы доверять, я сделаю это". Вместо этого попробуйте наш подход (он также позволяет вам обновлять клиент каждый раз, когда истекает срок действия сертификата сервера).

Ответ 2

У меня только что была аналогичная проблема, когда я переопределял checkServerTrusted.

Оказывается, что если вам нужно проверить истечение срока действия, вы можете вызвать X509Certificate.checkValidity(), и он будет генерировать исключение CertificateExpiredException или CertificateNotYetValidException. Оба они расширяют исключение CertificateException, поэтому их можно с радостью отбросить с помощью checkServerTrusted.

Чтобы решить вашу проблему, вы можете реализовать новый X509TrustManager, который создает ваш исходный экземпляр в своем конструкторе, реализует все методы как вызовы исходного экземпляра и добавляет вызов checkValidity для каждого сертификата в certs[] внутри checkServerTrusted.

Ответ 3

Я считаю, что IBM JSSE проверяет срок действия, пока Sun не делает.