[Неподдерживаемый шифровальный пакет] [Java SSLSocket]

#java #ssl #encryption

#java #ssl #шифрование

Вопрос:

Я пытаюсь подключить сервер через SSLSocket, используя протокол TLSv1.2. Сервер поддерживает только следующие шифры.

  • ECDHE-ECDSA-AES128-GCM-SHA256
  • ECDHE-RSA-AES128-GCM-SHA256
  • ECDHE-ECDSA-AES128-SHA256

Когда я пытаюсь установить включенные наборы шифров, я сталкиваюсь со следующим исключением:

 java.lang.IllegalArgumentException: Unsupported ciphersuite ECDHE-ECDSA-AES128-GCM-SHA256
at sun.security.ssl.CipherSuite.valueOf(Unknown Source) ~[?:1.8.0_74]
at sun.security.ssl.CipherSuiteList.<init>(Unknown Source) ~[?:1.8.0_74]
at sun.security.ssl.SSLSocketImpl.setEnabledCipherSuites(Unknown Source) ~[?:1.8.0_74]
  

Я пытался заменить Java Cryptography Extension (JCE) Unlimited Strength Juridity Policy Files 8 на следующий URL-адрес на C:Program Файлы Java jdk1.8.0_92 jre lib security, но по-прежнему не удается подключиться к серверу.

URL: https://www.oracle.com/java/technologies/javase-jce8-downloads.html

Я использую следующий код для создания SSLSocket:

 protected void openSocket() throws IOException {
    LGR.info("Opening SSL socket to "   addr   ":"   port);
    String[] TLS_SUPPORTED_VERSIONS = new String[] { "TLSv1.2" };
    String[] CIPHER_SUITES = new String[] { "ECDHE-ECDSA-AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256", "ECDHE-ECDSA-AES128-SHA256" };
    try {
        SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(addr, port);
        socket.setEnabledProtocols(TLS_SUPPORTED_VERSIONS);
        socket.setEnabledCipherSuites(CIPHER_SUITES);
        
    } catch (Exception ex) {
        LGR.error("##Exception##", ex);
    } catch (Throwable ex) {
        LGR.error("##Throwable##", ex);
    }
}
  

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

1. Вы можете использовать Bouncy Castle вместо JCE по умолчанию.

Ответ №1:

Вы можете перечислить поддерживаемые наборы шифров с помощью:

 SSLSocketFactory socketFactory = SSLContext.getDefault().getSocketFactory();
for (String cipherSuite : socketFactory.getSupportedCipherSuites()) {
    System.out.println(cipherSuite);
}
  

Следующая запись соответствует запрошенному вами набору: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 .

Вам больше не нужны файлы политики юрисдикции неограниченной силы JCE:

  • в Java 8 u151 / u152 файлы политики были включены в стандартный дистрибутив Java, но их необходимо было включить явно: Security.setProperty("crypto.policy", "unlimited");
  • начиная с Java 8 u161 (и во всех будущих версиях Java), эти файлы политики включены, и по умолчанию включена политика неограниченного шифрования.

Вы можете проверить это следующим образом: Cipher.getMaxAllowedKeyLength("AES") должен вернуться Integer.MAX_VALUE , когда включена неограниченная мощность.

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

1. Я не знал, что эти шифры находятся в OpenSSL, и я должен использовать соответствующий шифр IANA. Но теперь я получаю ошибку «Сброс соединения». Я попытался включить отладку и обнаружил следующие строки. Поток-8, обработка исключения: java.net.SocketException: Сброс соединения %% Недействителен: [Сеанс-1, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256] Поток-8, ОТПРАВКА ПРЕДУПРЕЖДЕНИЯ TLSv1.2: фатальный, описание = unexpected_message Поток-8, ЗАПИСЬ: Предупреждение TLSv1.2, длина = 2 Поток-8, отправка предупреждения об исключении: java.net. Исключение SocketException: Сброс соединения одноранговым узлом: поток ошибок записи в сокет-8, вызываемый closeSocket()

2. При сбое установления связи TLS (нет взаимно поддерживаемых наборов шифров между клиентом и сервером, отсутствует взаимно поддерживаемая версия TLS или, что более вероятно: недействительный сертификат X509) соединение будет немедленно прервано. Сброс соединения с помощью однорангового узла означает, что другой конец закрыл соединение. Отладка с помощью OpenSSL или в Java с -Djavax.net.debug=ssl может помочь в поиске причины.

3. Спасибо за вашу помощь. Очень признателен.