Как разрешаются имена серверов сертификатов SSL/можно ли добавлять альтернативные имена с помощью keytool?


Они могут быть сформулированы как отдельные вопросы для ясности, но все они относятся к одному вопросу.

как разрешаются имена серверов сертификатов SSL?

Почему браузеры, похоже, используют поле CN сертификата, но механизм Java, похоже, смотрит только на "альтернативные имена субъектов"?

можно ли добавить альтернативные имена в сертификат SSL с помощью keytool? Если нет, то использует openSSL вместо хорошего вариант??

просто немного фона: мне нужно получить основной сервер для связи с несколькими серверами с помощью HTTPS. Очевидно, что мы не хотим покупать SSL-сертификаты для каждого сервера (их может быть много), поэтому я хочу использовать самозаверяющие сертификаты (я использую keytool для их создания). После того, как я добавляю сертификаты как доверенные в ОС, браузеры (IE и Chrome) с радостью принимают соединение как доверенное. Однако, даже после добавления сертификатов в Java cacerts, Java по-прежнему не будет принимать соединение как доверенное и выдает следующее исключение:

вызвано: java.безопасность.сертификат.CertificateException: нет альтернативных имен субъектов подарок в Sun.безопасность.утиль.HostnameChecker.matchIP (HostnameChecker.Ява:142) в Sun.безопасность.утиль.HostnameChecker.матч(HostnameChecker.на Java:75) на ком.солнце.чистая.протокол SSL.внутренние.протокол SSL.X509TrustManagerImpl.checkIdentity(X509T rustManagerImpl.java:264) на ком.солнце.чистая.протокол SSL.внутренние.протокол SSL.X509TrustManagerImpl.checkservertrusted методы( X509TrustManagerImpl.java: 250) на ком.солнце.чистая.протокол SSL.внутренние.протокол SSL.ClientHandshaker.serverCertificate(пре тандшейкер.java: 1185) ... Более 14

Я обнаружил, что могу заставить Java доверять сертификату, реализующему мой собственный HostNameVerifier, который я скопировал отсюда: com.солнце.ЖБИ.внутренний.безопасность.протокол https.DefaultHostnameVerifier просто для проверки (кстати, имя прошло в качестве аргумента для HostnameVerifier правильно, поэтому я думаю, что это должно было быть принято).

Я использую поле сертификата CN в качестве имени хоста (обычно IP-адрес).

может ли кто-нибудь сказать мне, если я делаю что-то неправильно и указать мне в правильном направлении?

1 60

1 ответ:

как проверка имени хоста должна быть выполнена определяется в RFC 6125, который совсем недавно и обобщает практику для всех протоколов, и заменяет RFC 2818, который был специфичен для HTTPS. (Я даже не уверен, что Java 7 использует RFC 6125, который может быть слишком недавним для этого.)

С RFC 2818 (раздел 3.1):

если расширение subjectAltName типа dNSName присутствует, это должно быть использован в качестве тождественность. В противном случае (наиболее конкретное) общее имя необходимо использовать поле в поле Тема сертификата. Несмотря на то использование общего имени-это существующая практика, она устарела и Центры сертификации рекомендуется использовать DNS-имя.

[...]

в некоторых случаях URI указывается как IP-адрес, а не a имя хоста. В этом случае iPAddress subjectAltName должен присутствовать в сертификате так и должно точно сопоставьте IP в URI.

по сути, конкретная проблема у вас возникает из-за того, что вы используете IP-адреса в своем CN, а не имя хоста. Некоторые браузеры могут работать, потому что не все инструменты строго следуют этой спецификации, в частности потому, что "наиболее конкретный" в RFC 2818 не определен четко (см. обсуждение в RFC 6215).

если вы используете keytool,С Java 7, keytool есть возможность включить альтернативный предмет Имя (см. таблицу в документации для -ext): вы могли бы использовать -ext san=dns:www.example.com или -ext san=ip:10.0.0.1.

EDIT:

вы можете запросить SAN в OpenSSL, изменив openssl.cnf (он выберет копию в текущем каталоге, если вы не хотите редактировать глобальную конфигурацию, насколько я помню, или вы можете выбрать явное местоположение с помощью OPENSSL_CONF переменные среды).

установите следующие параметры (найдите соответствующие разделы внутри скобки сначала):

[req]
req_extensions = v3_req

[ v3_req ]
subjectAltName=IP:10.0.0.1
# or subjectAltName=DNS:www.example.com

есть также хороший трюк, чтобы использовать переменную среды для этого (а не фиксировать ее в файле конфигурации) здесь:http://www.crsr.net/Notes/SSL.html