Warum gibt SSL-Handshake die Ausnahme "DH-Schlüsselpaar konnte nicht generiert werden" aus?

142

Wenn ich eine SSL-Verbindung mit einigen IRC-Servern herstelle (aber nicht mit anderen - vermutlich aufgrund der bevorzugten Verschlüsselungsmethode des Servers), 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

Letzte 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 demonstriert, ist kornbluth.freenode.net:6697. [Es überrascht nicht, dass alle Server in jedem Netzwerk dasselbe Verhalten aufweisen.]

Mein Code (der wie erwähnt beim Herstellen einer Verbindung zu einigen SSL-Servern funktioniert) lautet:

    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 dieser letzte startHandshake, der die Ausnahme auslöst. Und ja, mit den 'trustAllCerts' ist etwas Magisches los. Dieser Code zwingt das SSL-System, keine Zertifikate zu validieren. (Also ... kein Zertifizierungsproblem.)

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

Folgendes passiert, wenn ich über 'openssl' über die Befehlszeile eine Verbindung zu aperture.esper.net 6697 herstelle:

~ $ 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, wird die Verbindung nach all dem erfolgreich hergestellt, 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.

Sam
quelle
2
Der Grund scheint folgender zu sein : Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive). Keine Ahnung, welche Größe der Server hier gesendet hat und was die Spezifikation dazu sagt.
Paŭlo Ebermann
@ PaŭloEbermann: Tatsächlich können Sie die Größe des in der opensslAusgabe verwendeten Servers in der Frage sehen: "Verschlüsselung ist DHE-RSA-AES256-SHA, öffentlicher Serverschlüssel ist 2048 Bit". Und 2048> 1024 :-).
Sleske
@sleske: nicht genau. Server public key (size)war und ist der Schlüssel im Zertifikat. s_clientim Jahr 2011 zeigte überhaupt keinen kurzlebigen Schlüssel; 1.0.2 im Jahr 2015 und Server Temp Keyhöher macht mehrere Zeilen höher. Obwohl ein guter Server normalerweise die DHE-Größe mit der RSA-Auth-Größe identisch machen sollte .
Dave_thompson_085

Antworten:

117

Das Problem ist die Primzahl. Die maximal akzeptable Größe, die Java akzeptiert, beträgt 1024 Bit. Dies ist ein bekanntes Problem (siehe JDK-6521495 ).

In dem von mir verlinkten Fehlerbericht wird eine Problemumgehung mit der JCE-Implementierung von BouncyCastle erwähnt . Hoffentlich sollte das für Sie funktionieren.

AKTUALISIEREN

Dies wurde als Fehler JDK-7044060 gemeldet und kürzlich behoben.

Beachten Sie jedoch, dass das Limit nur auf 2048 Bit angehoben wurde. Für Größen> 2048 Bit gibt es JDK-8072452 - Entfernen Sie die maximale Primgröße der DH-Schlüssel . Der Fix scheint für 9 zu sein.

Vivin Paliath
quelle
14
+1. Jeder, der ein Sun Developer Network-Konto hat, stimmt für diesen Fehler.
Paŭlo Ebermann
1
Vielen Dank. Scheint ein ziemlich ernstes Problem zu sein, da Server vorhanden sind, die eine größere Größe erfordern! :( Ich habe BouncyCastle ausprobiert. Wenn Sie es als bevorzugten Anbieter einrichten, stürzt es mit einer anderen Ausnahme ab (Seufzer), und ich sehe keinen offensichtlichen Weg, dies nur für DH zu verwenden. Ich habe jedoch eine alternative Lösung gefunden, die ich Ich werde als neue Antwort hinzufügen. (Es ist nicht schön.)
Sam
3
Cool. Dies wurde in neueren Versionen von Java behoben. Aber meine Frage betrifft die Verwendung einer älteren Version. Wenn ich eine ältere Version verwende, funktioniert es manchmal und manchmal gibt es eine Ausnahme. Warum so zufälliges Verhalten? Wenn es ein Fehler in Java ist, dann sollte es wohl nie funktionieren?
N ..
2
Das 2048-Update wurde auf IcedTea 2.5.3 zurückportiert. Neuere Versionen von IcedTea erhöhten es auf 4096.
FuzzyTew
1
Das Problem ist die DH-Primgröße. Die maximal akzeptable Größe, die Java akzeptiert, beträgt 2048 Bit. Während wir darauf warten, dass Oracle das Limit erweitert, können Sie mit Excelsior Jet kompilieren, das ein erweitertes Limit hat.
user1332994
67

Die Antwort "JCE-Richtliniendateien mit unbegrenzter Stärke für Java Cryptography Extension (JCE)" funktionierte bei mir nicht, der Vorschlag des JCE-Anbieters von The BouncyCastle jedoch.

Hier sind die Schritte, die ich mit Java 1.6.0_65-b14-462 unter Mac OSC 10.7.5 ausgeführt habe

1) Laden Sie diese Gläser herunter:

