Java: Warum gibt der SSL-Handshake die Ausnahme 'DH-Schlüsselpaar nicht generieren' aus?


Answers

Die "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files" Antwort funktionierte nicht für mich, aber der BouncyCastle JCE Provider Vorschlag tat.

Hier sind die Schritte, die ich mit Java 1.6.0_65-b14-462 auf Mac OSC 10.7.5 unternommen habe

1) Laden Sie diese Gläser herunter:

2) verschiebe diese Jars nach $ JAVA_HOME / lib / ext

3) Bearbeiten Sie $ JAVA_HOME / lib / security / java.security wie folgt: security.provider.1 = org.bouncycastle.jce.provider.BouncyCastleProvider

App mit JRE neu starten und ausprobieren

Question

Wenn ich eine SSL-Verbindung mit einigen IRC-Servern (aber nicht mit anderen - vermutlich aufgrund der bevorzugten Verschlüsselungsmethode des Servers) herstelle, erhalte ich die folgende Ausnahme:

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

Endgültige Ursache:

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

Ein Beispiel für einen Server, der dieses Problem demonstriert, ist aperture.esper.net:6697 (dies ist ein IRC-Server). Ein Beispiel für einen Server, der das Problem nicht zeigt, ist kornbluth.freenode.net:6697. [Es überrascht nicht, dass alle Server in jedem Netzwerk das gleiche Verhalten aufweisen.]

Mein Code (der wie erwähnt bei der Verbindung mit einigen SSL-Servern funktioniert) ist:

    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();

Es ist das letzte startHandshake, das die Ausnahme auslöst. Und ja, mit den 'trustAllCerts' gibt es etwas Magie; Dieser Code zwingt das SSL-System, keine Zertifikate zu validieren. (Also ... kein Cert-Problem.)

Offensichtlich ist eine Möglichkeit, dass der Server von esper falsch konfiguriert ist, aber ich suchte und fand keine anderen Verweise auf Personen, die Probleme mit den SSL-Ports von esper haben, und "openssl" stellt eine Verbindung her (siehe unten). Ich frage mich, ob dies eine Einschränkung der Java-Standard-SSL-Unterstützung oder etwas ist. Irgendwelche Vorschläge?

Hier ist, was passiert, wenn ich mit openess.esper.net 6697 mit 'openssl' von der Kommandozeile aus verbinden:

~ $ 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)
---

Wie bereits erwähnt, verbindet es sich erfolgreich, was mehr ist, als Sie für meine Java-App sagen können.

Sollte es relevant sein, verwende ich OS X 10.6.8, Java Version 1.6.0_26.




Die folgende Befehlszeile behebt das Problem für mich:

java -jar -Dhttps.protocols=TLSv1.2 -Ddeployment.security.TLSv1.2=true -Djavax.net.debug=ssl:handshake XXXXX.jar

Ich benutze JDK 1.7.0_79




Das Problem wurde behoben, indem auf JDK 8 aktualisiert wurde.




Wenn der Server eine Chiffre unterstützt, die DH nicht enthält, können Sie den Client zwingen, diese Chiffre auszuwählen und den DH-Fehler zu vermeiden. Sowie:

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

Beachten Sie, dass die Angabe einer genauen Chiffre auf lange Sicht anfällig für Bruch ist.




Ich habe den SSL-Fehler auf einem CentOS-Server mit JDK 6 festgestellt.

Mein Plan war es, eine höhere JDK-Version (JDK 7) zu installieren, die mit JDK 6 koexistieren sollte, aber es stellte sich heraus, dass es einfach nicht ausreichte, das neuere JDK mit rpm -i installieren.

Die JDK 7-Installation würde nur mit der rpm -U Upgrade-Option wie unten dargestellt erfolgreich sein.

1. Laden Sie JDK 7 herunter

wget -O /root/jdk-7u79-linux-x64.rpm --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; o raclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.rpm"

2. Die RPM-Installation schlägt fehl

rpm -ivh jdk-7u79-linux-x64.rpm
Preparing...                ########################################### [100%]
        file /etc/init.d/jexec from install of jdk-2000:1.7.0_79-fcs.x86_64 conflicts with file from package jdk-2000:1.6.0_43-fcs.x86_64

3. Die RPM-Aktualisierung ist erfolgreich

rpm -Uvh jdk-7u79-linux-x64.rpm
Preparing...                ########################################### [100%]
   1:jdk                    ########################################### [100%]
