it-swarm.com.de

Wie kann ich eine Verbindung zu einer sicheren Website mit SSL in Java mit einer pkcs12-Datei herstellen?

Ich habe eine pkcs12-Datei. Ich muss dies verwenden, um mit dem https-Protokoll eine Verbindung zu einer Webseite herzustellen. Ich bin auf einen Code gestoßen, in dem ich die folgenden Systemeigenschaften einstellen muss, um eine Verbindung zu einer sicheren Webseite herzustellen:

System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
System.setProperty("javax.net.ssl.keyStoreType", "pkcs12");
System.setProperty("javax.net.ssl.keyStore", "new_cert.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "newpass");

Ich habe die p12 (pkcs12) -Datei. Ich brauche nur eine Truststore-Datei.

Ich habe die Zertifikate extrahiert mit:

openssl.exe pkcs12 -in c:/mykey.p12 -out c:/cert.txt -nokeys -clcerts

Konvertiert nun die cert-PEM-Datei in der

openssl.exe x509 -in c:/cert.txt -outform DER -out c:/CAcert.der 

Fügen Sie nun die der-Datei einem Schlüsselspeicher hinzu

keytool -import -file C:/Cacert.der -keystore mytruststore

Jetzt habe ich den Truststore, aber wenn ich ihn verwende, erhalte ich die folgende Fehlermeldung

Exception in thread "main" Java.net.SocketException: Java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.Sun.net.ssl.internal.ssl.DefaultSSLContextImpl)

Aktualisieren: Nachdem ich bestimmte Eigenschaften entfernt und nur die Eigenschaften "trustStore", "trustStorePassword" und "trustStoreType" festgelegt habe, erhielt ich die folgende Ausnahme

Java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty

Bitte helfen.

18
user27221

Für alle, die eine ähnliche Situation hatten, konnte ich das Problem wie folgt lösen:

  1. Erstellen Sie Ihre pkcs12-Datei wie folgt neu:

    openssl pkcs12 -in oldpkcs.p12 -out keys -passout pass:tmp
    openssl pkcs12 -in keys -export -out new.p12 -passin pass:tmp -passout pass:newpasswd
    
  2. Importieren Sie das CA-Zertifikat vom Server in einen TrustStore (entweder Ihren eigenen oder den Java-Schlüsselspeicher in $Java_HOME/jre/lib/security/cacerts, Kennwort: changeit).

  3. Legen Sie die folgenden Systemeigenschaften fest:

    System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
    System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
    System.setProperty("javax.net.ssl.keyStoreType", "pkcs12");
    System.setProperty("javax.net.ssl.keyStore", "new.p12");
    System.setProperty("javax.net.ssl.keyStorePassword", "newpasswd");
    
  4. Url testen.

Courtesy @ http://forums.Sun.com/thread.jspa?threadID=5296333

21
user27221

Ich kann wegen der Schwelle von 50 Punkten nicht kommentieren, aber ich glaube nicht, dass die Antwort in https://stackoverflow.com/a/537344/1341220 richtig ist Sie fügen Serverzertifikate in den Standard-Truststore des Systems ein:

$Java_HOME/jre/lib/security/cacerts, password: changeit)

Dies funktioniert zwar, bedeutet jedoch, dass Sie nicht wirklich einen lokalen Vertrauensspeicher für Ihr Projekt angegeben haben, sondern das Zertifikat universell in Ihrem System akzeptiert haben.

Sie verwenden eigentlich nie Ihren eigenen Truststore, den Sie hier definiert haben:

System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
5
Steffi

Es scheint, dass Sie Ihr Zertifikat aus dem PKCS # 12-Schlüsselspeicher extrahieren und einen neuen Java-Schlüsselspeicher (mit dem Typ "JKS") erstellen. Sie müssen nicht unbedingt ein Trust Store-Kennwort angeben (wenn Sie jedoch eines verwenden, um die Integrität Ihrer Stammzertifikate zu testen).

Versuchen Sie Ihr Programm also mit only mit den folgenden SSL-Eigenschaften. Die in Ihrer Frage angezeigte Liste ist zu hoch angegeben und kann Probleme verursachen.

