Тема Java MTLS и заказ эмитента
Мы обновляем соединение между собой и партнером, они требуют, чтобы мы обновились до MTLS. Я отлаживал низкоуровневую java,
javax.net.debug=all
и я вижу, что рукопожатие прошло успешно. Однако партнер сопоставляет полную строку с полями "Тема" и "Издатель" и сравнивает с полями something в своей базе данных.
Я использовал следующее,
if (cert instanceof X509Certificate) {
X509Certificate x509cert = (X509Certificate) cert;
// Get subject
Principal principal = x509cert.getSubjectDN();
String subjectDn = principal.getName();
logger.error(subjectDn);
// Get issuer
principal = x509cert.getIssuerDN();
String issuerDn = principal.getName();
logger.error(issuerDn);
}
чтобы сбросить значения, которые имеет java. Интересное примечание: openssl сообщает о них в совершенно ином порядке, чем отчеты java.
Я сейчас копался в Wireshark и вижу рукопожатие с этого уровня, однако, похоже, он переводит имена на id-at-commonName
, pkcs-9-at-emailAddress
насколько я могу судить.
Есть ли способ узнать, что на самом деле отправляется?
1 ответ
Нет протокола MTLS, но похоже, что вас интересует аутентификация клиента, также называемая взаимной аутентификацией, в TLS, который, как и аутентификация сервера, обычно использует сертификаты типа X.509 (точнее, PKIX).
Предпосылки: сертификаты X.509/PKIX идентифицируют Субъекта и Эмитента (а иногда и другие объекты / объекты в некоторых расширениях) с помощью структуры отличительного имени X.500/501, также называемой X500Name, X501Name или просто Name. Эта структура определена в ASN.1 как ПОСЛЕДОВАТЕЛЬНОСТЬ (упорядоченная) элементов RelativeDistinguishedName, каждый из которых официально представляет собой НАБОР (неупорядоченный) пар (ПОСЛЕДОВАТЕЛЬНОСТЬ) типа и значения атрибута, хотя на практике НАБОРЫ RDN почти всегда являются одиночными, так что имя фактически представляет собой последовательность типа и значения атрибута. Этот формат имени был разработан для использования в глобальной распределенной иерархической сети "каталогов", скорее как DNS. за исключением (поскольку CCITT-now-ITU-T - это организация правительственных агентств) в основном базирующихся на национальных каталогах стран, а не в функциональных или "общих", таких как .com .org .edu .gov .mil .net
, а сертификаты X.509 были разработаны как экспорт данных из этой сети каталогов, которые можно использовать в автономном режиме. На практике настоящие каталоги X.500 вообще не используются, и даже протоколы для них, такие как LDAP (Lightweight Directory Access Protocol), используются нечасто, за исключением доменов Microsoft Windows (Active Directory), но сертификатов X.509 включая используемый в них формат имени, широко используются в SSL-now-TLS, S/MIME и многих других приложениях.
Традиционная текстовая или внешняя форма DN представляет собой серию элементов attr=value, где attr обычно сокращается, например C для страны, ST для StateOrProvince, CN для CommonName и т. Д. Java использует определенную стандартизованную форму (с небольшими изменениями / улучшения) RFC 1485, 1779, 2253 и 4514, где элементы разделены запятыми и приведены в обратном порядке, то есть от последнего (самый низкий уровень) к первому (самый высокий уровень обычно корневой), аналогично DNS. Например, Java отображает тему сертификата, используемого в настоящее время www.duckduckgo.com как
CN=*.duckduckgo.com, O="Duck Duck Go, Inc.", L=Paoli, ST=Pennsylvania, C=US
OpenSSL традиционно использовал по умолчанию формат с косой чертой перед каждым элементом (вместо разделяющих их запятыми), а также в прямом порядке.
/C=US/ST=Pennsylvania/L=Paoli/O=Duck Duck Go, Inc./CN=*.duckduckgo.com
но до версии 1.1.0 изменено значение по умолчанию, чтобы использовать разделители запятой с прямым порядком
C = US, ST = Pennsylvania, L = Paoli, O = "Duck Duck Go, Inc.", CN = *.duckduckgo.com
Некоторые операции командной строки OpenSSL, например x509
, поддержка других форматов отображения; см. справочную страницу в разделе "Параметры имени". В частностиx509 -nameopt oneline,dn_rev
дает почти тот же формат, что и Java:
CN = *.duckduckgo.com, O = "Duck Duck Go, Inc.", L = Paoli, ST = Pennsylvania, C = US
Wireshark, если вы посмотрите только сводку для переданного сертификата (в TLS), отобразит пары атрибут = значение с полными именами вместо сокращений для атрибутов в обратном порядке, как в RFC и Java:
но если вы щелкните поля со знаком плюса, чтобы развернуть несколько уровней, вы можете увидеть структуру с каждым элементом атрибута отдельно в прямом порядке:
Именно потому, что существует и было множество вариантов формата отображения, сравнивать DN как строки - не лучшая идея. Если вам нужно сохранить его как строку, например, в базе данных, лучший способ - перестроить структурированную форму из строки - используя согласованные соглашения относительно порядка, сокращений и т. Д. - и сравнить структурированные объекты. Это станет немного проще, если вы прочитаете javadoc и увидите, что X509Certificate.getIssuerDN()
и аналогично .getSubjectDN()
"опорочены" (очевидно, предназначены для "устаревания") и заменены с версии Java 1.4 на .getIssuerX500Principal()
а также .getSubjectX500Principal()
которые используют задокументированный класс API (вместо непрозрачного внутреннего класса) javax.security.auth.x500.X500Principal
с задокументированным .equals()
операция.