¿Cómo importar un certificado x509 existente y una clave privada en Java keystore para usar en SSL?


Tengo esto en activemq config

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

Tengo un par de x509 cert y un archivo de clave

¿Cómo puedo importar esos dos para ser utilizados en conectores ssl y ssl+stomp? Todos los ejemplos que podría Google siempre generar la clave por sí mismos, pero ya tengo una clave.

He intentado

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

Pero esto solo importa el certificado y no el archivo de clave y resulta en

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.

He intentado concatenar el cert y la clave, pero obtuve lo mismo resultado

¿Cómo puedo importar la clave?

Author: jww, 2009-05-25

10 answers

Lo creas o no, keytool no proporciona una funcionalidad básica como la importación de clave privada al almacén de claves. Puede probar esta solución fusionando el archivo PKSC12 con la clave privada en un almacén de claves.

O simplemente use KeyMan más fácil de usar de IBM para el manejo del almacén de claves en lugar de keytool.exe.

 63
Author: Matej,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-24 10:58:55

Usé los siguientes dos pasos que encontré en los comentarios/posts enlazados en las otras respuestas:

Paso uno: Convertir x509 Cert y Clave a un archivo pkcs12

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

Nota: asegúrese de poner una contraseña en el archivo p12 - de lo contrario obtendrá una excepción de referencia nula cuando intenta importar. (En caso de que alguien más tuviera este dolor de cabeza). (Gracias jocull!)

Nota 2: Es posible que desee agregar la opción -chain para preservar el cadena de certificados. (Gracias Mafuba )

Paso dos: Convierta el archivo pkcs12 a un almacén de claves java

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

Terminado

Paso OPCIONAL Cero, crear certificado autofirmado

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

Salud!

 454
Author: reto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-17 14:04:51

Keytool en Java 6 tiene esta capacidad: Importar claves privadas en un almacén de claves Java usando keytool

Aquí están los detalles básicos de ese post.

  1. Convierta el cert existente a un PKCS12 usando OpenSSL. Se requiere una contraseña cuando se le pide o el segundo paso se quejará.

    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. Convierta el PKCS12 en un archivo de Almacén de claves Java.

    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]
    
 109
Author: CoverosGene,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-06 09:55:08

Y uno más:

#!/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"
 9
Author: David Tonhofer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-27 23:08:26

Sí, es un hecho triste que keytool no tiene ninguna funcionalidad para importar una clave privada.

Para el registro, al final fui con la solución descrita aquí

 8
Author: Aleksandar Ivanisevic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-10 03:26:17

En mi caso, tenía un archivo pem que contenía dos certificados y una clave privada encriptada para ser utilizada en la autenticación SSL mutua. Así que mi archivo pem se veía así:

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

Esto es lo que hice:

Divida el archivo en tres archivos separados, de modo que cada uno contenga una sola entrada, comenzando con " - - - BEGIN.."y terminando con" - - - FIN.." alinear. Supongamos que ahora tenemos tres archivos: cert1.pem cert2.pem y pkey.pem

Convertir pkey.pem en formato DER usando openssl y la siguiente sintaxis:

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

Tenga en cuenta que si la clave privada está encriptada, debe proporcionar una contraseña (obtenerla del proveedor del archivo pem original ) para convertir a formato DER, openssl le preguntará por la contraseña de esta manera: "introduzca un paso phraze para pkey.pem: " Si la conversión es exitosa, obtendrá un nuevo archivo llamado " pkey.der "

Cree un nuevo almacén de claves java e importe la clave privada y los certificados:

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

(opcional) Verificar el contenido de su nuevo almacén de llaves:

keytool -list -keystore mykeystore -storepass password

Tipo de almacén de claves: JKS Proveedor de almacén de claves: SUN

Su almacén de claves contiene 3 entradas

Cn=...,ou=..., o=.., Sep 2, 2014, trustedCertEntry, Certificado huella digital (SHA1): 2C: B8:...

Importkey, 2 de septiembre de 2014, PrivateKeyEntry, Huella dactilar del certificado (SHA1): 9C: B0:...

Cn=..., o=...., Sep 2, 2014, trustedCertEntry, Huella dactilar del certificado (SHA1): 83: 63:...

(facultativo) Pruebe sus certificados y clave privada de su nuevo almacén de claves contra su servidor SSL: ( Es posible que desee habilitar la depuración como una opción VM: -Djavax.net.debug=todos )

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

