Wie importiere ich ein vorhandenes X.509-Zertifikat und einen privaten Schlüssel in den Java-Schlüsselspeicher, um sie in SSL zu verwenden?

Lesezeit: 13 Minuten

Wie importiere ich ein vorhandenes X509 Zertifikat und einen privaten Schlussel
Aleksandar Ivanisevic

Ich habe dies in einer ActiveMQ-Konfiguration:

<sslContext>
        <sslContext keyStore="file:/home/alex/work/amq/broker.ks"  
 keyStorePassword="password" trustStore="file:${activemq.base}/conf/broker.ts" 
 trustStorePassword="password"/>
</sslContext>

Ich habe ein Paar X.509-Zertifikate und eine Schlüsseldatei.

Wie importiere ich diese beiden, um sie in SSL- und SSL+stomp-Konnektoren zu verwenden? Alle Beispiele, die ich googeln könnte, könnten den Schlüssel immer selbst generieren, aber ich habe bereits einen Schlüssel.

Ich habe versucht

keytool -import  -keystore ./broker.ks -file mycert.crt

Dies importiert jedoch nur das Zertifikat und nicht die Schlüsseldatei und führt zu

2009-05-25 13:16:24,270 [localhost:61612] ERROR TransportConnector - Could not accept connection : No available certificate or key corresponds to the SSL cipher suites which are enabled.

Ich habe versucht, das Zertifikat und den Schlüssel zu verketten, habe aber das gleiche Ergebnis erhalten.

Wie importiere ich den Schlüssel?

  • Sie müssen dazu tatsächlich ein wenig Code schreiben, und die Details hängen vom Format des privaten Schlüssels ab, den Sie zu importieren versuchen. Welches Format hat Ihr Schlüssel? Können Sie erklären, mit welchen Tools Sie den Schlüssel und das Zertifikat generiert haben, die Sie haben?

    – Ericsson

    25. Mai 2009 um 15:29 Uhr

  • Informationen zu bidirektionalem SSL (Client- und Serverzertifikat) mit Spring Boot finden Sie unter stackoverflow.com/a/59317888/548473

    – Grigori Kislin

    13. Dezember 2019 um 7:29 Uhr

Wie importiere ich ein vorhandenes X509 Zertifikat und einen privaten Schlussel
reto

Ich habe die folgenden zwei Schritte verwendet, die ich in den Kommentaren / Beiträgen gefunden habe, die in den anderen Antworten verlinkt sind:

Schritt eins: Konvertieren Sie das x.509-Zertifikat und den Schlüssel in eine pkcs12-Datei

openssl pkcs12 -export -in server.crt -inkey server.key \
               -out server.p12 -name [some-alias] \
               -CAfile ca.crt -caname root

Notiz: Stellen Sie sicher, dass Sie ein Passwort für die pkcs12-Datei eingeben – andernfalls erhalten Sie eine Nullzeiger-Ausnahme, wenn Sie versuchen, sie zu importieren. (Falls noch jemand diese Kopfschmerzen hatte). (Danke jokul!)

Anmerkung 2: Vielleicht möchten Sie die hinzufügen -chain Option zum Beibehalten der vollständigen Zertifikatskette. (Danke Mafuba)

Schritt zwei: Konvertieren Sie die pkcs12-Datei in einen Java-Schlüsselspeicher

keytool -importkeystore \
        -deststorepass [changeit] -destkeypass [changeit] -destkeystore server.keystore \
        -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass some-password \
        -alias [some-alias]

Beendet

OPTIONAL Schritt null: Erstellen Sie ein selbstsigniertes Zertifikat

