2012-05-21 2 views
14

Я прочитал предыдущее сообщение об ошибке «Не удалось создать DH keypair», когда сервер передает ключ длиннее 1024 бит. Загрузка JCE неограниченных банок должна исправить эту проблему. В тестовой среде я столкнулся с следующим: для того же веб-сервера, если я использую Java 6, я не получаю никаких ошибок при выполнении запроса https, но если я использую Java 7, тогда я получаю «Не удалось создать DH keypair».Java 7 и не удалось создать DH keypair

Я попытался заменить файлы jar для JCE неограниченно, но все равно получить ту же ошибку. Об ошибке сообщается с 2007 года, но почему она запускается для Java 6, а не для Java 7? Не загружаются ли файлы не соответствующими? Я получил ссылку с предыдущего сообщения Java: Why does SSL handshake give 'Could not generate DH keypair' exception?.

На данный момент я не знаю, что делать. Если я попытаюсь загрузить поставщика BouncyCastle, я получаю исключение ArrayOutOfIndex. Мой сервер разрешает только алгоритм DH, поэтому я не могу использовать другой алгоритм, подобный предложенному выше.

ответ

8

Я наткнулся на ту же проблему с SSLScokets, и я думаю, что я определил причину этой регрессии с Java 7. Причина кроется в шифрах, согласованных между клиентом и сервером.

По умолчанию Java 6 включает эти шифры для соединения TLS (в порядке приоритета):

SSL_RSA_WITH_RC4_128_MD5 
SSL_RSA_WITH_RC4_128_SHA 
TLS_RSA_WITH_AES_128_CBC_SHA 
TLS_DHE_RSA_WITH_AES_128_CBC_SHA 
TLS_DHE_DSS_WITH_AES_128_CBC_SHA 
SSL_RSA_WITH_3DES_EDE_CBC_SHA 
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA 
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA 
SSL_RSA_WITH_DES_CBC_SHA 
SSL_DHE_RSA_WITH_DES_CBC_SHA 
SSL_DHE_DSS_WITH_DES_CBC_SHA 
SSL_RSA_EXPORT_WITH_RC4_40_MD5 
SSL_RSA_EXPORT_WITH_DES40_CBC_SHA 
SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA 
SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA 
TLS_EMPTY_RENEGOTIATION_INFO_SCSV 

и Java 7 включает эти шифры:

TLS_DHE_RSA_WITH_AES_128_CBC_SHA 
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA 
SSL_RSA_WITH_RC4_128_SHA 
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 
TLS_ECDHE_RSA_WITH_RC4_128_SHA 
TLS_ECDH_ECDSA_WITH_RC4_128_SHA 
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 
TLS_ECDH_RSA_WITH_RC4_128_SHA 
TLS_EMPTY_RENEGOTIATION_INFO_SCSV 
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 
TLS_RSA_WITH_AES_128_CBC_SHA 
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 
SSL_RSA_WITH_RC4_128_MD5 
TLS_DHE_DSS_WITH_AES_128_CBC_SHA 
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA 
SSL_RSA_WITH_3DES_EDE_CBC_SHA 

шифров с использованием Диффи-Хеллмана бывают выше приоритет на Java 7, но они, похоже, не поддерживают ключи длиной более 1024 бит, если не установлен сильный криптова пакет.

Обходной я должен был указать шифры включена по Java 6 на SSLSocket:

SSLSocketFactory socketFactory = SSLContext.getInstance("TLS").getSocketFactory(); 
SSLSocket socket = (SSLSocket) socketFactory.createSocket(InetAddress.getByName(hostname), port); 
socket.setEnabledCipherSuites(new String[] { 
     "SSL_RSA_WITH_RC4_128_MD5", 
     "SSL_RSA_WITH_RC4_128_SHA", 
     "TLS_RSA_WITH_AES_128_CBC_SHA", 
     "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", 
     "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", 
     "SSL_RSA_WITH_3DES_EDE_CBC_SHA", 
     "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", 
     "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", 
     "SSL_RSA_WITH_DES_CBC_SHA", 
     "SSL_DHE_RSA_WITH_DES_CBC_SHA", 
     "SSL_DHE_DSS_WITH_DES_CBC_SHA", 
     "SSL_RSA_EXPORT_WITH_RC4_40_MD5", 
     "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", 
     "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", 
     "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", 
     "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"}); 

