Я довольно новичок HTTPS/SSL/TLS
и немного запутался в том, что именно клиенты должны представлять при аутентификации с помощью сертификатов.
Я пишу Java-клиент, который должен делать простые POST
данные для конкретного URL
. Эта часть работает нормально, единственная проблема в том, что она должна быть закончена HTTPS
. Эта HTTPS
часть довольно проста в обращении (со HTTPclient
встроенной HTTPS
поддержкой Java или с ее помощью ), но я застрял на аутентификации с помощью клиентских сертификатов. Я заметил, что здесь уже есть очень похожий вопрос, который я еще не пробовал с моим кодом (сделаю это достаточно скоро). Моя текущая проблема заключается в том, что - что бы я ни делал - клиент Java никогда не отправляет сертификат (я могу проверить это с помощью PCAP
дампов).
Я хотел бы знать, что именно клиент должен представлять серверу при аутентификации с помощью сертификатов (особенно для Java - если это вообще имеет значение)? Это JKS
файл или PKCS#12
? Что должно быть в них; просто сертификат клиента или ключ? Если да, то какой ключ? Существует много недоразумений по поводу всех типов файлов, типов сертификатов и тому подобного.
Как я уже говорил ранее, я новичок в этом, HTTPS/SSL/TLS
поэтому я был бы признателен за некоторую справочную информацию (не должно быть эссе; я соглашусь на ссылки на хорошие статьи).
источник
Ответы:
Наконец-то удалось решить все вопросы, поэтому я отвечу на свой вопрос. Это настройки / файлы, которые я использовал для решения своих проблем;
В хранилище ключей клиента является формат PKCS # 12 файл , содержащий
Для генерации я использовал
pkcs12
команду OpenSSL , например;Совет: убедитесь, что вы получили последнюю версию OpenSSL, а не версию 0.9.8h, потому что, похоже, она страдает от ошибки, которая не позволяет правильно генерировать файлы PKCS # 12.
Этот файл PKCS # 12 будет использоваться клиентом Java для представления сертификата клиента серверу, когда сервер явно запросил у клиента аутентификацию. См. Статью в Википедии о TLS для обзора того, как на самом деле работает протокол для аутентификации сертификата клиента (здесь также объясняется, почему нам нужен закрытый ключ клиента).
В доверенном хранилище клиента является прямым JKS формат файл , содержащий корень или промежуточного ЦСА сертификатов . Эти сертификаты CA будут определять, с какими конечными точками вам будет разрешено общаться, в этом случае ваш клиент сможет подключиться к тому серверу, на котором будет представлен сертификат, который был подписан одним из центров доверенных сертификатов.
Для его генерации вы можете использовать стандартный Java keytool, например;
Используя это доверенное хранилище, ваш клиент попытается выполнить полное рукопожатие SSL со всеми серверами, которые представляют сертификат, подписанный ЦС, идентифицированным
myca.crt
.Приведенные выше файлы предназначены исключительно для клиента. Если вы также хотите настроить сервер, ему нужны собственные файлы хранилища ключей и доверенных сертификатов. На этом веб-сайте можно найти отличное руководство по настройке полностью работающего примера для клиента и сервера Java (с использованием Tomcat) .
Проблемы / Замечания / Советы
-Djavax.net.debug=ssl
но является более структурированным и (возможно) более легким для интерпретации, если вас не устраивает отладочный вывод Java SSL.Вполне возможно использовать библиотеку Apache httpclient. Если вы хотите использовать httpclient, просто замените целевой URL-адрес на HTTPS-эквивалент и добавьте следующие аргументы JVM (которые одинаковы для любого другого клиента, независимо от библиотеки, которую вы хотите использовать для отправки / получения данных по HTTP / HTTPS) :
источник
SSLContext
как в ответе @ Магнуса.Другие ответы показывают, как глобально настроить клиентские сертификаты. Однако если вы хотите программно определить ключ клиента для одного конкретного соединения, а не глобально определять его для каждого приложения, работающего на вашей JVM, то вы можете настроить свой собственный SSLContext следующим образом:
источник
sslContext = SSLContexts.custom().loadTrustMaterial(keyFile, PASSWORD).build();
. Я не мог заставить это работатьloadKeyMaterial(...)
.loadKeyMaterial(keystore, keyPassphrase.toCharArray())
коде, а также!SSLContext
.Их JKS-файл является просто контейнером для сертификатов и пар ключей. В сценарии аутентификации на стороне клиента различные части ключей будут расположены здесь:
Разделение склада доверенных сертификатов и хранилища ключей не обязательно, но рекомендуется. Они могут быть одним и тем же физическим файлом.
Чтобы установить расположение файловой системы двух хранилищ, используйте следующие системные свойства:
и на сервере:
Чтобы экспортировать сертификат клиента (открытый ключ) в файл, чтобы вы могли скопировать его на сервер, используйте
Чтобы импортировать открытый ключ клиента в хранилище ключей сервера, используйте (как упоминалось выше, администраторы сервера уже сделали это)
источник
Maven pom.xml:
Java-код:
источник
configureRequest()
для установки прокси клиентского проекта правильно?Для тех из вас, кто просто хочет настроить двустороннюю аутентификацию (серверные и клиентские сертификаты), комбинация этих двух ссылок поможет вам:
Настройка двусторонней аутентификации:
https://linuxconfig.org/apache-web-server-ssl-authentication
Вам не нужно использовать конфигурационный файл openssl, который они упоминают; просто используйте
$ openssl genrsa -des3 -out ca.key 4096
$ openssl req -new -x509 -days 365 -key ca.key -out ca.crt
создать свой собственный сертификат CA, а затем сгенерировать и подписать ключи сервера и клиента с помощью:
$ openssl genrsa -des3 -out server.key 4096
$ openssl req -new -key server.key -out server.csr
$ openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 100 -out server.crt
и
$ openssl genrsa -des3 -out client.key 4096
$ openssl req -new -key client.key -out client.csr
$ openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 101 -out client.crt
В остальном следуйте инструкциям по ссылке. Управление сертификатами для Chrome работает так же, как в примере для Firefox, который упоминается.
Далее настройте сервер через:
https://www.digitalocean.com/community/tutorials/how-to-create-a-ssl-certificate-on-apache-for-ubuntu-14-04
Обратите внимание, что вы уже создали серверы .crt и .key, поэтому вам больше не нужно делать этот шаг.
источник
server.key
неclient.key
Я подключился к банку по двустороннему протоколу SSL (сертификат клиента и сервера) с помощью Spring Boot. Итак, опишите здесь все мои шаги, надеюсь, это кому-нибудь поможет (самое простое рабочее решение, которое я нашел):
Генерация запроса сертификата:
Создать закрытый ключ:
Создать запрос на сертификат:
Сохраните
user.key
(и пароль) и отправьте запрос сертификатаuser.csr
в банк для моего сертификатаПолучите 2 сертификата: мой клиентский корневой сертификат
clientId.crt
и банковский корневой сертификат:bank.crt
Создать хранилище ключей Java (введите пароль ключа и установите пароль хранилища ключей):
Не обращайте внимания на результат
unable to write 'random state'
. Java PKCS12keystore.p12
создан.Добавьте в хранилище ключей
bank.crt
(для простоты я использовал одно хранилище ключей):Проверьте сертификаты хранилища ключей по:
Готов к Java-коду :) Я использовал Spring Boot
RestTemplate
сorg.apache.httpcomponents.httpcore
зависимостью add :источник
Учитывая файл p12 с сертификатом и закрытым ключом (сгенерированным, например, openssl), следующий код будет использовать его для определенного HttpsURLConnection:
Процесс
SSLContext
инициализации занимает некоторое время, поэтому вы можете его кэшировать.источник
Я думаю, что исправлением здесь был тип хранилища ключей, pkcs12 (pfx) всегда имеет закрытый ключ, а тип JKS может существовать без закрытого ключа. Если вы не укажете в своем коде или не выберете сертификат через браузер, сервер не сможет узнать, что он представляет клиента на другом конце.
источник