Я столкнулся с некоторой проблемой при вызове стороннего-API из java-приложения. Для внешнего API требуется по крайней мере один из следующих шифров :
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
. Я следовал приведенным здесь инструкциям :https://confluence.atlassian.com/stashkb/list-ciphers-used-by-jvm-679609085.html, чтобы попытаться обновить доступные шифры на моем сервере приложений. Однако после обновления я все еще не вижу ни одного из перечисленных совместимых шифров.
Я подозреваю, что проблема в том, что на моем сервере работает jdk 1.7. Это устаревшее приложение, поэтому, к сожалению, я не могу перейти на более новый jdk. Есть ли способ добавить эти шифры в мою существующую установку Java?
Обновление: Я понял, как добавить дополнительные шифры, но, похоже, это не помогло. В моей фабрике сокетов я добавил такой код:
private Socket acceptOnlyTLS12(Socket socket) {
if (!(socket instanceof SSLSocket))
return socket;
SSLSocket sslSocket = (SSLSocket) socket;
sslSocket.setEnabledProtocols(new String[] { "TLSv1.2" });
List<String> ciphers = new ArrayList<String>(Arrays.asList(sslSocket.getEnabledCipherSuites()));
ciphers.add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256");
sslSocket.setEnabledCipherSuites(ciphers.toArray(new String[] {}));
return sslSocket;
}
Есть ли еще один шаг, который я где-то пропустил? Есть ли способ получить дополнительную информацию о том, почему рукопожатие ssl не работает?
Я, наконец, нашел обходной путь, хотя и немного уродливый. Я создал скрипт groovy, который делает cURL-запрос к внешнему API. Поскольку cURL может использовать последние сертификаты, я могу обойти ограничения, налагаемые на старый JDK. Это неуклюже, но это работает.
(1 )Эта веб-страница датирована 2014 годом; неограниченная политика больше не используется для версий Oracle Java после 2017 года и до этого (, что, например. 7u80 был )это имело значение только для симметричного шифрования более 128 бит , что здесь затронет только наборы AES256, а не наборы AES128. (Он никогда не применялся к OpenJDK, хотя OpenJDK ниже 8 в основном был доступен только в основных дистрибутивах Linux, таких как RedHat и Debian, которые могли выделить персонал для сборки и упаковки; вы не говорите, что вы используете.)
(2 )Java (1. )7поддерживает ли шифровальные наборы CBC, которые вы показываете (не GCM, а для версий Oracle ниже 7u171 AES256 действительно требуется неограниченная политика ), но ТОЛЬКО при использовании TLS1.2 (эти наборы шифров не существовали в протоколах более ранних версий ), и по умолчанию j7 отключает TLS1.2 (и 1.1 )на стороне клиента.
Если вы явно подключаетесь к этому API с помощью HttpsURLConnection
(, например.new URL("https://something").openConnection()
)вы можете настроить socketfactory для использования SSLContext.getInstance("TLSv1.2")
и/или явно setEnabledProtocols
в сокете. Если вы используете другое промежуточное ПО, например. Apache HttpComponents обычно имеют похожие методы, но они различаются в деталях; вам нужно будет показать нам код, и он, вероятно, будет принадлежать StackOverflow, а не здесь. Если вы вызываете библиотеку, которая выполняет внутреннее соединение, у нее могут быть параметры или нет. Для всех или многих методов вызова вы можете изменить значения по умолчанию, такие как SSLContext.setDefault()
или HttpsURLConnection.setDefaultSSLSocketFacfory()
, если эти значения по умолчанию не переопределены в соответствующем коде и , внесение таких глобальных изменений не вызывает проблем для всего, что работает в той же JVM.
Альтернативно (и еще по теме! )если у вас достаточно свежее обновление j7,Я почти уверен, что они перенесли системное свойство jdk.tls.client.protocols
, которое вы могли бы установить, например. TLSv1,TLSv1.1,TLSv1.2
для изменения значения по умолчанию без изменения кода (, но опять же только в том случае, если оно не переопределено и не вредит чему-либо еще ). Я не помню точно, когда это было, но определенно после 7u80, поэтому у вас было бы это только с платной поддержкой Oracle или OpenJDK, поддерживаемым кем-то еще за плату или бесплатно. Это легко попробовать, и может сработать.