2) Verschieben Sie diese Gläser nach $ JAVA_HOME / lib / ext

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

Starten Sie die App mit JRE neu und probieren Sie es aus

mjj1409
quelle
5
funktioniert bei mir! obwohl nicht ganz sicher, was ich tue.
DiveInto
11
security.provider.2 = org.bouncycastle.jce.provider.BouncyCastleProvider funktionierte besser und stellte es auf 1. führte zu Fehlern in der Standardsoftware.
TinusSky
1
Dies funktioniert auch bei mir, aber ich habe dynamisch einen Anbieter hinzugefügt. Reffer meine Antwort hier für weitere Details.
v.ladynev
Vielen Dank, dies hat bei mir funktioniert und war erforderlich, um die Tomcat 7.0.78-Quelle erfolgreich zu erstellen.
Phillipsipiversum
@ mjj1409, in Java 1.5 haben wir nicht $ JAVA_HOME / lib / Sicherheitspfad
Mostafa
15

Hier ist meine Lösung (Java 1.6), würde mich auch interessieren, warum ich das tun musste:

Ich habe aus javax.security.debug = ssl bemerkt, dass die verwendete Verschlüsselungssuite manchmal TLS_DHE _... und manchmal TLS_ECDHE _.... ist. Letzteres würde passieren, wenn ich BouncyCastle hinzufüge. Wenn TLS_ECDHE_ ausgewählt wurde, funktionierte es die meiste Zeit, aber nicht IMMER. Daher war das Hinzufügen eines BouncyCastle-Anbieters unzuverlässig (fehlgeschlagen mit demselben Fehler, jedes zweite Mal oder so). Ich denke, irgendwo in der Sun SSL-Implementierung wird manchmal DHE gewählt , manchmal ECDHE .

Die hier veröffentlichte Lösung basiert also auf dem vollständigen Entfernen der TLS_DHE_-Chiffren. HINWEIS: BouncyCastle ist für die Lösung NICHT erforderlich.

Erstellen Sie die Serverzertifizierungsdatei wie folgt:

echo |openssl s_client -connect example.org:443 2>&1 |sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'

Speichern Sie dies, da später darauf verwiesen wird. Hier ist die Lösung für ein SSL-http-Get, mit Ausnahme der TLS_DHE_-Verschlüsselungssuiten.

package org.example.security;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import org.apache.log4j.Logger;

public class SSLExcludeCipherConnectionHelper {

    private Logger logger = Logger.getLogger(SSLExcludeCipherConnectionHelper.class);

    private String[] exludedCipherSuites = {"_DHE_","_DH_"};

    private String trustCert = null;

    private TrustManagerFactory tmf;

    public void setExludedCipherSuites(String[] exludedCipherSuites) {
        this.exludedCipherSuites = exludedCipherSuites;
    }

