wake-up-neo.com

Importiertes Zertifikat in Java-Keystore, JVM ignoriert das neue Zertifikat

Ich versuche, eine Anwendung auf Tomcat 6 auszuführen, um eine Verbindung zu einem LDAP-Server über SSL herzustellen.

Ich habe ein Zertifikat des Servers in den Keystore importiert:

C:\Program Files\Java\jdk1.6.0_32\jre\lib\security>keytool -importcert -trustcacerts -file mycert -alias ca_alias -keystore "c:\Program Files\Java\jdk1.6.0_32\jre\lib\security\cacerts"

Wenn ich Tomcat mit aktiviertem SSL-Debugging starte, verwendet Tomcat laut Protokollen die richtige Zertifikatsdatei:

trustStore is: C:\Program Files\Java\jdk1.6.0_32\jre\lib\security\cacerts

Tomcat fügt jedoch das soeben importierte Zertifikat nicht hinzu. Alle anderen Zertifikate in der Cacerts-Datei werden in das Protokoll geschrieben - und die Verbindung schlägt fehl:

handling exception: javax.net.ssl.SSLHandshakeException: Sun.security.validator.ValidatorException: PKIX path building failed: Sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Der Neustart von Tomcat hilft nicht. Ich habe mit dem Befehl keytool -list überprüft, ob das neue Zertifikat tatsächlich in der Datei vorhanden ist.

Warum ignoriert Tomcat mein neues Zertifikat immer noch?

BEARBEITEN:

Scheint, dass das Problem von Windows 7 VirtualStore verursacht wurde. Keytool hat eine neue Kopie der Cacert-Datei erstellt, und Tomcat hat die Originaldatei verwendet.

18
tputkonen

Die JVM muss nach dem Import der Zertifikate in den Keystore neu gestartet werden.

16
SSLKida

Prüfen Sie, ob es einen Schlüssel mit denselben CN-Informationen, aber einem anderen Alias ​​gibt.

Ich hatte zuvor ähnliche Probleme, als ich versuchte, eine neuere Version eines Zertifikats zu importieren, die ältere Version jedoch im Keystore belassen. Meine Java-Programme würden einfach den ersten passenden CN-Schlüssel im Keystore (der alte abgelaufene) gefunden und versucht, diesen zu verwenden, obwohl es einen neueren gab, der auch dem CN entsprach.

Stellen Sie außerdem sicher, dass das authentifizierende Stammzertifikat (und ggf. das Zwischenzertifikat) im Keystore vorhanden ist. Wenn Sie sich bei einem der wichtigsten Sicherheitsanbieter wie Verisign oder Globalsign authentifizieren, erhalten Sie normalerweise Stamm- und Zwischenzertifikate. Wenn diese Zertifikate bereits im Keystore vorhanden sind, stellen Sie sicher, dass sie noch gültig sind. Sie müssen alle Zertifikate Ihres persönlichen Zertifikats über die gesamte Authentifizierungskette bis zum Stamm, der in Ihrem Keystore vorhanden ist, haben, damit er Ihre Anmeldeinformationen überprüfen kann.

5
wattostudios

Was Sie beschrieben haben, ist genau das, was ich erhalten habe, wenn Sie cmd.exe und einen normalen Benutzer verwenden, obwohl er Mitglied einer administrativen Gruppe auf einem Windows Server ist. Sie müssen cmd.exe im Verwaltungsmodus starten, um die Änderungen in cacerts-Dateien zu übernehmen. Zumindest auf den Win2k8-Betriebssystemen. 

Wenn Sie dies nicht tun, werden Ihnen die Carets in der keytool.exe -list-Ansicht die neu hinzugefügten Zertifikate zeigen, aber Tomcat sieht sie nicht. Ich weiß nicht warum. Wenn Sie es jedoch mit cmd.exe als Administrator hinzufügen, ist Tomcat mit den neu hinzugefügten Zertifikaten in Ordnung.

Sie können auch Djavax.net.debug="ssl,handshake" verwenden, um zu sehen, was Tomcat aus der cacerts-Datei liest.

2
jturunen

In meinem Fall habe ich so viele Dinge durchgesehen, bevor ich herausfand, was falsch war. Ich fügte das Zertifikat verschiedenen Schlüsselspeichern hinzu. Ich fügte alle Zertifikate in der Kette hinzu (was sinnlos ist), ich lud das cert erneut für meinen eigenen Verstand herunter und überprüfte die Seriennummer und überprüfte sogar das heruntergeladene Zertifikat, um sicherzustellen, dass alle korrekten Informationen vorhanden waren.

Am Ende schrieb ich eine TLS-Überprüfungs-Client-App, um das Problem zu beheben. Der Remote-Server, mit dem ich mich verband, unterstützte nicht nur TLS 1.2 (in meiner Version von Java 7 standardmäßig deaktiviert), der Server unterstützte auch keine der in meinem Client aktivierten Verschlüsselungscodes. Es stellte sich heraus, dass in Java 7 weniger als die Hälfte der unterstützten Verschlüsselungen aktiviert war. Viele davon waren wirklich unsicher und einige der sichersten wurden deaktiviert.

Nach einigem Abgleich habe ich die folgende geordnete Liste von TLS 1.2-unterstützten sicheren Chiffren gefunden:

new String[] {
    "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
    "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
    "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
    "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
    "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
    "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
    "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
    "TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384",
    "TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256",
    "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
    "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
    "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",
    "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",
    "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
    "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
    "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
    "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
    "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
    "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
    "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
    "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
    "TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256",
    "TLS_DHE_RSA_WITH_AES_256_CCM",
    "TLS_DHE_RSA_WITH_AES_128_CCM",
    "TLS_DHE_PSK_WITH_AES_256_CCM",
    "TLS_DHE_PSK_WITH_AES_128_CCM",
    "TLS_CHACHA20_POLY1305_SHA256",
    "TLS_AES_256_GCM_SHA384",
    "TLS_AES_128_GCM_SHA256",
    "TLS_AES_128_CCM_SHA256"
}

Wenn es Krypto-Experten gibt, können Sie diese Liste aktualisieren. Ich habe Qualys SSL Labs , diese Information Security SE-Antwort und IANA als meine Quellen verwendet.

Für diejenigen, die ein Beispiel des verwendeten Quellcodes benötigen, siehe unten. Ich habe Apache Commons HttpClient 3.0 verwendet, daher müssen Sie wahrscheinlich die folgenden Binärdateien herunterladen:

TLS12SocketFactory.Java

import Java.io.*;
import Java.net.*;
import Java.util.*;
import org.Apache.commons.httpclient.params.HttpConnectionParams;
import org.Apache.commons.httpclient.protocol.*;
import org.Apache.commons.lang.StringUtils;

public class TLS12SocketFactory implements SecureProtocolSocketFactory {

        private final SecureProtocolSocketFactory base;
        public TLS12SocketFactory()
        {
            this.base = (SecureProtocolSocketFactory)Protocol.getProtocol("https").getSocketFactory();
        }
        private Socket acceptOnlyTLS12(Socket socket)
        {
            if(socket instanceof javax.net.ssl.SSLSocket) {
                final javax.net.ssl.SSLSocket s = (javax.net.ssl.SSLSocket)socket;

                // Set TLS 1.2
                s.setEnabledProtocols(new String[]{ "TLSv1.2" });

                // Using recommended ciphers from https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#table-tls-parameters-4
                List<String> recommended = new ArrayList(Arrays.asList(new String[]{ "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256", "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384", "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256", "TLS_DHE_RSA_WITH_AES_256_CCM", "TLS_DHE_RSA_WITH_AES_128_CCM", "TLS_DHE_PSK_WITH_AES_256_CCM", "TLS_DHE_PSK_WITH_AES_128_CCM", "TLS_CHACHA20_POLY1305_SHA256", "TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256", "TLS_AES_128_CCM_SHA256" }));
                recommended.retainAll(Arrays.asList(s.getSupportedCipherSuites()));
                if(recommended.size() == 0) {
                    System.err.println("No supported modern ciphers. Update crypto policy or install JCE Unlimited Strength Jurisdiction Policy files." + System.lineSeparator());
                } else if(recommended.size() < 3) {
                    System.out.println("Few supported modern ciphers. It's recommended to update crypto policy or install JCE Unlimited Strength Jurisdiction Policy files." + System.lineSeparator());
                }
                s.setEnabledCipherSuites(recommended.toArray(new String[0]));

                // Log matched cipher and cert
                s.addHandshakeCompletedListener(new javax.net.ssl.HandshakeCompletedListener() {
                    @Override
                    public void handshakeCompleted(javax.net.ssl.HandshakeCompletedEvent hce) {
                        String print = s.getInetAddress().getHostName() + System.lineSeparator() + hce.getCipherSuite() + System.lineSeparator();
                        try {
                            for(Java.security.cert.Certificate cert : hce.getPeerCertificates()) {
                                List<String> certStrings = Arrays.asList(cert.toString().split("\r?\n"));
                                for(int line = 0; line < certStrings.size(); line++) {
                                    if(certStrings.get(line).startsWith("Certificate Extensions:")) {
                                        print += System.lineSeparator() + StringUtils.join(certStrings.subList(2, line-1), System.lineSeparator()) + System.lineSeparator();
                                        break;
                                    }
                                }
                            }
                        } catch (javax.net.ssl.SSLPeerUnverifiedException ex) {
                            print += "Non-certificate based cipher used" + System.lineSeparator();
                        }
                        System.out.println(print);
                    }
                });
            }
            return socket;
        }

