Как работает keytool: PrivateKeyEntry и trustedCertEntry?

#ssl #istio #keytool

#ssl #istio #keytool

Вопрос:

Хорошо, сначала я расскажу, что я знаю о том, как работает SSL.

Больше всего мне нужно понять, как работает сертификат клиента, потому что я настраивал mTls istio gateway и у меня возникли проблемы с этим.

Итак, сначала мне нужна пара ключей, частная и общедоступная. Если я правильно понял, я создаю их следующей командой:

 keytool -genkey -alias myKeyPair -keyalg RSA -keysize 2048 store.jks
  

Если я загляну в хранилище ключей, там будет один PrivateKeyEntry. Затем я создаю запрос на сертификат:

 keytool -certreq -keyalg RSA -alias myKeyPair -file request.csr -keystore store.jks
  

Через некоторое время я получил подписанный сертификат клиента client.cer и сертификат доверенного центра сертификации ca.cer .
Теперь есть вопросы:

Сначала я попытался отправить запрос из curl. Но curl нужен закрытый ключ, который хранится в jks. У меня нет openssl, и я не могу его получить, поэтому я извлекаю закрытый ключ, используя Java-код. Но результат всегда был одним и тем же: istio gateway: peer did not return a certificate

Во-вторых, я попытался использовать параметр java.net.http.HttpClient with SSLContext , содержащий мои jks. И это сработало. Но сначала мне пришлось вставить ca.cer и client.cer в мой jks. И этого я не могу понять: зачем мне нужно ставить ca.cer ? Потому что без ca.cer сохраненного в store.jks у меня ошибка проверки сертификата.

Также, когда я помещаю client.cer в jks, keytool отображает предупреждение: Certificate already exists in keystore under alias <myKeyPair>. Do you still want to add it? Почему он считает, что PrivateKeyEntry и trustedCertEntry одинаковы?

Комментарии:

1. Привет, какую версию istio ты используешь?

Ответ №1:

Meta: плохой ответ из-за расплывчатости вопроса, но слишком длинный для комментариев.

Сначала я попытался отправить запрос из curl. Но curl нужен закрытый ключ, который хранится в jks. У меня нет openssl, и я не могу его получить, поэтому я извлекаю закрытый ключ, используя Java-код. Но результат всегда был один и тот же: шлюз istio: одноранговый узел не вернул сертификат

Либо ваш ‘extract’ был неправильным, либо способ, которым вы предоставили его curl, был неправильным, либо и то, и другое, и вы не описали ни то, ни другое. Во-первых, чтобы было понятно, как и любому клиенту, выполняющему аутентификацию клиента, curl на самом деле нужны privatekey и сертификат, и обычно любые применимые сертификаты цепочки. Какие форматы файлов вы должны использовать, и будет ли это единый объединенный файл или отдельные файлы (добавлено:) или их вообще не будет, как выясняется, зависит от используемой вами сборки curl: curl поддерживает семь реализаций SSL / TLS, и способы предоставления клиентского ключа и сертификата различаются среди них. Используйте curl -V (верхний регистр), чтобы увидеть, как он был создан, затем просмотрите разделы справочной страницы в вашей системе или в Интернете, которые применяются к этой реализации.

Во-вторых, я попытался использовать java.net.http.HttpClient с настройкой SSLContext, содержащей мои jks. И это сработало. Но сначала мне пришлось поместить ca.cer и client.cer в мой jks. И это я не могу понять: зачем мне нужно ставить ca.cer? Потому что без ca.cer, хранящегося в store.jks, у меня ошибка проверки сертификата.

Возможно, это «цепочка» или промежуточный сертификат CA. Стандарт требует, чтобы клиент SSL / TLS (например, сервер) отправлял любые сертификаты цепочки, необходимые для подключения сертификата конечного объекта (клиента или сервера) к обычному «корню» в хранилище доверия получателя. (Начиная с RFC5280 и подтвержденный RFC8446, на самом деле возможно использовать привязку, которая не является корневой, но это редко делается.) Возможно, это даже комбинация сертификатов цепочки и root (или привязки). (Некоторые отправители иногда все еще могут создать цепочку для проверки сертификата, когда он был отправлен неправильно; браузеры особенно склонны это делать, но большинство серверов — нет.)

Посмотрите на это и убедитесь. Если это формат PEM, вы можете увидеть с помощью любой программы отображения текста или редактирования, сколько сертификатов он содержит. Если это единый сертификат, вы можете отобразить детали с помощью keytool -printcert -file $file — или, поскольку вы уже импортировали его, keytool -list -v -alias name -keystore $ks [-storepass $pw] . Если это несколько сертификатов в формате PEM, вы можете разделить их с помощью редактора и отобразить каждый из них отдельно. Если это несколько сертификатов в формате DER, вы не сможете с этим легко справиться, но, к счастью, этот формат используется редко. openssl x509 [-inform pem|der] -text -noout также обычно используется для отображения сведений о файле сертификата, но вы говорите, что не можете его использовать.

Также, когда я помещаю client.cer в jks, keytool отображает предупреждение: сертификат уже существует в хранилище ключей под псевдонимом . Вы все еще хотите его добавить? Почему он считает, что PrivateKeyEntry и trustedCertEntry — это одно и то же?

Если вы сделали это только один раз и правильно, этого не должно быть. Учитывая отдельные файлы сертификатов, вы должны keytool -importcert предоставить клиентскому сертификату псевдоним записи privatekey, которую вы создали, и использовать для создания -certreq , которая в вашем примере является myKeyPair , после вас keytool -importcert любых необходимых сертификатов цепочки и, необязательно, корневых или привязанных (для каждого) к другому псевдониму. (Часто удобно, но не обязательно, использовать простые слова, такие как root , imed , imed2 и т.д. в качестве псевдонимов.) В качестве альтернативы, если у вас есть вся цепочка в виде одного файла, либо последовательности PEM, либо последовательности DER, либо ‘p7b’ (фиктивные подписанные данные PKCS7 без данных и подписи, обычно используемые в качестве контейнера для одного или нескольких сертификатов, таких как цепочка), либо PEM, либо DER, вам следует импортировать эту цепочку за одну операцию.

Комментарии:

1. Я нашел способ получить openssl, так что теперь я успешно конвертировал store.jks в key.pem и cert.pem . Я пытаюсь подключиться через curl curl -v --key key.pem --cert cert.pem --cacert ca.pem --ssl-no-revoke https://myserver/test , но ошибка остается той же: schannel: next InitializeSecurityContext failed: SEC_E_ILLEGAL_MESSAGE (0x800990326) Также я пытаюсь добавить в cert.pem все доверенные сертификаты из ca.pem

2. curl -V: curl 7.55.1 (Windows) libcurl/7.55.1 WinSSL

3. pwflamy: WinSSL на самом деле является Schannel; смотрите части справочной страницы для этого. Он не используется --cert --key с файлами PEM или вообще с любыми файлами; для клиентских сертификатов и ключей используется только хранилище Windows . Утверждения на странице руководства --cert могут использоваться для выбора записи в Windows Store по отпечатку пальца, но мой Win10 (недавно обновленный до 2004 года) даже этого не делает. Используйте keytool или openssl для создания файла PKCS12 и используйте «Инструменты администратора» с плагином Cert — или просто certmgr.msc напрямую — для импорта его в «личный» раздел вашего магазина.