    public SSLExcludeCipherConnectionHelper(String trustCert) {
        super();
        this.trustCert = trustCert;
        //Security.addProvider(new BouncyCastleProvider());
        try {
            this.initTrustManager();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void initTrustManager() throws Exception {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = new BufferedInputStream(new FileInputStream(trustCert));
        Certificate ca = null;
        try {
            ca = cf.generateCertificate(caInput);
            logger.debug("ca=" + ((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
        }

        // Create a KeyStore containing our trusted CAs
        KeyStore keyStore = KeyStore.getInstance("jks");
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);
    }

    public String get(URL url) throws Exception {
        // Create an SSLContext that uses our TrustManager
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, tmf.getTrustManagers(), null);
        SSLParameters params = context.getSupportedSSLParameters();
        List<String> enabledCiphers = new ArrayList<String>();
        for (String cipher : params.getCipherSuites()) {
            boolean exclude = false;
            if (exludedCipherSuites != null) {
                for (int i=0; i<exludedCipherSuites.length && !exclude; i++) {
                    exclude = cipher.indexOf(exludedCipherSuites[i]) >= 0;
                }
            }
            if (!exclude) {
                enabledCiphers.add(cipher);
            }
        }
        String[] cArray = new String[enabledCiphers.size()];
        enabledCiphers.toArray(cArray);

        // Tell the URLConnection to use a SocketFactory from our SSLContext
        HttpsURLConnection urlConnection =
            (HttpsURLConnection)url.openConnection();
        SSLSocketFactory sf = context.getSocketFactory();
        sf = new DOSSLSocketFactory(sf, cArray);
        urlConnection.setSSLSocketFactory(sf);
        BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
        String inputLine;
        StringBuffer buffer = new StringBuffer();
        while ((inputLine = in.readLine()) != null) 
            buffer.append(inputLine);
        in.close();

        return buffer.toString();
    }

    private class DOSSLSocketFactory extends javax.net.ssl.SSLSocketFactory {

        private SSLSocketFactory sf = null;
        private String[] enabledCiphers = null;

        private DOSSLSocketFactory(SSLSocketFactory sf, String[] enabledCiphers) {
            super();
            this.sf = sf;
            this.enabledCiphers = enabledCiphers;
        }

        private Socket getSocketWithEnabledCiphers(Socket socket) {
            if (enabledCiphers != null && socket != null && socket instanceof SSLSocket)
                ((SSLSocket)socket).setEnabledCipherSuites(enabledCiphers);

            return socket;
        }

        @Override
        public Socket createSocket(Socket s, String host, int port,
                boolean autoClose) throws IOException {
            return getSocketWithEnabledCiphers(sf.createSocket(s, host, port, autoClose));
        }

        @Override
        public String[] getDefaultCipherSuites() {
            return sf.getDefaultCipherSuites();
        }

        @Override
        public String[] getSupportedCipherSuites() {
            if (enabledCiphers == null)
                return sf.getSupportedCipherSuites();
            else
                return enabledCiphers;
        }

        @Override
        public Socket createSocket(String host, int port) throws IOException,
                UnknownHostException {
            return getSocketWithEnabledCiphers(sf.createSocket(host, port));
        }

        @Override
        public Socket createSocket(InetAddress address, int port)
                throws IOException {
            return getSocketWithEnabledCiphers(sf.createSocket(address, port));
        }

        @Override
        public Socket createSocket(String host, int port, InetAddress localAddress,
                int localPort) throws IOException, UnknownHostException {
            return getSocketWithEnabledCiphers(sf.createSocket(host, port, localAddress, localPort));
        }

        @Override
        public Socket createSocket(InetAddress address, int port,
                InetAddress localaddress, int localport) throws IOException {
            return getSocketWithEnabledCiphers(sf.createSocket(address, port, localaddress, localport));
        }

    }
}

Schließlich wird Folgendes verwendet (certFilePath, wenn der Pfad des Zertifikats von openssl gespeichert wurde):

try {
            URL url = new URL("https://www.example.org?q=somedata");            
            SSLExcludeCipherConnectionHelper sslExclHelper = new SSLExcludeCipherConnectionHelper(certFilePath);
            logger.debug(
                    sslExclHelper.get(url)
            );
        } catch (Exception ex) {
            ex.printStackTrace();
        }
Zsozso
quelle
9
Testen Sie einfach Ihre Lösung. Es funktioniert wie beabsichtigt. Vielen Dank. Eigentlich nur das Hinzufügen jdk.tls.disabledAlgorithms=DHE, ECDHEin JDK_HOME/jre/lib/security/java.securityfunktioniert auch und vermeiden Sie alle diesen Code.
Ludovic Guillaume
3
Das Deaktivieren von DHE hat bei mir funktioniert : jdk.tls.disabledAlgorithms=DHE. Verwenden von 1.7.0_85-b15.
stephan f
1
Jdk.tls.disabledAlgorithms = DHE, ECDHE in JDK_HOME / jre / lib / security / java.security hinzugefügt und gut funktioniert! Danke dir! Verwenden von 1.7.0_79
Eric Na
1
Deaktivieren Sie ECDHE nicht. Es ist anders als DHE und verwendet nicht einmal Primzahlen.
Kubanczyk
1
Kann mir bitte jemand sagen, wie ich den 'certFilePath' bekommen kann. Ich bin seit einer Woche dabei. @ Zsozso
user1172490
13

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

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

Dies wird auch in einem Forum-Thread besprochen, den ich gefunden habe und in dem keine Lösung erwähnt wird. 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 damit überhaupt nicht zufrieden bin. Die Lösung besteht darin, es so einzustellen, dass der Diffie-Hellman-Algorithmus überhaupt nicht verfügbar ist. Angenommen, der Server unterstützt einen alternativen Algorithmus, wird er während der normalen Aushandlung ausgewählt. Der Nachteil dabei ist natürlich, dass wenn es jemandem irgendwie gelingt, einen Server zu finden, der Diffie-Hellman nur mit 1024 Bit oder weniger unterstützt, dies tatsächlich bedeutet, dass er nicht dort funktioniert, wo er früher funktioniert hat.

Hier ist Code, der mit 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.

Sam
quelle
1
Schade, dass dies der einzige Weg ist :(. Dieses Ticket ist seit '07 geöffnet. Seltsam, dass in 4 Jahren nichts dagegen unternommen wurde.
Vivin Paliath
Ich bin neu in Java Securities. Bitte helfen Sie, wo soll ich diesen Code schreiben?
Shashank
Ich habe jede Lösung in diesem Thread ausprobiert und dies war die einzige, die mit meinem ibm jvm (ibm-java-s390x-60) funktioniert hat.
Gianluca Greco
@ Sam, Was ist eine Variable in ((SSLSocket) s)?
Mostafa
13

Sie können DHE in Ihrem JDK vollständig deaktivieren, jre / lib / security / java.security bearbeiten und sicherstellen, dass DHE deaktiviert ist, z. mögen

jdk.tls.disabledAlgorithms=SSLv3, DHE.

Tor
quelle
4
Dies ist nur in JDK 1.7 und höher verfügbar. link
hoangthienan
Das Problem für mich gelöst JDK 1.8.0_144-b01
MrSmith42
12

Sie können den Anbieter dynamisch installieren:

1) Laden Sie diese Gläser herunter:

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

2) Kopieren Sie Gläser in WEB-INF/lib(oder Ihren Klassenpfad)

3) Anbieter dynamisch hinzufügen:

import org.bouncycastle.jce.provider.BouncyCastleProvider;

...

Security.addProvider(new BouncyCastleProvider());

Engelskorral
quelle
Diese Lösung funktioniert gut und passt gut zu meinem Fall, da ich die Änderungen nur auf Projektebene und nicht auf Server- / Umgebungsebene vornehmen wollte. Danke
ishanbakshi
Vielen Dank! das hat bei mir funktioniert. In meinem Fall war es der nächste Import von bcp 1.4, der dazu führte, dass E-Mails bei Google fehlschlugen.
Japheth Ongeri - Inkalimeva
Ich erhalte javax.net.ssl.SSLHandshakeException: Nicht unterstützte Kurven-ID: 29 mit Java-Version 1.6.0_27
Ein weiterer Codierer
6

Wenn Sie jdk1.7.0_04 verwenden, aktualisieren Sie auf jdk1.7.0_21. Das Problem wurde in diesem Update behoben.

Lekkie
quelle
2
Ich habe gerade das Java SE Development Kit 7u25 heruntergeladen und laut dem kleinen Programm, das ich geschrieben habe, um die maximal unterstützte DH-Größe zu bestimmen , ist es immer noch 1024.
user2666524
1
Problem besteht immer noch mit JDK 1.7.0_25
Sébastien Vanmechelen
Das Aktualisieren hat für mich funktioniert. Hatte 6.22 auf 7.59 aktualisiert. Problem gelöst.
Elazaron
1
@Shashank - Ein Upgrade auf JDK 1.8.0_73 hat bei mir funktioniert.
dgoverde
DHKeyPairs mit Bitlängen größer als 1024 wurden von JDK 1.7.0_91 eingeführt, sind jedoch nicht öffentlich verfügbar.
Ein weiterer Codierer
6

Möglicherweise haben Sie falsche Maven-Abhängigkeiten. Sie müssen diese Bibliotheken in der Maven-Abhängigkeitshierarchie finden:

bcprov-jdk14, bcpkix-jdk14, bcmail-jdk14

Wenn Sie diese Abhängigkeiten haben, ist dies der Fehler, und Sie sollten dies tun:

Fügen Sie die Abhängigkeit hinzu:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcmail-jdk15on</artifactId>
    <version>1.59</version>
</dependency>

Schließen Sie diese Abhängigkeiten von dem Artefakt aus, das die falschen Abhängigkeiten enthielt. In meinem Fall ist dies:

<dependency>
    <groupId>com.lowagie</groupId>
    <artifactId>itext</artifactId>
    <version>2.1.7</version>
    <exclusions>
        <exclusion>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bctsp-jdk14</artifactId>                
        </exclusion>
        <exclusion>
            <groupId>bouncycastle</groupId>
            <artifactId>bcprov-jdk14</artifactId>               
        </exclusion>
        <exclusion>
            <groupId>bouncycastle</groupId>
            <artifactId>bcmail-jdk14</artifactId>               
        </exclusion>
    </exclusions>       
</dependency>
Jose Antonio Sánchez Pujante
quelle
Die Frage hat bereits viele Antworten erhalten und hat eine validierte Antwort. Darüber hinaus wurde die Frage vor mehr als 6 Jahren gestellt. Ich bin mir nicht sicher, ob es noch relevant ist.
David Guyon
5

Versuchen Sie, "JCE-Richtliniendateien (Java Cryptography Extension) mit unbegrenzter Stärke" von der Java-Download-Site herunterzuladen und die Dateien in Ihrer JRE zu ersetzen.

Dies funktionierte für mich und ich musste nicht einmal BouncyCastle verwenden - der Standard Sun JCE konnte eine Verbindung zum Server herstellen.

PS. Ich habe den gleichen Fehler (ArrayIndexOutOfBoundsException: 64) erhalten, als ich versucht habe, BouncyCastle zu verwenden, bevor ich die Richtliniendateien geändert habe. Daher scheint unsere Situation sehr ähnlich zu sein.

mjomble
quelle
Hast du noch etwas getan? oder einfach die 2 Dateien in den Ordner kopiert?
Joergi
Es ist eine Weile her, aber soweit ich mich erinnere, war das alles, was ich tun musste. Abgesehen davon, dass alle laufenden Java-Prozesse anschließend neu gestartet werden.
Mjomble
5

Wenn Sie immer noch von diesem Problem betroffen sind UND Apache httpd v> 2.4.7 verwenden, versuchen Sie Folgendes: http://httpd.apache.org/docs/current/ssl/ssl_faq.html#javadh

von der URL kopiert :

Ab Version 2.4.7 verwendet mod_ssl DH-Parameter, die Primzahlen mit einer Länge von mehr als 1024 Bit enthalten. Java 7 und frühere Versionen beschränken ihre Unterstützung für DH-Primgrößen jedoch auf maximal 1024 Bit.

Wenn Ihr Java-basierter Client mit Ausnahmen wie java.lang.RuntimeException abbricht: DH-Schlüsselpaar und java.security.InvalidAlgorithmParameterException konnten nicht generiert werden: Die Prime-Größe muss ein Vielfaches von 64 sein und kann nur zwischen 512 und 1024 (einschließlich) und liegen httpd protokolliert den internen tlsv1-Alarmfehler (SSL-Alarmnummer 80) (bei LogLevel-Informationen oder höher). Sie können entweder die Verschlüsselungsliste von mod_ssl mit SSLCipherSuite (möglicherweise in Verbindung mit SSLHonorCipherOrder) neu anordnen oder benutzerdefinierte DH-Parameter mit einer 1024-Bit-Primzahl verwenden , die immer Vorrang vor den integrierten DH-Parametern haben.

Verwenden Sie die, um benutzerdefinierte DH-Parameter zu generieren

openssl dhparam 1024

Befehl. Alternativ können Sie die folgenden Standard-1024-Bit-DH-Parameter aus RFC 2409, Abschnitt 6.2 verwenden:

-----BEGIN DH PARAMETERS-----
MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR
Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL
/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC
-----END DH PARAMETERS-----

Fügen Sie die benutzerdefinierten Parameter einschließlich der Zeilen "BEGIN DH PARAMETERS" und "END DH PARAMETERS" am Ende der ersten Zertifikatdatei hinzu, die Sie mit der Anweisung SSLCertificateFile konfiguriert haben.


Ich verwende Java 1.6 auf der Clientseite und es hat mein Problem gelöst. Ich habe die Cipher Suites oder ähnliches nicht abgesenkt, sondern der Zertifizierungsdatei einen benutzerdefinierten generierten DH-Parameter hinzugefügt.

pka
quelle
Beachten Sie, dass jetzt angenommen wird, dass 1024-Bit-DH rechnerisch machbar (wenn auch höllisch teuer) ist.
Plugwash
2

Ich habe das gleiche Problem mit Yandex Maps Server, JDK 1.6 und Apache HttpClient 4.2.1. Der Fehler war

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

Bei aktiviertem Debugging -Djavax.net.debug=all gab es eine Meldung in einem Protokoll

Could not generate DH keypair

Ich habe dieses Problem behoben, indem ich die BouncyCastle-Bibliothek hinzugefügt bcprov-jdk16-1.46.jarund einen Anbieter in einer Kartendienstklasse registriert habe

public class MapService {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public GeocodeResult geocode() {

    }

}

Ein Anbieter wird bei der ersten Nutzung von registriert MapService.

v.ladynev
quelle
2

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, um mit JDK 6 koexistieren zu können, aber es stellt sich heraus, dass lediglich das neuere JDK mit installiert wird rpm -i nicht ausreichte.

Die JDK 7-Installation würde nur mit dem erfolgreich sein rpm -U unten dargestellten Upgrade-Option 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. RPM-Upgrade 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)
Saheed
quelle
1