openssl genrsa -out server.key 2048
openssl req -new -out server.csr -key server.key
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Prost!

  • Stellen Sie sicher, dass Sie ein Passwort für die p12-Datei eingeben – andernfalls erhalten Sie eine Null-Referenz-Ausnahme, wenn Sie versuchen, sie zu importieren. (Falls noch jemand diese Kopfschmerzen hatte)

    – jokul

    5. Juni 2012 um 20:12 Uhr

  • In meinem Fall bei Schritt eins die Option -CAfile ca.crt -caname root hat die CA-Zertifikate nicht korrekt ausgegeben. Stattdessen habe ich verwendet -certfile concatenedCAFiles.pem

    – dcernahoschi

    9. Februar 2013 um 0:36 Uhr

  • Vergessen Sie nicht, die zu verwenden -chain Argument mit openssl, um die vollständige Zertifikatskette in Ihre pfx/p12-Datei aufzunehmen, wenn Sie dies in Ihrem Schlüsselspeicher wünschen.

    – Mafuba

    24. September 2013 um 2:31 Uhr


  • In einer Windows-Umgebung pvk2pfx (ein Standard-VS-Tool, das im VS cmd Prompt) spuckt a aus .pfx–äquivalent zu a .p12. Der Rat von @jocull ist immer noch relevant; setzen Sie ein Passwort darauf. Nein openssl erforderlich.

    – Ben Mosher

    21. November 2013 um 22:49 Uhr


  • Besonders für Tomcat ist es unerlässlich, dass die Schlüsselspeicher und das Schlüssel Passwörter sind gleich. Beim Importieren einer .p12 der Schlüssel hat das Passwort des Originals .p12. Tomcat wird mit scheitern java.security.UnrecoverableKeyException: Cannot recover key. Mit anderen Worten: Wenn Sie ausführen müssen -deststorepass changeit -srcstorepass some-password mit unterschiedlich Passwörter, dann Sie Muss enthalten -destkeypass changeit (mit gleichem Passwort wie -deststorepass)

    – Slawisch

    2. Oktober 2014 um 15:14 Uhr

1646312829 156 Wie importiere ich ein vorhandenes X509 Zertifikat und einen privaten Schlussel
Gen Gotimer

Keytool in Java 6 hat diese Fähigkeit: Importieren privater Schlüssel in einen Java-Keystore mit keytool

Hier sind die grundlegenden Details aus diesem Beitrag.

  1. Konvertieren Sie das vorhandene Zertifikat mit OpenSSL in ein PKCS12. Ein Passwort ist erforderlich, wenn Sie gefragt werden, oder der 2. Schritt wird sich beschweren.

    openssl pkcs12 -export -in [my_certificate.crt] -inkey [my_key.key] -out [keystore.p12] -name [new_alias] -CAfile [my_ca_bundle.crt] -caname root
    
  2. Konvertieren Sie PKCS12 in eine Java Keystore-Datei.

    keytool -importkeystore -deststorepass [new_keystore_pass] -destkeypass [new_key_pass] -destkeystore [keystore.jks] -srckeystore [keystore.p12] -srcstoretype PKCS12 -srcstorepass [pass_used_in_p12_keystore] -alias [alias_used_in_p12_keystore]
    

  • Die Antwort von @reto enthält den Inhalt dieses Links.

    – Mafuba

    24. September 2013 um 2:33 Uhr

  • Wie von @Mafuba angegeben, müssen Sie dennoch einen separaten pkcs12-Keystore mit einem Nicht-Java-Tool wie openssl erstellen. Dieser kann dann von keytool in einen jks-Speicher importiert werden, wie in der Antwort von reto angegeben.

    – Herr_Tom

    6. Dezember 2013 um 21:09 Uhr

  • Eine Sache, die dies zu einer guten Antwort macht, ist die Tatsache, dass die Eingabezertifikate eindeutig in den Klammern angegeben sind.

    – Herr Budris

    3. Mai 2017 um 14:07 Uhr

  • FWIW, die Ausgabe von Schritt 1 sollte bereits als Java-Schlüsselspeicher verwendbar sein (daher ist Schritt 2 möglicherweise nicht erforderlich – es sei denn, Sie tun müssen das cert+key in eine importieren bestehender keystore) – wie bereits in einer früheren Antwort von @jaco0646 erwähnt

    – Janaka Bandara

    10. April 2020 um 2:26 Uhr


  • Sie können das Passwort im ersten Schritt überspringen und das Passwort im zweiten Schritt als “” dh -srcstorepass “” festlegen.

    – Trismegistos

    1. Februar 2021 um 17:30 Uhr