socket.startHandshake(); 
+0

Спасибо большое, я обнаружил странный * java.security.ProviderException: солнце .security.pkcs11.wrapper.PKCS11Exception: CKR_DOMAIN_PARAMS_INVALID * ошибка при использовании Webscarab (прокси SSL MITM). Явное указание этих наборов шифров заставляет его работать снова. – Lekensteyn

+1

Я новичок в ценных бумагах. Где я должен писать этот кусок кода? – Shashank

0

Если вы используете jdk1.7.0_04, обновление до jdk1.7.0_21. Проблема была исправлена ​​в этом обновлении.

+0

Прохладный. Это было исправлено в новых версиях Java. Но мой вопрос заключается в использовании более старой версии. Когда я использую более старую версию, иногда она работает, а иногда она дает исключение выше. Почему такое случайное поведение? Если его ошибка в java, то я думаю, что она никогда не должна работать? –

+2

К сожалению, я все еще получаю эту ошибку в '7u21-2.3.9-1ubuntu1'. – expert

+0

Я все еще получаю эту ошибку в сборке 1.7.0_45-b18 – duffymo

10

Некоторые дополнения или уточнения:

(Suncle) Java 7, так как 7u09 использует более разумный последовательный порядок ciphersuites по умолчанию, в отличие от, казалось бы, случайном порядке в 7u04. (У меня нет тестов с 04 по 09.) Этот заказ помещает ECDHE и plain-RSA (aka akRSA) перед DHE и, таким образом, позволяет избежать проблемы, если И ТОЛЬКО ЕСЛИ сервер поддерживает ECDHE или RSA и соглашается с предпочтением клиента. (Или ECDH-fixed, но практически никто не использует это.) Если сервер настаивает на DHE (по какой-либо причине) И использует DH> 1024 бит, у вас все еще есть проблема.

Если консультант (или кто-либо еще) подключается к серверу, которому действительно требуется целое-DH (а не ECDH или RSA), единственный способ работать с Java до 8 - заставить сервер использовать DH 1024-бит , Какой AFAWK технически безопасен еще несколько лет, но с небольшим отрывом ему запрещают важные власти, такие как NIST (см. Специальный паб 800-57 на csrc.nist.gov). (Даже RSA 1024 на самом деле еще не сломался, но, вероятно, это будет скоро, и поэтому это запрещено.)

«Политика неограниченной прочности» не имеет отношения к этой проблеме или, по крайней мере, не напрямую, и к хорошим ответам на # 6851461 не сказал, что это так. Он не изменяет ограничение параметров DH в SunJCE, которое (ошибочно) рассматривается как стандартная проблема, а не проблема с сильной стороной. (В частности, он принимает ограничения, которые были правильны для DSA, и применяет их к DH.) Он включает в себя пакеты AES-256 и SHA-2 (только для TLSv1.2) и дает достаточно странный список предпочтений, который может изменить результат выбора из DHE (сбой) на не-DHE (работает).

Вам не нужно полностью возвращаться к списку Java 6, вам просто нужно назначить приоритет другим обмену ключами через DHE или полностью отказываться от DHE сервера. Вы определенно НЕ должны возвращаться к разрешению любых EXPORT или наборов DES-DES, если это абсолютно необходимо для старого сервера; они не были БЕЗОПАСНЫ в течение нескольких лет и оставались включенными по умолчанию в 6 дольше, чем они должны были.

1

Мы также столкнулись с этой проблемой с Java7 и Java8. Мы также использовали обходное решение, подобное предложениям Эмануаль Борга. Но наша цель состояла в том, чтобы избежать жесткого кодирования фиксированного списка CipherSuites. Поэтому мы попытались удалить записи, вызвавшие проблему (методом проб и ошибок ...).

String[] enabledCipherSuites = socket.getEnabledCipherSuites(); 

// avoid hardcoding a new list, we just remove the entries 
// which cause the exception 
List<String> asList = new ArrayList(Arrays.asList(enabledCipherSuites)); 

// we identified the following entries causeing the problems 
// "Could not generate DH keypair" 
// and "Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)" 
asList.remove("TLS_DHE_RSA_WITH_AES_128_CBC_SHA"); 
asList.remove("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"); 
asList.remove("TLS_DHE_RSA_WITH_AES_256_CBC_SHA"); 

String[] array = asList.toArray(new String[0]); 
socket.setEnabledCipherSuites(array); 

Вопрос: Кто-нибудь видит проблему с этим подходом?

Btw: В случае, если вы используете Apache HTTPClient, то https://issues.apache.org/jira/browse/HTTPCLIENT-1111 интересно, который показывает, как установить CipherSuites (начиная с HTTPClient v4.2) с помощью метода

SSLConnectionSocketFactory() {...}.prepareSocket(SSLSocket) 

Update 2015/10/31 : чтобы лучше понять контекст, в котором, чтобы использовать это, вот как полный пример псевдо-кода, в котором вы видите, как подключить в переопределить prepareSocket() метод:

HttpClientBuilder builder = HttpClients.custom(); 

SSLContextBuilder sslContextBuilder = SSLContexts.custom(); 
SSLContext sslContext = sslContextBuilder.build(); 

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, hostNameVerfier) 
{ 


    protected void prepareSocket(SSLSocket socket) throws IOException { 

    // Workaround to use different order of CipherSuites used by Java6 in order 
     // to avoid the the problem of java7 "Could not generate DH keypair" 
     String[] enabledCipherSuites = socket.getEnabledCipherSuites(); 

     // but to avoid hardcoding a new list, we just remove the entries 
     // which cause the exception (via TrialAndError) 
     List<String> asList = new ArrayList(Arrays.asList(enabledCipherSuites)); 

     // we identified the following entries causeing the problems 
     // "Could not generate DH keypair" 
     // and "Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)" 
     asList.remove("TLS_DHE_RSA_WITH_AES_128_CBC_SHA"); 
     asList.remove("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"); 
     asList.remove("TLS_DHE_RSA_WITH_AES_256_CBC_SHA"); 

     String[] array = asList.toArray(new String[0]); 
     socket.setEnabledCipherSuites(array); 

    }; 
}; 

Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create().register("https", sslsf).build(); 

PoolingHttpClientConnectionManager conman = new PoolingHttpClientConnectionManager(socketFactoryRegistry); 
builder.setConnectionManager(conman); 

CloseableHttpClient httpClient = builder.build(); 

Будьте осторожны Мы используем этот кусок кода только в контексте, где пользователь явно позволяет доверять самозаверяющим сертификатам (например, для тестовых сред и т. д.). Если вы не хотите этого делать, тогда лучше не вмешиваться в SSL-материал.

+0

Я использую apache httpclient, но не мог понять, как использовать prepareSocket –

6

Учитывая вы используете последнюю версию Java Edition и до сих пор получаю ошибку, вы можете изменить настройки в java.security (например, в папке C: \ Program Files \ Java \ jre1.8.0_xx \ Lib \ безопасность

.!
# Example: 
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 
    jdk.tls.disabledAlgorithms=SSLv3, RC4 

Добавить DH в качестве алгоритма инвалидов в jdk.tls.disabledAlgorithms

jdk.tls.disabledAlgorithms=SSLv3, RC4, DH 

Restart или кот перезапускать программу

Смежные вопросы