Finalmente registre sus certificados con HttpsURLConnection si planea usarlo:

        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);
 6
Author: Interkot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-18 13:17:26

Primero convertir a p12:

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

Crear nuevos JKS desde p12:

keytool -importkeystore -deststorepass [password] -destkeystore [filename-new-keystore.jks] -srckeystore [filename-new-PKCS-12.p12] -srcstoretype PKCS12
 5
Author: Michał Jurczuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-01 08:49:59

Basado en las respuestas anteriores, aquí está cómo crear un nuevo almacén de claves para su servidor web basado en java, a partir de un certificado Comodo y clave privada creados independientemente usando keytool (requiere JDK 1.6+)

  1. Ejecute este comando y en el indicador de contraseña ingrese somepass - 'server.crt ' es el cert y el 'servidor de su servidor.clave ' es la clave privada que utilizó para emitir la CSR: openssl pkcs12 -export -in server.crt -inkey server.key -out server.p12 -name www.yourdomain.com -CAfile AddTrustExternalCARoot.crt -caname "AddTrust External CA Root"

  2. A continuación, utilice keytool para convertir el almacén de claves p12 en un jks almacén de claves: keytool -importkeystore -deststorepass somepass -destkeypass somepass -destkeystore keystore.jks -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass somepass

Luego importa los otros dos certificados raíz / intermedios que recibiste de Comodo:

  1. Importación COMODORSAAddTrustCA.crt: keytool -import -trustcacerts -alias cert1 -file COMODORSAAddTrustCA.crt -keystore keystore.jks

  2. Importación COMODORSADomainValidationSecureServerCA.crt: keytool -import -trustcacerts -alias cert2 -file COMODORSADomainValidationSecureServerCA.crt -keystore keystore.jks

 5
Author: Alex Fotios,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-21 17:32:13

Estos son los pasos que seguí para importar la clave a un almacén de claves existente-instrucciones combinadas de respuestas aquí y otros lugares para obtener estos pasos que funcionaron para mi almacén de claves java:

  1. Corre

openssl pkcs12 -export -in yourserver.crt -inkey yourkey.key -out server.p12 -name somename -certfile yourca.crt -caname root

(Si es necesario poner la opción-chain. Poniendo que falló para mí). Esto le pedirá la contraseña-usted debe dar la contraseña correcta de lo contrario obtendrá un error (error de encabezado o error de relleno, etc.).

  1. se le pedirá que introduzca un nuevo contraseña-debe ingresar una contraseña aquí-ingrese cualquier cosa menos recordarla. (Supongamos que entras en Aragorn).
  2. Esto creará el servidor.archivo p12 en el formato pkcs.
  3. Ahora para importarlo en el archivo *.jks ejecute:

Keytool-importkeystore-servidor srckeystore.p12-srcstoretype PKCS12 - destkeystore te estás volviendo loco.jks-deststoretype JKS-deststorepass existingjavastorepassword-destkeypass existingjavastorepassword

(Muy importante - no omita los parámetros deststorepass y destkeypass.)
5. Le pedirá la contraseña de la tienda de claves src. Entra Aragorn y pulsa enter. El certificado y la clave ahora se importan a su almacén de claves Java existente.

 4
Author: vanval,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-13 14:27:25

Las respuestas anteriores señalan correctamente que solo puede hacer esto con las herramientas JDK estándar convirtiendo primero el archivo JKS al formato PKCS #12. Si estás interesado, armé una utilidad compacta para importar claves derivadas de OpenSSL en un almacén de claves con formato JKS sin tener que convertir primero el almacén de claves a PKCS #12: http://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art049

Usarías la utilidad enlazada así:

$ openssl req -x509 -newkey rsa:2048 -keyout localhost.key -out localhost.csr -subj "/CN=localhost"

(firmar la CSR, obtener localhost de vuelta.cer)

$ openssl rsa -in localhost.key -out localhost.rsa
Enter pass phrase for localhost.key:
writing RSA key
$ java -classpath . KeyImport -keyFile localhost.rsa -alias localhost -certificateFile localhost.cer -keystore localhost.jks -keystorePassword changeit -keystoreType JKS -keyPassword changeit
 3
Author: Joshua Davies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-03 18:47:22