Pourquoi la négociation SSL donne-t-elle une exception «Impossible de générer une paire de clés DH»?

142

Lorsque j'établis une connexion SSL avec certains serveurs IRC (mais pas 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 illustrant ce problème est aperture.esper.net:6697 (il s'agit d'un serveur IRC). Un exemple de serveur qui ne présente pas le problème est kornbluth.freenode.net:6697. [Sans surprise, tous les serveurs de chaque réseau partagent le même comportement respectif.]

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

    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 ce dernier startHandshake qui lève l'exception. Et oui, il y a de la magie avec les «trustAllCerts»; ce code force le système SSL à ne pas valider les certificats. (Donc ... pas un problème de cert.)

De toute évidence, une possibilité est que le serveur d'esper est mal configuré, mais j'ai cherché et n'ai trouvé aucune autre référence à 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 s'agit d'une limitation du support SSL par défaut de Java, ou quelque chose. Aucune suggestion?

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 vous pouvez dire pour mon application Java.

Si cela est pertinent, j'utilise OS X 10.6.8, Java version 1.6.0_26.

sam
la source
2
La raison semble être le suivant: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive). Aucune idée de la taille envoyée par le serveur ici, et de ce que la spécification dit à ce sujet.
Paŭlo Ebermann
@ PaŭloEbermann: En fait, vous pouvez voir la taille du serveur utilisée dans la opensslsortie dans la question: "Le chiffrement est DHE-RSA-AES256-SHA, la clé publique du serveur est de 2048 bits". Et 2048> 1024 :-).
sleske
@sleske: pas exactement. Server public key (size)était, et est, la clé du cert. s_clienten 2011 n'a pas montré du tout de clé éphémère; 1.0.2 en 2015 et plus fait Server Temp Keyplusieurs lignes plus haut. Bien qu'un bon serveur doive généralement rendre la taille DHE identique à la taille d'authentification RSA.
dave_thompson_085

Réponses:

117

Le problème est la taille principale. La taille maximale acceptable acceptée par Java est de 1024 bits. Il s'agit d'un problème connu (voir JDK-6521495 ).

Le rapport de bogue que j'ai lié mentionne une solution de contournement utilisant l'implémentation JCE de BouncyCastle. J'espère que cela devrait fonctionner pour vous.

METTRE À JOUR

Cela a été signalé comme le bogue JDK-7044060 et corrigé récemment.

Notez, cependant, que la limite n'a été élevée qu'à 2048 bits. Pour les tailles> 2048 bits, il existe JDK-8072452 - Supprimez la taille principale maximale des clés DH ; le correctif semble être pour 9.

Vivin Paliath
la source
14
+1. Tous ceux qui ont un compte Sun Developer Network, veuillez voter pour ce bogue.
Paŭlo Ebermann le
1
Merci. Cela semble un problème assez sérieux étant donné l'existence de serveurs qui demandent une taille plus grande! :( J'ai essayé BouncyCastle; si vous le configurez comme fournisseur préféré, il se bloque avec une exception différente (soupir), et je ne vois pas de moyen évident de l'utiliser uniquement pour DH. Cependant, j'ai trouvé une solution alternative, que je 'va ajouter comme nouvelle réponse. (Ce n'est pas joli.)
sam
3
Cool. Ce problème a été corrigé dans les nouvelles versions de Java. Mais ma question porte sur l'utilisation d'une version plus ancienne .. Quand j'utilise une version plus ancienne, parfois cela fonctionne et parfois cela donne une exception ci-dessus .. Pourquoi un comportement si aléatoire? Si c'est un bogue en java, alors je suppose que cela ne devrait jamais fonctionner?
N ..
2
Le correctif 2048 a été rétroporté vers IcedTea 2.5.3. Les nouvelles versions d'IcedTea l'ont augmenté à 4096.
fuzzyTew
1
Le problème est la taille DH prime. La taille maximale acceptable acceptée par Java est de 2 048 bits. En attendant qu'Oracle élargisse la limite, vous pouvez compiler avec Excelsior Jet qui a une limite étendue.
user1332994
67

La réponse "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files" n'a pas fonctionné pour moi, mais la suggestion de fournisseur JCE de The BouncyCastle a fonctionné.