System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

Wenn Sie die PKCS # 12-Datei direkt als Vertrauensspeicher verwenden, sollte dies auch funktionieren, solange das CA-Zertifikat als "vertrauenswürdiger" Eintrag erkannt wird. In diesem Fall müssen Sie jedoch auch die javax.net.ssl.trustStoreType-Eigenschaft als "PKCS12" angeben.

Versuchen Sie es nur mit diesen Eigenschaften. Wenn Sie dieselbe Fehlermeldung erhalten, vermute ich, dass Ihr Problem nicht im Schlüsselspeicher liegt. Wenn es immer noch auftritt, veröffentlichen Sie mehr Stapelverfolgung in Ihrer Frage, um das Problem einzugrenzen.


Der neue Fehler "Der Parameter" trustAnchors darf nicht leer sein "ist möglicherweise darauf zurückzuführen, dass die Eigenschaft javax.net.ssl.trustStore auf eine nicht vorhandene Datei gesetzt wird. Wenn die Datei nicht geöffnet werden kann, wird ein leerer Schlüsselspeicher erstellt, der zu diesem Fehler führen würde.

4
erickson

Dies ist ein Beispiel, in dem NUR eine p12-Datei verwendet wird. Es ist nicht optimiert, aber es funktioniert. Die pkcs12-Datei wurde von OpenSSL von mir generiert. Es gibt Zertifikate aus der p12-Datei aus und fügt TrustStore gute Zertifikate hinzu

KeyStore ks=KeyStore.getInstance("pkcs12");
ks.load(new FileInputStream("client_t_c1.p12"),"c1".toCharArray());

KeyStore jks=KeyStore.getInstance("JKS");
jks.load(null);

for (Enumeration<String>t=ks.aliases();t.hasMoreElements();)
{
    String alias = t.nextElement();
    System.out.println("@:" + alias);
    if (ks.isKeyEntry(alias)){
        Certificate[] a = ks.getCertificateChain(alias);
        for (int i=0;i<a.length;i++)
        {
            X509Certificate x509 = (X509Certificate)a[i];
            System.out.println(x509.getSubjectDN().toString());
            if (i>0)
                jks.setCertificateEntry(x509.getSubjectDN().toString(), x509);
            System.out.println(ks.getCertificateAlias(x509));
            System.out.println("ok");
        }
    }
}

System.out.println("init Stores...");

KeyManagerFactory kmf=KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "c1".toCharArray());

TrustManagerFactory tmf=TrustManagerFactory.getInstance("SunX509");
tmf.init(jks);

SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
4
user122678
URL url = new URL("https://test.domain:443");   
String  keyStore = "server.p12"
String   keyStorePassword = "changeit";    
String  keyPassword = "changeit";    
String   KeyStoreType= "PKCS12";    
String   KeyManagerAlgorithm = "SunX509";    
String   SSLVersion = "SSLv3";    
public HttpURLConnection getHttpsURLConnection(URL url, String  keystore,
    String   keyStorePass,String  keyPassword, String  KeyStoreType
    ,String KeyManagerAlgorithm, String  SSLVersion)
    throws NoSuchAlgorithmException, KeyStoreException,
        CertificateException, FileNotFoundException, IOException,
        UnrecoverableKeyException, KeyManagementException {
    System.setProperty("javax.net.debug","ssl,handshake,record");

    SSLContext sslcontext = SSLContext.getInstance(SSLVersion);
    KeyManagerFactory kmf =  KeyManagerFactory.getInstance(KeyManagerAlgorithm);
    KeyStore ks = KeyStore.getInstance(KeyStoreType);
    ks.load(new FileInputStream(keystore), keyStorePass.toCharArray());
    kmf.init(ks, keyPassword.toCharArray());

     TrustManagerFactory tmf = TrustManagerFactory
            .getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(ks);
    TrustManager[] tm = tmf.getTrustManagers();

    sslcontext.init(kmf.getKeyManagers(), tm, null);
    SSLSocketFactory sslSocketFactory = sslcontext.getSocketFactory();
    HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
    HttpsURLConnection httpsURLConnection = ( HttpsURLConnection)uRL.openConnection();

    return httpsURLConnection;
}
1
Mohamad Faisal