Unpacking JAR files...
        rt.jar...
        jsse.jar...
        charsets.jar...
        tools.jar...
        localedata.jar...
        jfxrt.jar...

4. Bestätigen Sie die neue Version

java -version
java version "1.7.0_79"
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)



Wenn Sie jdk1.7.0_04 verwenden, führen Sie ein Upgrade auf jdk1.7.0_21 durch. Das Problem wurde in diesem Update behoben.




Laden Sie "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy-Dateien" von der Java-Download-Site herunter und ersetzen Sie die Dateien in Ihrer JRE.

Das funktionierte für mich und ich brauchte nicht einmal BouncyCastle zu benutzen - der Standard Sun JCE konnte sich mit dem Server verbinden.

PS. Ich habe den gleichen Fehler (ArrayIndexOutOfBoundsException: 64), als ich versuchte, BouncyCastle zu verwenden, bevor ich die Richtliniendateien änderte, also scheint es, dass unsere Situation sehr ähnlich ist.




Die obige Antwort ist korrekt, aber in Bezug auf die Problemumgehung hatte ich Probleme mit der BouncyCastle-Implementierung, wenn ich sie als bevorzugten Provider festlegte:

java.lang.ArrayIndexOutOfBoundsException: 64
    at com.sun.crypto.provider.TlsPrfGenerator.expand(DashoA13*..)

Dies wird auch in einem Forum Thread diskutiert, den ich gefunden habe, der keine Lösung erwähnt. http://www.javakb.com/Uwe/Forum.aspx/java-programmer/47512/TLS-problems

Ich habe eine alternative Lösung gefunden, die für meinen Fall funktioniert, obwohl ich überhaupt nicht zufrieden damit bin. Die Lösung besteht darin, es so einzustellen, dass der Diffie-Hellman-Algorithmus überhaupt nicht verfügbar ist. Unter der Annahme, dass der Server einen alternativen Algorithmus unterstützt, wird er während der normalen Verhandlung ausgewählt. Offensichtlich liegt der Nachteil darin, dass wenn irgendjemand irgendwie einen Server findet, der Diffie-Hellman nur mit 1024 Bits oder weniger unterstützt, dann bedeutet dies tatsächlich, dass es dort nicht funktionieren wird, wo es vorher gearbeitet hat.

Hier ist Code, der bei einem SSLSocket funktioniert (bevor Sie ihn verbinden):

List<String> limited = new LinkedList<String>();
for(String suite : ((SSLSocket)s).getEnabledCipherSuites())
{
    if(!suite.contains("_DHE_"))
    {
        limited.add(suite);
    }
}
((SSLSocket)s).setEnabledCipherSuites(limited.toArray(
    new String[limited.size()]));

Böse.




Ich habe diesen Fehler mit Bamboo 5.7 + Gradle Projekt + Apache. Gradle hat versucht, einige Abhängigkeiten von einem unserer Server via SSL zu bekommen.

Lösung:

  1. Erzeuge DH Param:

mit OpenSSL:

openssl dhparam 1024

Beispielausgabe:

-----BEGIN DH PARAMETERS-----
MIGHfoGBALxpfMrDpImEuPlhopxYX4L2CFqQov+FomjKyHJrzj/EkTP0T3oAkjnS
oCGh6p07kwSLS8WCtYJn1GzItiZ05LoAzPs7T3ST2dWrEYFg/dldt+arifj6oWo+
vctDyDqIjlevUE+vyR9MF6B+Rfm4Zs8VGkxmsgXuz0gp/9lmftY7AgEC
-----END DH PARAMETERS-----
  1. Ausgabe an Zertifikatsdatei SSLCertificateFile (für Apache - SSLCertificateFile param)

  2. Starten Sie den Apache neu

  3. Neustart Bamboo

  4. Versuchen Sie erneut, das Projekt zu erstellen




Sie können den Provider dynamisch installieren:

1) Laden Sie diese Gläser herunter:

  • bcprov-jdk15on-152.jar
  • bcprov-ext-jdk15on-152.jar

2) Kopiere jars in WEB-INF/lib (oder deinen Klassenpfad)

3) Provider dynamisch hinzufügen:

import org.bouncycastle.jce.provider.BouncyCastleProvider;

...

Security.addProvider(new BouncyCastleProvider());