150 votes

Pourquoi le handshake SSL génère-t-il une exception "Could not generate DH keypair" (Impossible de générer une paire de clés DH) ?

Lorsque j'établis une connexion SSL avec certains serveurs IRC (mais pas avec d'autres - probablement en raison de la méthode de cryptage préférée du serveur), j'obtiens l'exception suivante :

Caused by: java.lang.RuntimeException: Could not generate DH keypair
    at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:106)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverKeyExchange(ClientHandshaker.java:556)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:183)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
    ... 3 more

Cause finale :

Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
    at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DashoA13*..)
    at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:627)
    at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:100)
    ... 10 more

Un exemple de serveur qui démontre ce problème est aperture.esper.net:6697 (il s'agit d'un serveur IRC). Un exemple de serveur ne présentant pas ce problème est kornbluth.freenode.net:6697. [Il n'est pas surprenant de constater que tous les serveurs de chaque réseau ont le même comportement].

Mon code (qui, comme indiqué, fonctionne lors de la connexion à certains serveurs SSL) est le suivant :

    SSLContext sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, trustAllCerts, new SecureRandom());
    s = (SSLSocket)sslContext.getSocketFactory().createSocket();
    s.connect(new InetSocketAddress(host, port), timeout);
    s.setSoTimeout(0);
    ((SSLSocket)s).startHandshake();

C'est la dernière poignée de main de démarrage qui provoque l'exception. Et oui, il y a un peu de magie avec le code "trustAllCerts" ; ce code force le système SSL à ne pas valider les certificats. (Ce n'est donc pas un problème de certificat).

Évidemment, une possibilité est que le serveur d'esper soit mal configuré, mais j'ai cherché et je n'ai pas trouvé d'autres références à des personnes ayant des problèmes avec les ports SSL d'esper, et 'openssl' s'y connecte (voir ci-dessous). Je me demande donc s'il ne s'agit pas d'une limitation du support SSL par défaut de Java, ou quelque chose comme ça. Des suggestions ?

Voici ce qui se passe lorsque je me connecte à aperture.esper.net 6697 en utilisant 'openssl' depuis la ligne de commande :

~ $ openssl s_client -connect aperture.esper.net:6697
CONNECTED(00000003)
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
verify return:1
---
Certificate chain
 0 s:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
   i:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
---
Server certificate
-----BEGIN CERTIFICATE-----
[There was a certificate here, but I deleted it to save space]
-----END CERTIFICATE-----
subject=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
issuer=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
---
No client certificate CA names sent
---
SSL handshake has read 2178 bytes and written 468 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: 51F1D40A1B044700365D3BD1C61ABC745FB0C347A334E1410946DCB5EFE37AFD
    Session-ID-ctx: 
    Master-Key: DF8194F6A60B073E049C87284856B5561476315145B55E35811028C4D97F77696F676DB019BB6E271E9965F289A99083
    Key-Arg   : None
    Start Time: 1311801833
    Timeout   : 300 (sec)
    Verify return code: 18 (self signed certificate)
---

Comme indiqué, après tout cela, il se connecte avec succès, ce qui est plus que ce que l'on peut dire de mon application Java.

Si cela s'avère pertinent, j'utilise OS X 10.6.8, Java version 1.6.0_26.

0voto

Nous avons obtenu le même retour d'erreur d'exception, mais il a été facile de le résoudre après avoir passé des heures à surfer sur l'internet.

Nous avons téléchargé la version la plus récente de jdk que nous avons pu trouver sur oracle.com, nous l'avons installée et nous avons dirigé le serveur d'application Jboss vers le répertoire du nouveau jdk installé.

Redémarrage de Jboss, retraitement, problème résolu !!!

0voto

Evgeny Lebedev Points 721

J'ai obtenu cette erreur avec Bamboo 5.7 + Gradle project + Apache. Gradle a essayé d'obtenir des dépendances d'un de nos serveurs via SSL.

Solution :

  1. Générer les paramètres DH :

avec OpenSSL :

openssl dhparam 1024

exemple de sortie :

-----BEGIN DH PARAMETERS-----
MIGHfoGBALxpfMrDpImEuPlhopxYX4L2CFqQov+FomjKyHJrzj/EkTP0T3oAkjnS
oCGh6p07kwSLS8WCtYJn1GzItiZ05LoAzPs7T3ST2dWrEYFg/dldt+arifj6oWo+
vctDyDqIjlevUE+vyR9MF6B+Rfm4Zs8VGkxmsgXuz0gp/9lmftY7AgEC
-----END DH PARAMETERS-----
  1. Ajouter la sortie au fichier de certificat (pour Apache - SSLCertificateFile param)

  2. Redémarrer apache

  3. Redémarrer Bamboo

  4. Réessayer de construire le projet

0voto

covener Points 3463

J'avais l'habitude d'obtenir une erreur similaire en accédant à svn.apache.org avec des clients SVN java utilisant un JDK IBM. Actuellement, svn.apache.org utilise les préférences de chiffrement des clients.

Après une seule exécution avec une capture de paquets / javax.net.debug=ALL, j'ai pu blacklister un seul cryptogramme DHE et les choses fonctionnent pour moi (ECDHE est négocié à la place).

.../java/jre/lib/security/java.security:
    jdk.tls.disabledAlgorithms=SSL_DHE_RSA_WITH_AES_256_CBC_SHA

Il s'agit d'une solution rapide et agréable lorsqu'il n'est pas facile de changer de client.

0voto

Sam Points 372

J'ai récemment rencontré le même problème et après avoir mis à jour la version de jdk de 1.6.0_45 a jdk1.7.0_191 ce qui a permis de résoudre le problème.

-1voto

Jason Martin Points 229

Si le serveur prend en charge un algorithme de chiffrement qui n'inclut pas DH, vous pouvez forcer le client à sélectionner cet algorithme et éviter l'erreur DH. Par exemple :

String pickedCipher[] ={"TLS_RSA_WITH_AES_256_CBC_SHA"};
sslsocket.setEnabledCipherSuites(pickedCipher);

Gardez à l'esprit que la spécification d'un chiffrement exact est susceptible d'entraîner des ruptures à long terme.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X