Das Problem wurde durch ein Upgrade auf JDK 8 behoben.

anre
quelle
1

Ich verwende ColdFusion 8 unter JDK 1.6.45 und hatte Probleme, mir nur rote Kreuze anstelle von Bildern zu geben, und auch, dass cfhttp mit ssl keine Verbindung zum lokalen Webserver herstellen konnte.

Mein Testskript zur Reproduktion mit ColdFusion 8 war

<CFHTTP URL="https://www.onlineumfragen.com" METHOD="get" ></CFHTTP>
<CFDUMP VAR="#CFHTTP#">

Dies gab mir den ziemlich allgemeinen Fehler "E / A-Ausnahme: Peer nicht authentifiziert". Ich habe dann versucht, dem Java-Keystore und auch dem Coldfusion-Keystore Zertifikate des Servers einschließlich Root- und Zwischenzertifikaten hinzuzufügen, aber nichts hat geholfen. dann habe ich das problem mit debuggt

java SSLPoke www.onlineumfragen.com 443

und bekam

javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair

und

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:107)
    ... 10 more

Ich hatte dann die Idee, dass der Webserver (in meinem Fall Apache) sehr moderne Chiffren für SSL hat und ziemlich restriktiv ist (Qualys Score a +) und starke Diffie-Hellmann-Schlüssel mit mehr als 1024 Bit verwendet. Offensichtlich können ColdFusion und Java JDK 1.6.45 dies nicht schaffen. Der nächste Schritt auf dem Odyssee war die Installation eines alternativen Sicherheitsanbieters für Java, und ich entschied mich für eine Hüpfburg. siehe auch http://www.itcsolutions.eu/2011/08/22/how-to-use-bouncy-castle-cryptographic-api-in-netbeans-or-eclipse-for-java-jse-projects/

Ich habe dann die heruntergeladen

bcprov-ext-jdk15on-156.jar

von http://www.bouncycastle.org/latest_releases.html und installiert es unter C: \ jdk6_45 \ jre \ lib \ ext oder wo immer sich Ihr JDK befindet, in der ursprünglichen Installation von ColdFusion 8 wäre es unter C: \ JRun4 \ jre \ lib \ ext, aber ich verwende ein neueres jdk (1.6.45) außerhalb des ColdFusion-Verzeichnisses. Es ist sehr wichtig, die Datei bcprov-ext-jdk15on-156.jar im Verzeichnis \ ext abzulegen (dies hat mich ungefähr zwei Stunden und einige Haare gekostet ;-). Dann habe ich die Datei C: \ jdk6_45 \ jre \ lib \ security \ bearbeitet java.security (mit wordpad nicht mit editor.exe!) und in eine Zeile für den neuen Anbieter setzen. danach sah die Liste so aus

#
# List of providers and their preference orders (see above):
#
security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=sun.security.mscapi.SunMSCAPI

(siehe den neuen in Position 1)

Starten Sie dann den ColdFusion-Dienst vollständig neu. du kannst dann

java SSLPoke www.onlineumfragen.com 443 (or of course your url!)

und genieße das Gefühl ... und natürlich

Was für eine Nacht und was für ein Tag. Hoffentlich hilft dies jemandem (teilweise oder vollständig) da draußen. Wenn Sie Fragen haben, senden Sie mir einfach eine E-Mail an info ... (Domain oben).

Raffael Meier
quelle
0

Wenn der Server eine Verschlüsselung ohne DH unterstützt, können Sie den Client zwingen, diese Verschlüsselung 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 zu Brüchen führen kann.

Jason Martin
quelle
0

Wir haben genau den gleichen Ausnahmefehler erhalten, der nach stundenlangem Surfen im Internet leicht zu beheben war.

Wir haben die höchste Version von jdk heruntergeladen, die wir auf oracle.com finden konnten, sie installiert und den Jboss-Anwendungsserver auf das Verzeichnis des installierten neuen jdk verwiesen.

Jboss neu gestartet, wiederaufbereitet, Problem behoben !!!

Peter Azuka Molokwu
quelle
0

Ich habe diesen Fehler mit Bamboo 5.7 + Gradle-Projekt + Apache. Gradle hat versucht, einige Abhängigkeiten von einem unserer Server über SSL abzurufen.

Lösung:

  1. DH Param generieren:

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 Zertifikatdatei SSLCertificateFileanhängen (für Apache - param)

  2. Starten Sie Apache neu

  3. Starten Sie Bamboo neu

  4. Versuchen Sie erneut, ein Projekt zu erstellen