1646312830 102 Wie importiere ich ein vorhandenes X509 Zertifikat und einen privaten Schlussel
Matej

Ob Sie es glauben oder nicht, keytool bietet keine grundlegenden Funktionen wie das Importieren privater Schlüssel in den Schlüsselspeicher. Sie können dies versuchen Problemumgehung beim Zusammenführen der PKSC12-Datei mit dem privaten Schlüssel zu einem Schlüsselspeicher:

keytool -importkeystore \
  -deststorepass storepassword \
  -destkeypass keypassword \
  -destkeystore my-keystore.jks \
  -srckeystore cert-and-key.p12 \
  -srcstoretype PKCS12 \
  -srcstorepass p12password \
  -alias 1

Oder verwenden Sie einfach benutzerfreundlichere Schlüsselmann von IBM für das Keystore-Handling anstelle von keytool.

  • Laut der Antwort von CoverosGene unterstützt Keytool dies seit Java 6. Dies ist die Verknüpfung er stellte bereit

    – Houtmann

    8. Dezember 2014 um 11:58 Uhr


  • Für das, was es wert ist, für all den Lärm zu diesem Thema, ist der beste Link der ‘Workaround’-Link von @Matej zu diesem Beitrag von 2008: cunning.sharp.fm/2008/06/importing_private_keys_into_a.html

    – Wolkensurfen

    11. Februar 2016 um 0:44 Uhr

  • KeyMan scheint mir nicht so benutzerfreundlich zu sein.

    – Schurke

    10. August 2016 um 17:10 Uhr

  • Defekter Link. Bitte geben Sie die Details der Lösung direkt in die Antwort ein 🙁

    – lilalinux

    9. August 2018 um 12:46 Uhr

1646312830 887 Wie importiere ich ein vorhandenes X509 Zertifikat und einen privaten Schlussel
Mathias Braun

Verwenden von Let’s Encrypt-Zertifikaten

Angenommen, Sie haben Ihre Zertifikate und privaten Schlüssel mit erstellt Lassen Sie uns verschlüsseln in /etc/letsencrypt/live/you.com:

1. Erstellen Sie eine PKCS #12 Datei

openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out pkcs.p12 \
        -name letsencrypt

Dies kombiniert Ihr SSL-Zertifikat fullchain.pem und Ihren privaten Schlüssel privkey.pem in einer einzigen Datei, pkcs.p12.

Sie werden nach einem Passwort für gefragt pkcs.p12.

Die export Option gibt an, dass eine PKCS #12-Datei erstellt und nicht geparst wird (gemäß das Handbuch).

2. Erstellen Sie den Java-Keystore

keytool -importkeystore -destkeystore keystore.jks -srckeystore pkcs.p12 \
        -srcstoretype PKCS12 -alias letsencrypt

Wenn keystore.jks nicht existiert, wird sie mit den erstellt pkcs.12 oben erstellte Datei. Andernfalls importieren Sie pkcs.12 in den vorhandenen Schlüsselspeicher.


Diese Anweisungen leiten sich aus dem Beitrag „Create a Java Keystore (.JKS) from Let’s Encrypt Certificates“ ab dieses Blog.

Hier ist mehr auf die verschiedenen Arten von Dateien in /etc/letsencrypt/live/you.com/.

Konvertieren Sie zuerst in p12:

openssl pkcs12 -export -in [filename-certificate] -inkey [filename-key] -name [host] -out [filename-new-PKCS-12.p12]

Neues JKS aus p12 erstellen:

keytool -importkeystore -deststorepass [password] -destkeystore [filename-new-keystore.jks] -srckeystore [filename-new-PKCS-12.p12] -srcstoretype PKCS12

Und einer mehr:

#!/bin/bash

# We have:
#
# 1) $KEY : Secret key in PEM format ("-----BEGIN RSA PRIVATE KEY-----") 
# 2) $LEAFCERT : Certificate for secret key obtained from some
#    certification outfit, also in PEM format ("-----BEGIN CERTIFICATE-----")   
# 3) $CHAINCERT : Intermediate certificate linking $LEAFCERT to a trusted
#    Self-Signed Root CA Certificate 
#
# We want to create a fresh Java "keystore" $TARGET_KEYSTORE with the
# password $TARGET_STOREPW, to be used by Tomcat for HTTPS Connector.
#
# The keystore must contain: $KEY, $LEAFCERT, $CHAINCERT
# The Self-Signed Root CA Certificate is obtained by Tomcat from the
# JDK's truststore in /etc/pki/java/cacerts

# The non-APR HTTPS connector (APR uses OpenSSL-like configuration, much
# easier than this) in server.xml looks like this 
# (See: https://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html):
#
#  <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
#                SSLEnabled="true"
#                maxThreads="150" scheme="https" secure="true"
#                clientAuth="false" sslProtocol="TLS"
#                keystoreFile="/etc/tomcat6/etl-web.keystore.jks"
#                keystorePass="changeit" />
#

# Let's roll:    

TARGET_KEYSTORE=/etc/tomcat6/foo-server.keystore.jks
TARGET_STOREPW=changeit

TLS=/etc/pki/tls

KEY=$TLS/private/httpd/foo-server.example.com.key
LEAFCERT=$TLS/certs/httpd/foo-server.example.com.pem
CHAINCERT=$TLS/certs/httpd/chain.cert.pem

# ----
# Create PKCS#12 file to import using keytool later
# ----

# From https://www.sslshopper.com/ssl-converter.html:
# The PKCS#12 or PFX format is a binary format for storing the server certificate,
# any intermediate certificates, and the private key in one encryptable file. PFX
# files usually have extensions such as .pfx and .p12. PFX files are typically used 
# on Windows machines to import and export certificates and private keys.

TMPPW=$$ # Some random password

PKCS12FILE=`mktemp`

if [[ $? != 0 ]]; then
  echo "Creation of temporary PKCS12 file failed -- exiting" >&2; exit 1
fi

TRANSITFILE=`mktemp`

if [[ $? != 0 ]]; then
  echo "Creation of temporary transit file failed -- exiting" >&2; exit 1
fi

cat "$KEY" "$LEAFCERT" > "$TRANSITFILE"

openssl pkcs12 -export -passout "pass:$TMPPW" -in "$TRANSITFILE" -name etl-web > "$PKCS12FILE"

/bin/rm "$TRANSITFILE"

# Print out result for fun! Bug in doc (I think): "-pass " arg does not work, need "-passin"

openssl pkcs12 -passin "pass:$TMPPW" -passout "pass:$TMPPW" -in "$PKCS12FILE" -info

# ----
# Import contents of PKCS12FILE into a Java keystore. WTF, Sun, what were you thinking?
# ----

if [[ -f "$TARGET_KEYSTORE" ]]; then
  /bin/rm "$TARGET_KEYSTORE"
fi

keytool -importkeystore \
   -deststorepass  "$TARGET_STOREPW" \
   -destkeypass    "$TARGET_STOREPW" \
   -destkeystore   "$TARGET_KEYSTORE" \
   -srckeystore    "$PKCS12FILE" \
   -srcstoretype  PKCS12 \
   -srcstorepass  "$TMPPW" \
   -alias foo-the-server

/bin/rm "$PKCS12FILE"

# ----
# Import the chain certificate. This works empirically, it is not at all clear from the doc whether this is correct
# ----

echo "Importing chain"

TT=-trustcacerts