        @Override
        public Socket createSocket(String Host, int port) throws IOException
        {
            return acceptOnlyTLS12(base.createSocket(Host, port));
        }
        @Override
        public Socket createSocket(String Host, int port, InetAddress localAddress, int localPort) throws IOException
        {
            return acceptOnlyTLS12(base.createSocket(Host, port, localAddress, localPort));
        }
        @Override
        public Socket createSocket(String Host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException
        {
            return acceptOnlyTLS12(base.createSocket(Host, port, localAddress, localPort, params));
        }
        @Override
        public Socket createSocket(Socket socket, String Host, int port, boolean autoClose) throws IOException
        {
            return acceptOnlyTLS12(base.createSocket(socket, Host, port, autoClose));
        }
}

Main.Java

import Java.io.*;
import Java.security.*;
import Java.security.cert.*;
import Java.util.*;
import org.Apache.commons.httpclient.protocol.Protocol;
import org.Apache.commons.httpclient.*;
import org.Apache.commons.httpclient.cookie.CookiePolicy;
import org.Apache.commons.httpclient.methods.*;
import org.Apache.commons.httpclient.params.HttpClientParams;

public class Main {
    public static void main(String[] args) {
        List<Java.net.URI> locations = new ArrayList<>();
        for(String arg : args) {
            Java.net.URI location = Java.net.URI.create(arg);
            if(location.isAbsolute() && location.getScheme().equals("https")) {
                locations.add(location);
            } else {
                System.out.println("Skipping invalid URL: " + arg);
            }
        }
        System.out.println("Connecting to URL's");
        System.out.println();
        System.out.println("-------------------------");

        TLS12SocketFactory tls12factory = new TLS12SocketFactory();
        Protocol.registerProtocol("httpss", new Protocol("httpss", tls12factory, 443));
        for(Java.net.URI location : locations) {
            System.out.println();
            try {
                // Form request
                String tls12url = location.toString().replaceFirst("^https:", "httpss:");
                HttpMethod method = new HeadMethod(tls12url);

                // Send request
                HttpClientParams params = new HttpClientParams();
                params.setParameter(HttpClientParams.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES);
                new HttpClient(params).executeMethod(method);
                method.setFollowRedirects(true);

                // Print response
                System.out.println(location.toString());
                System.out.println(method.getStatusLine().toString());
            } catch (javax.net.ssl.SSLHandshakeException ex) {
                System.out.println("There was an error making a secure connection to " + location.getHost());
                ex.printStackTrace(System.out);
            } catch (HttpException ex) {
                System.out.println("There was an error with the external webpage");
                ex.printStackTrace(System.out);
            } catch (Exception ex) {
                System.out.println("Could not complete request");
                ex.printStackTrace(System.out);
            }
        }
        System.out.println();
        System.out.println("-------------------------");
        System.out.println();
        try {
            // Load supported SSL Ciphers
            System.out.println("Supported ciphers");
            System.out.println();
            System.out.println("-------------------------");
            System.out.println();
            javax.net.ssl.SSLSocket socket = (javax.net.ssl.SSLSocket)tls12factory.createSocket("www.google.com", 443);
            for(String cipher : socket.getSupportedCipherSuites()) {
                System.out.println(cipher);
            }
            System.out.println();
            System.out.println("-------------------------");
            System.out.println();

            // Load enabled SSL Ciphers
            System.out.println("Enabled ciphers");
            System.out.println();
            System.out.println("-------------------------");
            System.out.println();
            for(String cipher : socket.getEnabledCipherSuites()) {
                System.out.println(cipher);
            }
            System.out.println();
            System.out.println("-------------------------");
            System.out.println();

            // Load the JDK's cacerts keystore file
            String filename = System.getProperty("Java.home") + "/lib/security/cacerts".replace('/', File.separatorChar);
            System.out.println("Loading keystore");
            System.out.println(filename);
            System.out.println();
            System.out.println("-------------------------");
            System.out.println();
            FileInputStream is = new FileInputStream(filename);
            KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
            String password = "changeit";
            keystore.load(is, password.toCharArray());

            // This class retrieves the most-trusted CAs from the keystore
            PKIXParameters params = new PKIXParameters(keystore);

            // Get the set of trust anchors, which contain the most-trusted CA certificates
            for (TrustAnchor ta : params.getTrustAnchors()) {
                // Print certificate
                System.out.println(ta.getTrustedCert());
            }
        } catch (CertificateException | KeyStoreException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | IOException ex) {
            System.out.println("Could not load keystore");
            ex.printStackTrace(System.out);
        }
    }
}
0
Pluto