Evgeny Lebedev
quelle
0

Ich habe einen ähnlichen Fehler beim Zugriff auf svn.apache.org mit Java-SVN-Clients unter Verwendung eines IBM JDK erhalten. Derzeit verwendet svn.apache.org die Verschlüsselungseinstellungen der Clients.

Nachdem ich nur einmal mit einem Paket Capture / javax.net.debug = ALL ausgeführt hatte, konnte ich nur eine einzige DHE-Verschlüsselung auf die schwarze Liste setzen und die Dinge funktionieren für mich (ECDHE wird stattdessen ausgehandelt).

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

Eine schöne schnelle Lösung, wenn es nicht einfach ist, den Client zu wechseln.

Covener
quelle
0

Vor kurzem habe ich das gleiche Problem und nach dem Upgrade der JDK-Version von 1.6.0_45 auf JDK1.7.0_191, wodurch das Problem behoben wurde.

Sam
quelle
-1

Für mich hat die folgende Befehlszeile das Problem behoben:

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

Ich verwende JDK 1.7.0_79

rico-chango
quelle
1
Ich war mit JDK 1.7.0_xx in der gleichen Situation. Das Standardproblem wird nach Verwendung von jdk 1.8 behoben. Aber manchmal können wir JDK nicht schnell aktualisieren. Mein Problem wurde nach dem Hinzufügen der Systemkonfiguration behoben: System.setProperty ("https.protocols", "TLSv1.2"); System.setProperty ("deploy.security.TLSv1.2", "true");
Ramgau