Die folgenden Schritte helfen Ihnen, Ihr Problem zu lösen.

Schritte: Developer_identity.cer <= Download von Apple Mykey.p12 <= Ihr privater Schlüssel

Befehle, die folgen sollen: 

    openssl x509 -in developer_identity.cer -inform DER -out developer_identity.pem -outform PEM

    openssl pkcs12 -nocerts -in mykey.p12 -out mykey.pem

    openssl pkcs12 -export -inkey mykey.pem -in developer_identity.pem -out iphone_dev.p12

Das letzte p12, das wir benötigen, ist die Datei iphone_dev.p12 und die Passphrase.

verwenden Sie diese Datei als p12 und versuchen Sie es dann. Dies ist in der Tat die Lösung. :)

1
Apurv Nerlekar

In diesem Beispiel wird gezeigt, wie Sie SSL auf einen vorhandenen Socket legen und das Client-Zertifikat von einer PKCS # 12-Datei abrufen. Dies ist sinnvoll, wenn Sie über einen Proxy eine Verbindung zu einem Upstream-Server herstellen müssen und das Protokoll vollständig selbst verwalten möchten.

Sobald Sie jedoch den SSL-Kontext haben, können Sie ihn auf eine HttpsURLConnection usw. anwenden.

KeyStore ks = KeyStore.getInstance("PKCS12");
InputStream is = ...;
char[] ksp = storePassword.toCharArray();
ks.load(is, ksp);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
char[] kp = keyPassword.toCharArray();
kmf.init(ks, kp);
sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(kmf.getKeyManagers(), null, null);
SSLSocketFactory factory = sslContext.getSocketFactory();
SSLSocket sslsocket = (SSLSocket) factory.createSocket(socket, socket
    .getInetAddress().getHostName(), socket.getPort(), true);
sslsocket.setUseClientMode(true);
sslsocket.setSoTimeout(soTimeout);
sslsocket.startHandshake();
1
Rogan Dawes

Ich stelle fest, dass dieser Artikel möglicherweise veraltet ist, aber ich möchte smithsv bitten, seinen Quellcode zu korrigieren. Er enthält viele Fehler. Ich konnte die meisten korrigieren, weiß aber noch nicht, was für ein Objekt x509 sein könnte. Hier ist Der Quellcode, wie ich denke, sollte sein:

import Java.io.FileInputStream;
import Java.security.KeyStore;
import Java.security.cert.Certificate;
import Java.util.Enumeration;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;

public class Connection2 {
    public void connect() {
        /*
         * This is an example to use ONLY p12 file it's not optimazed but it
         * work. The pkcs12 file where generated by OpenSSL by me. Example how
         * to load p12 file and build Trust zone from it... It outputs
         * certificates from p12 file and add good certs to TrustStore
         */
        KeyStore ks = KeyStore.getInstance( "pkcs12" );
        ks.load( new FileInputStream( cert.pfx ), "passwrd".toCharArray() );

        KeyStore jks = KeyStore.getInstance( "JKS" );
        jks.load( null );

        for( Enumeration t = ks.aliases(); t.hasMoreElements(); ) {
            String alias = (String )t.nextElement();
            System.out.println( "@:" + alias );
            if( ks.isKeyEntry( alias ) ) {
                Certificate[] a = ks.getCertificateChain( alias );
                for( int i = 0; i == 0; )
                    jks.setCertificateEntry( x509Cert.getSubjectDN().toString(), x509 );

                System.out.println( ks.getCertificateAlias( x509 ) );
                System.out.println( "ok" );
            }
        }

        System.out.println( "init Stores..." );

        KeyManagerFactory kmf = KeyManagerFactory.getInstance( "SunX509" );
        kmf.init( ks, "c1".toCharArray() );

        TrustManagerFactory tmf = TrustManagerFactory.getInstance( "SunX509" );
        tmf.init( jks );

        SSLContext ctx = SSLContext.getInstance( "TLS" );
        ctx.init( kmf.getKeyManagers(), tmf.getTrustManagers(), null );
    }
}
0
Roquen