Voici les étapes que j'ai suivies en utilisant Java 1.6.0_65-b14-462 sur Mac OSC 10.7.5

1) Téléchargez ces pots:

2) déplacez ces jars vers $ JAVA_HOME / lib / ext

3) modifiez $ JAVA_HOME / lib / security / java.security comme suit: security.provider.1 = org.bouncycastle.jce.provider.BouncyCastleProvider

redémarrez l'application à l'aide de JRE et essayez-la

mjj1409
la source
5
travaille pour moi! mais pas tout à fait sûr de ce que je fais.
Plongez jusqu'au
11
security.provider.2 = org.bouncycastle.jce.provider.BouncyCastleProvider fonctionnait mieux, le mettre sur 1. a entraîné des erreurs dans le logiciel par défaut.
TinusSky
1
Cela fonctionne pour moi aussi, mais j'ai ajouté un fournisseur de manière dynamique. Reffer ma réponse ici pour plus de détails.
v.ladynev
Merci beaucoup, cela a fonctionné pour moi et était nécessaire pour réussir à construire la source Tomcat 7.0.78.
phillipuniverse
@ mjj1409, en Java 1.5, nous n'avons pas le chemin $ JAVA_HOME / lib / security
Mostafa
15

Voici ma solution (java 1.6), je serais également intéressé par la raison pour laquelle je devais faire cela:

J'ai remarqué à partir du javax.security.debug = ssl, que parfois la suite de chiffrement utilisée est TLS_DHE _... et parfois TLS_ECDHE _.... Le plus tard se produirait si j'ajoutais BouncyCastle. Si TLS_ECDHE_ a été sélectionné, la plupart du temps cela a fonctionné, mais pas TOUJOURS, donc l'ajout même du fournisseur BouncyCastle n'était pas fiable (a échoué avec la même erreur, une fois sur deux environ). Je suppose que quelque part dans l'implémentation Sun SSL, il choisit parfois DHE , parfois ECDHE .

La solution publiée ici repose donc sur la suppression complète des chiffrements TLS_DHE_. REMARQUE: BouncyCastle n'est PAS nécessaire pour la solution.

Créez donc le fichier de certification du serveur en:

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

Enregistrez-le car il sera référencé plus tard, car voici la solution pour un http get SSL, à l'exclusion des suites de chiffrement TLS_DHE_.

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

    }
}

Enfin voici comment il est utilisé (certFilePath si le chemin du certificat enregistré depuis openssl):

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
la source
9
Je viens de tester votre solution. Cela fonctionne comme prévu. Merci. En fait, le simple ajout jdk.tls.disabledAlgorithms=DHE, ECDHEdans JDK_HOME/jre/lib/security/java.securityfonctionne aussi et éviter tout ce code.
Ludovic Guillaume
3
Juste la désactivation de DHE a fonctionné pour moi: jdk.tls.disabledAlgorithms=DHE. Utilisation de 1.7.0_85-b15.
stephan f
1
Ajout de jdk.tls.disabledAlgorithms = DHE, ECDHE dans JDK_HOME / jre / lib / security / java.security et a bien fonctionné! Je vous remercie! Utilisation de 1.7.0_79
Eric Na
1
Ne désactivez pas ECDHE. C'est différent de DHE et n'utilise même pas de nombres premiers.
kubanczyk
1
Quelqu'un peut-il s'il vous plaît me dire comment je peux obtenir le «certFilePath». Je suis coincé là-dessus depuis une semaine. @Zsozso
user1172490
13

La réponse ci-dessus est correcte, mais en termes de solution de contournement, j'ai eu des problèmes avec l'implémentation de BouncyCastle lorsque je l'ai définie comme fournisseur préféré:

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

Ceci est également discuté dans un fil de discussion du forum que j'ai trouvé, qui ne mentionne pas de solution. http://www.javakb.com/Uwe/Forum.aspx/java-programmer/47512/TLS-problems