keytool -import $TT -storepass "$TARGET_STOREPW" -file "$CHAINCERT" -keystore "$TARGET_KEYSTORE" -alias chain

# ----
# Print contents
# ----

echo "Listing result"

keytool -list -storepass "$TARGET_STOREPW" -keystore "$TARGET_KEYSTORE"

1646312830 64 Wie importiere ich ein vorhandenes X509 Zertifikat und einen privaten Schlussel
bekce

In meinem Fall hatte ich eine PEM-Datei, die zwei Zertifikate und einen verschlüsselten privaten Schlüssel enthielt, die für die gegenseitige SSL-Authentifizierung verwendet werden sollten. Meine pem-Datei sah also so aus:

-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,C8BF220FC76AA5F9
...
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

Folgendes habe ich getan:

Teilen Sie die Datei in drei separate Dateien auf, sodass jede nur einen Eintrag enthält, beginnend mit „—BEGIN..“ und endend mit „—END..“ Zeilen. Nehmen wir an, wir haben jetzt drei Dateien: cert1.pem cert2.pem und pkey.pem

Konvertieren Sie pkey.pem mithilfe von openssl und der folgenden Syntax in das DER-Format:

openssl pkcs8 -topk8 -nocrypt -in pkey.pem -inform PEM -out pkey.der -outform DER

Beachten Sie, dass Sie, wenn der private Schlüssel verschlüsselt ist, ein Passwort angeben müssen (beziehen Sie es vom Lieferanten der ursprünglichen PEM-Datei), um in das DER-Format zu konvertieren, openssl Sie wie folgt nach dem Passwort fragen wird: “Geben Sie eine Passphrase für pkey .pem: ” Bei erfolgreicher Konvertierung erhalten Sie eine neue Datei namens “pkey.der”

Erstellen Sie einen neuen Java-Schlüsselspeicher und importieren Sie den privaten Schlüssel und die Zertifikate:

String keypass = "password";  // this is a new password, you need to come up with to protect your java key store file
String defaultalias = "importkey";
KeyStore ks = KeyStore.getInstance("JKS", "SUN");

// this section does not make much sense to me, 
// but I will leave it intact as this is how it was in the original example I found on internet:   
ks.load( null, keypass.toCharArray());
ks.store( new FileOutputStream ( "mykeystore"  ), keypass.toCharArray());
ks.load( new FileInputStream ( "mykeystore" ),    keypass.toCharArray());
// end of section..


// read the key file from disk and create a PrivateKey

FileInputStream fis = new FileInputStream("pkey.der");
DataInputStream dis = new DataInputStream(fis);
byte[] bytes = new byte[dis.available()];
dis.readFully(bytes);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);

byte[] key = new byte[bais.available()];
KeyFactory kf = KeyFactory.getInstance("RSA");
bais.read(key, 0, bais.available());
bais.close();

PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key );
PrivateKey ff = kf.generatePrivate (keysp);


// read the certificates from the files and load them into the key store:

Collection  col_crt1 = CertificateFactory.getInstance("X509").generateCertificates(new FileInputStream("cert1.pem"));
Collection  col_crt2 = CertificateFactory.getInstance("X509").generateCertificates(new FileInputStream("cert2.pem"));

Certificate crt1 = (Certificate) col_crt1.iterator().next();
Certificate crt2 = (Certificate) col_crt2.iterator().next();
Certificate[] chain = new Certificate[] { crt1, crt2 };

String alias1 = ((X509Certificate) crt1).getSubjectX500Principal().getName();
String alias2 = ((X509Certificate) crt2).getSubjectX500Principal().getName();

ks.setCertificateEntry(alias1, crt1);
ks.setCertificateEntry(alias2, crt2);

// store the private key
ks.setKeyEntry(defaultalias, ff, keypass.toCharArray(), chain );

// save the key store to a file         
ks.store(new FileOutputStream ( "mykeystore" ),keypass.toCharArray());

(optional) Überprüfen Sie den Inhalt Ihres neuen Schlüsselspeichers:

keytool -list -keystore mykeystore -storepass password

Keystore-Typ: JKS Keystore-Anbieter: SUN

Ihr Schlüsselspeicher enthält 3 Einträge

cn=…,ou=…,o=.., 2. September 2014, trustedCertEntry, Zertifikat-Fingerabdruck (SHA1): 2C:B8: …

importkey, 02.09.2014, PrivateKeyEntry, Zertifikatsfingerabdruck (SHA1): 9C:B0: …

cn=…,o=…., 2. September 2014, trustedCertEntry, Zertifikat-Fingerabdruck (SHA1): 83:63: …

(optional) Testen Sie Ihre Zertifikate und privaten Schlüssel aus Ihrem neuen Schlüsselspeicher mit Ihrem SSL-Server: (Möglicherweise möchten Sie das Debugging als VM-Option aktivieren: -Djavax.net.debug=all )

        char[] passw = "password".toCharArray();
        KeyStore ks = KeyStore.getInstance("JKS", "SUN");
        ks.load(new FileInputStream ( "mykeystore" ), passw );

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

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

        SSLContext sclx = SSLContext.getInstance("TLS");
        sclx.init( kmf.getKeyManagers(), tm, null);

        SSLSocketFactory factory = sclx.getSocketFactory();
        SSLSocket socket = (SSLSocket) factory.createSocket( "192.168.1.111", 443 );
        socket.startHandshake();

        //if no exceptions are thrown in the startHandshake method, then everything is fine..

Registrieren Sie abschließend Ihre Zertifikate bei HttpsURLConnection, wenn Sie diese verwenden möchten:

        char[] passw = "password".toCharArray();
        KeyStore ks = KeyStore.getInstance("JKS", "SUN");
        ks.load(new FileInputStream ( "mykeystore" ), passw );

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

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

        SSLContext sclx = SSLContext.getInstance("TLS");
        sclx.init( kmf.getKeyManagers(), tm, null);

        HostnameVerifier hv = new HostnameVerifier()
        {
            public boolean verify(String urlHostName, SSLSession session)
            {
                if (!urlHostName.equalsIgnoreCase(session.getPeerHost()))
                {
                    System.out.println("Warning: URL host '" + urlHostName + "' is different to SSLSession host '" + session.getPeerHost() + "'.");
                }
                return true;
            }
        };

        HttpsURLConnection.setDefaultSSLSocketFactory( sclx.getSocketFactory() );
        HttpsURLConnection.setDefaultHostnameVerifier(hv);

  • Bruno erwähnte jedoch, dass dieser Hostnamen-Verifizierer falsch ist: „Ihr Hostnamen-Verifizierer ist falsch, session.getPeerHost() gibt nicht den Namen im Zertifikat zurück, sondern den Namen, mit dem Sie sich verbunden haben (dh hier den urlHostName), also geht das immer wahr zu sein. Du kehrst sowieso immer wahr zurück. – Bruno“. Es hat zwar für mich funktioniert, aber ich würde es begrüßen, wenn mir jemand zeigt, wie man einen guten Hostnamen-Verifizierer schreibt.

    – Interkot

    4. September 2014 um 16:22 Uhr


  • Natürlich wird es für Sie “funktionieren”, da es niemals einen Fehler produziert, selbst wenn es sollte. Belassen Sie den standardmäßigen Hostnamen-Verifizierer, der von verwendet wird HttpsURLConnection anstatt zu versuchen, Ihre eigenen zu schreiben. (Ein weiteres Problem mit Ihrem Beispiel ist, dass Sie denselben Keystore als Keystore und Truststore verwenden, was nicht immer eine gute Idee ist …)

    – Bruno

    4. September 2014 um 16:31 Uhr


923680cookie-checkWie importiere ich ein vorhandenes X.509-Zertifikat und einen privaten Schlüssel in den Java-Schlüsselspeicher, um sie in SSL zu verwenden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy