(Не ответ, но слишком много комментариев).
, где содержимое client.csr предоставляется в виде строки открытого ключа ...
CSRэто не открытый ключ, это CSR.Но код, который вы показываете, явно не использует его.Он, очевидно, использует сертификат, который также не является открытым ключом, это сертификат, который содержит открытый ключ.Тем не менее, сертификат, а НЕ открытый ключ ИЛИ CSR, является правильной вещью, которую следует использовать для аутентификации SSL / TLS.
Я получаю закрытый ключ PKCS # 1 в качестве ввода строки, и я должен использоватьНадежный замок для конвертации в PKCS # 8 и генерации privatekey и добавления в хранилище ....
На самом деле вам не нужно конвертировать в PKCS8;PEMParser plus JcaPEMKeyConvertor может конвертировать PKCS1 напрямую в KeyPair, содержащую пригодный для использования (RSA) PrivateKey, что намного проще.Или OpenSSL может легко создать ключ PKCS8, который может прочитать стандартный JCE (без BouncyCastle) - или, в этом отношении, PKCS12, который уже является хранилищем ключей Java без какого-либо преобразования.Но то, что у вас работает, работает.
Теперь мне нужно создать хранилище ключей java, добавить эти ключи и прагматично экспортировать в файл JKS.
В сторону: вы, вероятно, имеете в виду программно, а не прагматично.Ваш код не экспортирует файл хранилища ключей и не нуждается в этом;и вам не нужно специально использовать хранилище ключей JKS, любое поддерживаемое хранилище ключей в памяти должно работать, хотя вы не показываете код, выполняющий соединение и использующий хранилище ключей.Начиная с Java 9 (почти два года назад), Oracle рекомендует , чтобы люди прекратили использовать JKS и вместо этого использовали PKCS12, хотя я сомневаюсь, что они действительно отбросят JKS в ближайшее время.
javax.net.ssl.SSLProtocolException: нарушение последовательности сообщений рукопожатия, 2
Это ваша настоящая проблема, и это не хранилище ключей или ключ, и не должно быть сертификатом.Даже если вы отправляете ключ и подтверждаете, что он не нравится, сервер должен ответить, отклонив аутентификацию в пределах протокола (ов), не нарушая протокол.И 2 - ServerHello, которое должно происходить только за до , когда сертификат отправляется или проверяется в направлении или .Выполните хотя бы одно из следующих действий:
стандартная отладка Java SSL / TLS : запустите с помощью sysprop javax.net.debug=ssl,handshake
и перехватите / зарегистрируйте вывод.(Ниже Java 11 вы на самом деле можете использовать только ssl
, и он автоматически включает handshake
.) Это точно покажет, что ваша система отправляет и получает, и позволяет определить, как это неправильно, что должно, по крайней мере, помочь определить, почему.
захватите рукопожатие с помощью сетевой трассировки, например wireshark, tcpdump или аналогичной, и посмотрите на нее.Это работает, даже если в Java что-то серьезно не так (чего не должно быть), но его, по крайней мере, немного сложнее декодировать, и если вы не очень осторожны, рискуете включить другие данные в сеть в течение того же периода времени,может быть чувствительным и недоступным для обмена.
попытайтесь соединиться с другим инструментом (или инструментами), используя тот же ключ + сертификат и с того же компьютера, если это вообще возможно - это может быть проблема, связанная с сетью, которая зависитна том, где вы подключаетесь.Поскольку у вас есть openssl
и у вас уже есть файлы в форматах OpenSSL, проще всего использовать
openssl s_client -connect $host:$port -key keyfile -cert certfile [see text]
s_client
также является необычным (уникальным AFAIK) в том смысле, что вы можете контролировать, отправляется ли SNI (расширение индикации имени сервера), и в настоящее время со многими серверами это может хорошо влиять на поведение сервера (возможно, вызывая или подавляяошибка).То, отправляет ли Java (JSSE) SNI, зависит от комбинации обычно нескольких факторов, которые вы нам не сообщили: всегда версия Java и, как правило, некоторые детали кода, выполняющего попытку подключения, особенно, использует ли он HttpsURLConnection
, новыйj11 + HttpClient
, сторонний код, такой как Apache или Google, или пользовательский код.Для выпусков OpenSSL до 1.1.0 SNI не отправляется по умолчанию, и вы должны добавить -servername $host
, чтобы отправить его.Для 1.1.1 он отправляется по умолчанию, но не отправляется, если вы добавляете -noservername
.
В этом примере я не указал склад доверенных сертификатов.s_client
по умолчанию будет проверять хранилище доверенных сертификатов по умолчанию, которое может или может быть правильным для вашего сервера, но проигнорирует любую ошибку и продолжит работу в любом случае.Если вы отлаживали проблему доверия сертификата, тогда было бы важно сопоставить хранилище доверенных сертификатов OpenSSL с тем, которое используется вашей Java, но не для вашей проблемы.
уточните у оператора сервера) как эта проблема воспринимается с их стороны: думают ли они, что с вашим рукопожатием что-то не так, и если да, то что?Какое программное обеспечение (или, как правило, более подходящее промежуточное программное обеспечение) они используют, с какими настройками или опциями?
Если вы добавите (некоторую / достаточную) эту информацию в свой вопрос, я постараюсь обновить ее, чтобы она соответствовала действительности.