J'ai trouvé une solution alternative qui fonctionne pour mon cas, même si je ne suis pas du tout satisfait. La solution est de le paramétrer de sorte que l'algorithme Diffie-Hellman ne soit pas disponible du tout. Ensuite, en supposant que le serveur prend en charge un algorithme alternatif, il sélectionnera pendant la négociation normale. De toute évidence, l'inconvénient est que si quelqu'un parvient d'une manière ou d'une autre à trouver un serveur qui ne prend en charge Diffie-Hellman qu'à 1024 bits ou moins, cela signifie en fait qu'il ne fonctionnera pas là où il fonctionnait auparavant.

Voici le code qui fonctionne avec un SSLSocket (avant de le connecter):

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

Méchant.

sam
la source
1
Triste que ce soit le seul moyen :(. Ce billet est ouvert depuis '07. Étrange que rien n'ait été fait à ce sujet en 4 ans.
Vivin Paliath
Je suis nouveau sur les valeurs Java. S'il vous plaît aider où dois-je écrire ce morceau de code?
Shashank
J'ai essayé toutes les solutions de ce fil et c'était la seule qui fonctionnait avec mon ibm jvm (ibm-java-s390x-60).
Gianluca Greco
@Sam, Quelle est la variable dans ((SSLSocket) s)?
Mostafa
13

Vous pouvez désactiver complètement DHE dans votre jdk, éditer jre / lib / security / java.security et vous assurer que DHE est désactivé, par exemple. comme

jdk.tls.disabledAlgorithms=SSLv3, DHE.

Tor
la source
4
qui n'est disponible que dans JDK 1.7 et versions ultérieures. lien
hoangthienan
Résolu le problème pour moi JDK 1.8.0_144-b01
MrSmith42
12

Vous pouvez installer le fournisseur de manière dynamique:

1) Téléchargez ces pots:

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

2) Copiez les fichiers jars vers WEB-INF/lib(ou votre chemin de classe)

3) Ajouter un fournisseur dynamiquement:

import org.bouncycastle.jce.provider.BouncyCastleProvider;

...

Security.addProvider(new BouncyCastleProvider());

angelcorral
la source
Cette solution fonctionne bien et correspondait bien à mon cas car je voulais apporter les modifications uniquement au niveau du projet et non au niveau du serveur / environnement. Merci
ishanbakshi
Merci! cela a fonctionné pour moi. Dans mon cas, itext importait bcp 1.4 provoquant l'échec des e-mails de Google.
Japheth Ongeri - inkalimeva
Je reçois javax.net.ssl.SSLHandshakeException: CurveId non pris en charge: 29 avec la version java 1.6.0_27
Un autre codeur
6

Si vous utilisez jdk1.7.0_04, effectuez une mise à niveau vers jdk1.7.0_21. Le problème a été résolu dans cette mise à jour.

Lekkie
la source
2
Je viens de télécharger Java SE Development Kit 7u25, et selon le petit programme que j'ai écrit pour déterminer la taille DH maximale prise en charge , il est toujours de 1024.
user2666524
1
Le problème existe toujours avec JDK 1.7.0_25
Sébastien Vanmechelen
la mise à jour jre a fonctionné pour moi. avait 6.22 mis à jour à 7.59. problème résolu.
Elazaron
1
@Shashank - La mise à niveau vers JDK 1.8.0_73 a fonctionné pour moi.
dgoverde
DHKeyPairs avec des longueurs de bits supérieures à 1024 introduites à partir du JDK 1.7.0_91 mais non disponibles publiquement.
Un autre codeur le
6

Il est possible que vous ayez des dépendances Maven incorrectes. Vous devez trouver ces bibliothèques dans la hiérarchie de dépendances Maven:

bcprov-jdk14, bcpkix-jdk14, bcmail-jdk14

Si vous avez ces dépendances, c'est l'erreur et vous devriez le faire:

Ajoutez la dépendance:

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

Excluez ces dépendances de l'artefact qui incluait les mauvaises dépendances, dans mon cas, c'est:

<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>
José Antonio Sánchez Pujante
la source
La question a déjà reçu de nombreuses réponses et a une réponse validée. De plus, la question a été posée il y a plus de 6 ans. Je ne sais pas si c'est toujours pertinent.
David Guyon
5

Essayez de télécharger «Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files» à partir du site de téléchargement Java et de remplacer les fichiers dans votre JRE.

Cela a fonctionné pour moi et je n'ai même pas eu besoin d'utiliser BouncyCastle - le Sun JCE standard était capable de se connecter au serveur.

PS. J'ai eu la même erreur (ArrayIndexOutOfBoundsException: 64) lorsque j'ai essayé d'utiliser BouncyCastle avant de modifier les fichiers de stratégie, il semble donc que notre situation soit très similaire.

mjomble
la source
avez-vous fait autre chose? ou simplement copié les 2 fichiers dans le dossier?
Joergi
Cela faisait un moment, mais pour autant que je me souvienne, c'était tout ce que j'avais à faire. En plus de redémarrer les processus Java en cours d'exécution par la suite.
mjomble
5

Si vous êtes toujours mordu par ce problème ET que vous utilisez Apache httpd v> 2.4.7, essayez ceci: http://httpd.apache.org/docs/current/ssl/ssl_faq.html#javadh

copié depuis l'url :

À partir de la version 2.4.7, mod_ssl utilisera des paramètres DH qui incluent des nombres premiers avec des longueurs de plus de 1024 bits. Cependant, Java 7 et les versions antérieures limitent leur prise en charge des tailles DH prime à un maximum de 1024 bits.

Si votre client Java abandonne avec des exceptions telles que java.lang.RuntimeException: impossible de générer une paire de clés DH et java.security.InvalidAlgorithmParameterException: la taille principale doit être un multiple de 64 et ne peut varier que de 512 à 1024 (inclus), et httpd enregistre l'erreur interne d'alerte tlsv1 (numéro d'alerte SSL 80) (au niveau des informations LogLevel ou supérieur), vous pouvez soit réorganiser la liste de chiffrement de mod_ssl avec SSLCipherSuite (éventuellement en conjonction avec SSLHonorCipherOrder), soit utiliser des paramètres DH personnalisés avec un premier 1024 bits , qui aura toujours la priorité sur l'un des paramètres DH intégrés.

Pour générer des paramètres DH personnalisés, utilisez le

openssl dhparam 1024

commander. Vous pouvez également utiliser les paramètres DH standard 1024 bits suivants de la RFC 2409, section 6.2:

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

Ajoutez les paramètres personnalisés, y compris les lignes "BEGIN DH PARAMETERS" et "END DH PARAMETERS" à la fin du premier fichier de certificat que vous avez configuré à l'aide de la directive SSLCertificateFile.


J'utilise java 1.6 côté client et cela a résolu mon problème. Je n'ai pas abaissé les suites de chiffrement ou autres, mais j'ai ajouté un paramètre DH personnalisé au fichier cert.

pka
la source
Sachez que l'on pense maintenant que le DH 1024 bits est réalisable sur le plan informatique (bien que extrêmement coûteux) à casser.
plugwash
2

J'ai le même problème avec le serveur Yandex Maps, JDK 1.6 et Apache HttpClient 4.2.1. L'erreur était

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

avec le débogage activé par -Djavax.net.debug=all il y avait un message dans un journal

Could not generate DH keypair

J'ai résolu ce problème en ajoutant la bibliothèque BouncyCastle bcprov-jdk16-1.46.jaret en enregistrant un fournisseur dans une classe de service de carte

public class MapService {

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

    public GeocodeResult geocode() {

    }

}

Un fournisseur est enregistré lors de la première utilisation de MapService.

v.ladynev
la source
2

J'ai rencontré l'erreur SSL sur un serveur CentOS exécutant JDK 6.

Mon plan était d'installer une version supérieure de JDK (JDK 7) pour coexister avec JDK 6, mais il s'avère que simplement installer le nouveau JDK avec rpm -in'était pas suffisant.

L'installation du JDK 7 ne réussirait qu'avec l' rpm -Uoption de mise à niveau comme illustré ci-dessous.

1. Téléchargez le JDK 7

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. L'installation de RPM échoue

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. La mise à niveau du RPM a réussi

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. Confirmez la nouvelle 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
la source
1

Résolution du problème en mettant à niveau vers JDK 8.

anre
la source
1

J'utilise Coldfusion 8 sur JDK 1.6.45 et j'ai eu des problèmes en me donnant juste des croix rouges au lieu d'images, et aussi avec cfhttp incapable de se connecter au serveur Web local avec ssl.

mon script de test à reproduire avec Coldfusion 8 était

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

cela m'a donné l'erreur assez générique de "I / O Exception: peer not authenticated". J'ai ensuite essayé d'ajouter des certificats du serveur, y compris des certificats racine et intermédiaires au keystore java et aussi au keystore Coldfusion, mais rien n'y a aidé. puis j'ai débogué le problème avec

java SSLPoke www.onlineumfragen.com 443

et obtenu

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

et

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

J'ai alors eu l'idée que le serveur web (apache dans mon cas) avait des chiffrements très modernes pour ssl et était assez restrictif (qualys score a +) et utilise de fortes clés différentes de Hellmann avec plus de 1024 bits. évidemment, coldfusion et java jdk 1.6.45 ne peuvent pas gérer cela. La prochaine étape dans l'odysee a été de penser à installer un fournisseur de sécurité alternatif pour java, et j'ai opté pour un château gonflable. voir également http://www.itcsolutions.eu/2011/08/22/how-to-use-bouncy-castle-cryptographic-api-in-netbeans-or-eclipse-for-java-jse-projects/

J'ai ensuite téléchargé le

bcprov-ext-jdk15on-156.jar

à partir de http://www.bouncycastle.org/latest_releases.html et l'a installé sous C: \ jdk6_45 \ jre \ lib \ ext ou où que se trouve votre jdk, dans l'installation d'origine de coldfusion 8, il serait sous C: \ JRun4 \ jre \ lib \ ext mais j'utilise un jdk plus récent (1.6.45) situé en dehors du répertoire coldfusion. il est très important de mettre le bcprov-ext-jdk15on-156.jar dans le répertoire \ ext (cela m'a coûté environ deux heures et quelques cheveux ;-) puis j'ai édité le fichier C: \ jdk6_45 \ jre \ lib \ security \ java.security (avec wordpad pas avec editor.exe!) et mettez en une ligne pour le nouveau fournisseur. après la liste ressemblait à

#
# 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

(voir le nouveau en position 1)

puis redémarrez complètement le service Coldfusion. tu peux alors

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

et profitez de la sensation ... et bien sûr

quelle nuit et quelle journée. Espérons que cela aidera (partiellement ou totalement) quelqu'un là-bas. si vous avez des questions, envoyez-moi un mail à info ... (domaine ci-dessus).

Raffael Meier
la source
0

Si le serveur prend en charge un chiffrement qui n'inclut pas DH, vous pouvez forcer le client à sélectionner ce chiffrement et éviter l'erreur DH. Tel que:

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

Gardez à l'esprit que la spécification d'un chiffre exact est sujette à la rupture à long terme.

Jason Martin
la source
0

Nous avons renvoyé la même erreur d'exception exacte, la réparer était facile après des heures de surf sur Internet.

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

Jboss redémarré, retraité, problème résolu !!!

Peter Azuka Molokwu
la source
0

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

Solution:

  1. Générer DH Param:

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 - SSLCertificateFileparam)

  2. Redémarrez Apache

  3. Redémarrez Bamboo

  4. Essayez à nouveau de créer un projet

Evgeny Lebedev
la source
0

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

Après avoir exécuté une seule fois avec une capture de paquets / javax.net.debug = ALL, j'ai pu mettre sur liste noire un seul chiffrement 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

Une belle solution rapide lorsqu'il n'est pas facile de changer de client.

couvrir
la source
0

Récemment, j'ai le même problème et après la mise à niveau de la version jdk de 1.6.0_45 à jdk1.7.0_191, ce qui a résolu le problème.

Sam
la source
-1

Pour moi, la ligne de commande suivante a résolu le problème:

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

J'utilise JDK 1.7.0_79

rico-chango
la source
1
J'ai fait face à la même situation en utilisant JDK 1.7.0_xx. Par défaut, le problème sera résolu après l'utilisation de jdk 1.8. Mais parfois, nous ne pouvons pas mettre à jour jdk rapidement. Mon problème a donc été résolu après l'ajout de la configuration du système: System.setProperty ("https.protocols", "TLSv1.2"); System.setProperty ("deployment.security.TLSv1.2", "true");
Ramgau