web-dev-qa-db-fra.com

Certificats Java et SSL

J'essaie d'établir une connexion avec un script PHP en Java à l'aide de la couche de socket sécurisée (HTTPS), mais j'ai découvert que pour garantir une sécurité/validité maximale, je dois importer le certificat SSL mon site Web utilise dans mon application ... Quelque chose que je ne sais pas faire.

Si cela peut aider, mon certificat SSL n'est pas auto-signé, mais fourni par StartSSL AND J'utilise Eclipse IDE.

Quelqu'un pourrait-il me diriger dans la bonne direction? i.e. De quels fichiers ai-je besoin, où dois-je les importer et de quel code ai-je besoin en Java, etc.?

10
Andy

J'ai découvert que pour assurer une sécurité/validité maximale, je dois importer le certificat SSL que mon site Web utilise dans mon application.

Vous avez partiellement raison lorsque vous faites cette déclaration. Vous n'avez pas besoin d'importer votre certificat SSL. Il suffit que le certificat StartSSL CA soit importé.

De plus, l'importation d'un certificat dans une application Java n'existe pas. La prise en charge de SSL en Java repose sur le concept de magasin de clés et de magasin de clés de confiance, et non sur un certificat fourni avec votre application. Si vous publiez votre application pour qu'elle soit téléchargée et exécutée par les utilisateurs finaux, vous n'avez pas besoin de publier votre certificat, ni d'ailleurs votre clé privée dans votre application. La clé privée et le certificat associé seraient stockés dans un magasin de clés auquel seul vous pouvez accéder.

Les utilisateurs finaux de votre application s'appuieraient sur la prise en charge de SSL dans le runtime Java, ce qui permettrait à l'application d'établir des connexions SSL avec des sites, une fois le certificat de serveur vérifié. Le runtime Java est livré avec un ensemble de certificats d'autorité de certification par défaut dans un fichier de clés certifiées, et la seule condition requise pour que les connexions SSL soient correctement établies est que le certificat SSL du serveur soit émis par l'une des autorités de certification du fichier de clés certifiées. Les certificats de StartSSL ne sont pas présents dans le magasin de clés de confiance du runtime Java}, au moins à partir de la version 6, et par conséquent:

  • Vous pouvez demander à vos utilisateurs finaux d’importer le certificat StartSSL CA dans le fichier de clés certifiées Java. Les liens utiles peuvent inclure ce fil de discussion StartSSL (seules les 4 premières étapes sont nécessaires pour importer les certificats AC dans un magasin de données de confiance), un projet GitHub , et cet article de blog ; une clause de non-responsabilité - Je n'ai jamais essayé de les utiliser et vous devriez les utiliser à vos risques et périls.
  • Vous pouvez également initialiser votre application avec votre propre fichier de clés certifiées à l'aide des indicateurs de démarrage JVM -Djavax.net.ssl.trustStore=<path_to_truststore> -Djavax.net.ssl.trustStorePassword=<truststore_password> ou exécuter le code suivant avant d'initialiser les connexions SSL:

    System.setProperty("javax.net.ssl.trustStore","<path_to_truststore>");
    System.setProperty("javax.net.ssl.trustStorePassword","<truststore_password>");
    

    Cette approche n'est viable que si votre application est une application Java SE qui n'est pas un applet (ou une application avec des restrictions similaires sur la manière dont le magasin de clés est spécifié).


Il serait également utile de lire la documentation Java keytool .

26
Vineet Reynolds

Apparemment, pour une raison quelconque, les ingénieurs mailgun ne veulent pas nous donner des instructions claires sur la façon de résoudre ce problème. C'est ce que j'ai fait 

Nous exécutons Tomcat8 et nous nous connectons via des services Web jersey à l'API mailgun. J'ai suivi les instructions de cet utilisateur et cela a bien fonctionné. J'espère que ça aide quelqu'un.

Le 1/22, nous avons mis à jour nos certificats SSL car l'infrastructure de l'infrastructure à clé publique de Symantec était sur le point de ne plus être fiable. Certaines versions plus anciennes de Java ne disposent pas de l'autorité de certification "DigiCert Global Root G2".

Il y a plusieurs options:

Importez l’AC "DigiCert Global Root G2" dans votre fichier "cacerts". Mettez à niveau votre JRE au format 8u91 (ou supérieur), qui inclut cette racine. Pour importer le "DigiCert Global Root G2" Vous pouvez télécharger la racine depuis https://www.digicert.com/digicert-root-certificates.htm . Assurez-vous de télécharger le certificat racine correct.

Une fois le certificat téléchargé, vous devrez l'importer avec une commande comme celle-ci:

keytool -import -trustcacerts -keystore/chemin/to/cacerts -storepass changeit -noprompt -alias digicert-global-root-g2 -file /path/to/digicert.crt.Vous devrez définir le chemin d'accès votre fichier de clés Java et l'emplacement du certificat racine que vous avez téléchargé.


Số 1. /path/to/digicert.crt est le fichier que vous venez de télécharger. 2./path/to/cacerts - C'est dans votre chemin JRE. Je "trouve/-name cacerts -print" cela vous aidera à trouver rapidement tous les cacerts Java sur votre système de fichiers. Pour moi, il s’agissait de/usr/lib/jvm/Java-7-openjdk-AMD64/jre/lib/security/cacerts 

2
Will Berger

La méthode suivante charge le magasin de clés par défaut (cacerts), vérifie si un certificat est installé et l'installe sinon. Cela évite d'avoir à exécuter manuellement la commande keystore sur tous les serveurs.

Il suppose que le mot de passe du magasin de clés par défaut (changeit) n’a pas changé, mettez à jour CACERTS_PASSWORD sinon. Notez que la méthode enregistre le fichier de clés après avoir ajouté un certificat. Par conséquent, après avoir été exécuté une fois, le certificat sera définitivement dans le magasin.

import Java.io.File;
import Java.io.FileInputStream;
import Java.io.FileNotFoundException;
import Java.io.FileOutputStream;
import Java.io.IOException;
import Java.io.InputStream;
import Java.net.MalformedURLException;
import Java.net.URL;
import Java.security.KeyStore;
import Java.security.KeyStoreException;
import Java.security.NoSuchAlgorithmException;
import Java.security.cert.Certificate;
import Java.security.cert.CertificateException;
import Java.security.cert.CertificateFactory;

/**
 * Add a certificate to the cacerts keystore if it's not already included
 */
public class SslUtil {
    private static final String CACERTS_PATH = "/lib/security/cacerts";

    // NOTE: DO NOT STORE PASSWORDS IN PLAIN TEXT CODE, LOAD AT RUNTIME FROM A SECURE CONFIG
    // DEFAULT CACERTS PASSWORD IS PROVIDED HERE AS A QUICK, NOT-FOR-PRODUCTION WORKING EXAMPLE
    // ALSO, CHANGE THE DEFAULT CACERTS PASSWORD, AS IT IMPLORES YOU TO!
    private static final String CACERTS_PASSWORD = "changeit";

    /**
     * Add a certificate to the cacerts keystore if it's not already included
     * 
     * @param alias The alias for the certificate, if added
     * @param certInputStream The certificate input stream
     * @throws KeyStoreException
     * @throws NoSuchAlgorithmException
     * @throws CertificateException
     * @throws IOException
     */
    public static void ensureSslCertIsInKeystore(String alias, InputStream certInputStream)
            throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException{
        //get default cacerts file
        final File cacertsFile = new File(System.getProperty("Java.home") + CACERTS_PATH);
        if (!cacertsFile.exists()) {
            throw new FileNotFoundException(cacertsFile.getAbsolutePath());
        }

        //load cacerts keystore
        FileInputStream cacertsIs = new FileInputStream(cacertsFile);
        final KeyStore cacerts = KeyStore.getInstance(KeyStore.getDefaultType());
        cacerts.load(cacertsIs, CACERTS_PASSWORD.toCharArray());
        cacertsIs.close();

        //load certificate from input stream
        final CertificateFactory cf = CertificateFactory.getInstance("X.509");
        final Certificate cert = cf.generateCertificate(certInputStream);
        certInputStream.close();

        //check if cacerts contains the certificate
        if (cacerts.getCertificateAlias(cert) == null) {
            //cacerts doesn't contain the certificate, add it
            cacerts.setCertificateEntry(alias, cert);
            //write the updated cacerts keystore
            FileOutputStream cacertsOs = new FileOutputStream(cacertsFile);
            cacerts.store(cacertsOs, CACERTS_PASSWORD.toCharArray());
            cacertsOs.close();
        }
    }
}

Utilisez-le comme suit:

SslUtil.ensureSslCertIsInKeystore("startssl", new FileInputStream("/path/to/cert.crt"));
1
Shane

J'ai découvert que pour assurer une sécurité/validité maximale, je dois Importer le certificat SSL

Non tu ne le fais pas. Vous n'avez besoin de cette étape que si vos clients n'approuvent pas déjà le signataire du certificat de serveur, ce qui ne se produit que si le certificat de serveur est auto-signé ou signé, par exemple. par une autorité de certification interne.

0
user207421

Jetez un oeil à l'article suivant: http://stilius.net/Java/java_ssl.php Il contient un exemple de code qui peut vous aider si vous essayez d'accéder à votre script à partir de code.

Notez que vous devez soit utiliser les propriétés du système

javax.net.ssl.keyStore
javax.net.ssl.keyStorePassword

passer le certificat SSL à la machine virtuelle Java ou l'importer dans le magasin de clés JRE à l'aide de keytool tool

0
Sergey