Come importare un certificato X.509 esistente e una chiave privata nel keystore Java da utilizzare in SSL?


228

Ho questo in una configurazione ActiveMQ:

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

Ho un paio di certificati X.509 e un file chiave.

Come importare quei due per usarli nei connettori SSL e SSL + stomp? Tutti gli esempi che ho potuto google generano sempre la chiave da soli, ma ho già una chiave.

Ho provato

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

ma questo importa solo il certificato e non il file chiave e risulta

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.

Ho provato a concatenare il certificato e la chiave ma ho ottenuto lo stesso risultato.

Come importare la chiave?


1
In realtà devi scrivere un po 'di codice per farlo e i dettagli dipendono dal formato della chiave privata che stai cercando di importare. Di che formato è la tua chiave? Puoi spiegare quali strumenti hai usato per generare la chiave e il certificato che hai?
Erickson,

Per due vie SSL (client e server certificato) con la molla di avvio vedere stackoverflow.com/a/59317888/548473
Grigory Kislin

Risposte:


73

Che ci crediate o no, keytool non fornisce tali funzionalità di base come l'importazione della chiave privata nel keystore. Puoi provare questa soluzione alternativa con l'unione del file PKSC12 con la chiave privata in un keystore.

Oppure utilizza KeyMan più intuitivo di IBM per la gestione dei keystore anziché keytool.exe.


11
Secondo la risposta di CoverosGene, il keytool lo supporta da Java 6. Questo è il link che ha fornito
Houtman,

Per quello che vale, per tutto il rumore su questo argomento, il miglior link è il link 'workaround' di @ Matej a questo post del 2008: cunning.sharp.fm/2008/06/importing_private_keys_into_a.html
cloudsurfin

2
Ho seguito la risposta fornita da CoverosGene e ha funzionato.
Robert3452,

1
KeyMan non mi sembra così facile da usare.
Miscreant

15
Collegamento non funzionante. Per favore, includi i dettagli della soluzione direttamente nella risposta :-(
lilalinux

536

Ho usato i seguenti due passaggi che ho trovato nei commenti / post collegati nelle altre risposte:

Passaggio 1: convertire il certificato e la chiave x.509 in un file pkcs12

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

Nota: assicurarsi di inserire una password nel file pkcs12, altrimenti si otterrà un'eccezione puntatore null quando si tenta di importarlo. (Nel caso qualcun altro avesse questo mal di testa). ( Grazie jocull! )

Nota 2: è possibile aggiungere l' -chainopzione per preservare l'intera catena di certificati. ( Grazie Mafuba )

Passaggio 2: convertire il file pkcs12 in un keystore Java

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

Finito

OPZIONALE Passaggio zero: creare un certificato autofirmato

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

Saluti!


12
Assicurati di inserire una password nel file p12, altrimenti otterrai un'eccezione di riferimento null quando provi a importarla. (Nel caso qualcun altro avesse questo mal di testa)
giocate il

9
Nel mio caso al primo passaggio l'opzione -CAfile ca.crt -caname rootnon ha prodotto correttamente i certificati CA. Invece ho usato-certfile concatenedCAFiles.pem
dcernahoschi il

11
Non dimenticare di usare l' -chainargomento con openssl per includere l'intera catena di certificati nel tuo file pfx / p12 se lo desideri nel tuo keystore.
Mafuba,

3
In un ambiente Windows, pvk2pfx(uno strumento VS standard disponibile nel cmdprompt VS ) .pfxsputerà un --equivalente a a .p12. Il consiglio di @jocull è ancora rilevante; mettici sopra una password. Non opensslserve
Ben Mosher,

9
Per Tomcat, in particolare, è fondamentale che il keystore e le password delle chiavi siano uguali. Quando si importa una .p12chiave, la password del .p12.Tomcat originale avrà esito negativo java.security.UnrecoverableKeyException: Cannot recover key. In altre parole: se devi eseguire -deststorepass changeit -srcstorepass some-passwordcon password diverse , devi includere -destkeypass changeit(con la stessa password di -deststorepass)
Slav

127

Keytool in Java 6 ha questa capacità: Importare chiavi private in un keystore Java usando keytool

Ecco i dettagli di base di quel post.

  1. Converti il ​​certificato esistente in un PKCS12 usando OpenSSL. È richiesta una password quando viene richiesta o il secondo passaggio si lamenterà.

    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. Convertire PKCS12 in un file di archivio chiavi 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]

4
La risposta di @reto contiene i contenuti di questo link.
Mafuba,

4
Come affermato da @Mafuba, è comunque necessario creare un keystore pkcs12 separato con uno strumento non java come openssl - quindi questo può essere importato in un archivio jks da keytool come indicato nella risposta da reto.
Mister_Tom,

Una cosa che rende questa una buona risposta è il fatto che i certificati di input sono chiaramente indicati tra parentesi.
Mr.Brisris,

FWIW, l'output del passaggio 1 dovrebbe già essere utilizzabile come keystore Java (quindi il passaggio 2 potrebbe non essere necessario, a meno che non sia necessario importare la chiave cert + in un keystore esistente ), come già accennato in una risposta precedente da @ jaco0646
Janaka Bandara,

9

E ancora uno:

#!/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

Prima conversione in p12:

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

Crea nuovo JKS da p12:

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

7

Sì, è davvero un fatto triste che keytool non abbia funzionalità per importare una chiave privata.

Per la cronaca, alla fine sono andato con la soluzione descritta qui


6

Nel mio caso avevo un file pem che conteneva due certificati e una chiave privata crittografata da utilizzare nell'autenticazione SSL reciproca. Quindi il mio file pem era simile al seguente:

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

Ecco cosa ho fatto:

Dividi il file in tre file separati, in modo che ognuno contenga solo una voce, iniziando con "--- INIZIA .." e terminando con "--- FINE ..". Supponiamo che ora abbiamo tre file: cert1.pem cert2.pem e pkey.pem

Converti pkey.pem in formato DER usando openssl e la sintassi seguente:

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

Nota che se la chiave privata è crittografata devi fornire una password (ottenerla dal fornitore del file pem originale) per convertirla in formato DER, openssl ti chiederà la password in questo modo: "inserisci una passphraze per pkey .pem: "Se la conversione ha esito positivo, otterrai un nuovo file chiamato" pkey.der "

Crea un nuovo archivio chiavi Java e importa la chiave privata e i certificati:

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

(facoltativo) Verifica il contenuto del tuo nuovo keystore:

keytool -list -keystore mykeystore -storepass password

Tipo di archivio chiavi: JKS Fornitore archivio chiavi: SUN

Il tuo keystore contiene 3 voci

cn = ..., ou = ..., o = .., 2 set 2014, trustedCertEntry, impronta digitale del certificato (SHA1): 2C: B8: ...

importkey, 2 set 2014, PrivateKeyEntry, impronta digitale del certificato (SHA1): 9C: B0: ...

cn = ..., o = ...., 2 set 2014, trustedCertEntry, impronta digitale del certificato (SHA1): 83:63: ...

(facoltativo) Testa i tuoi certificati e chiave privata dal tuo nuovo archivio chiavi sul tuo server SSL: (Potresti voler abilitare il debug come opzione VM: -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..

Infine registra i tuoi certificati con HttpsURLConnection se intendi utilizzarlo:

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

Tuttavia, Bruno ha affermato che questo verificatore del nome host è errato: "Il verificatore del nome host è errato, session.getPeerHost () non restituisce il nome nel certificato, ma il nome con cui ti sei collegato (ovvero urlHostName qui), quindi è sempre attivo per essere vero. Ritorni sempre vero comunque. - Bruno ". Però ha funzionato per me, ma apprezzerei se qualcuno mi mostrasse come scrivere un buon verificatore di nomi host.
Interkot

1
Ovviamente "funzionerà" per te, dal momento che non produrrà mai un errore, anche quando dovrebbe. Lasciare utilizzato il verificatore del nome host predefinito utilizzato HttpsURLConnectioninvece di provare a scrivere il proprio. (Un altro problema con il tuo esempio è che stai usando lo stesso keystore di un keystore e un truststore, il che non è sempre una buona idea ...)
Bruno

6

Utilizzando Let's Encrypt certificati

Supponendo di aver creato i certificati e le chiavi private con Let's Encrypt in /etc/letsencrypt/live/you.com:

1. Creare un file PKCS # 12

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

Questo combina il certificato SSL fullchain.peme la chiave privata privkey.pemin un unico file, pkcs.p12.

Ti verrà richiesta una password per pkcs.p12 .

L' exportopzione specifica che verrà creato un file PKCS # 12 anziché analizzato (dal manuale ).

2. Creare il keystore Java

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

Se keystore.jksnon esiste, verrà creato contenente il pkcs.12file creato sopra. Altrimenti, importerai pkcs.12nel keystore esistente.


Queste istruzioni derivano da questo post sul blog .

Ecco di più sui diversi tipi di file in /etc/letsencrypt/live/you.com/.


5

Sulla base delle risposte sopra, ecco come creare un nuovissimo keystore per il tuo server Web basato su Java, da un certificato Comodo creato in modo indipendente e una chiave privata usando keytool (richiede JDK 1.6+)

  1. Emetti questo comando e al prompt della password inserisci somepass - 'server.crt' è il certificato del tuo server e 'server.key' è la chiave privata che hai usato per emettere il 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. Quindi utilizzare keytool per convertire il keystore p12 in un keystore jks: keytool -importkeystore -deststorepass somepass -destkeypass somepass -destkeystore keystore.jks -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass somepass

Quindi importare le altre due certificazioni root / intermedie ricevute da Comodo:

  1. Importa COMODORSAAddTrustCA.crt: keytool -import -trustcacerts -alias cert1 -file COMODORSAAddTrustCA.crt -keystore keystore.jks

  2. Importa COMODORSADomainValidationSecureServerCA.crt: keytool -import -trustcacerts -alias cert2 -file COMODORSADomainValidationSecureServerCA.crt -keystore keystore.jks


4

È possibile utilizzare questi passaggi per importare la chiave in un archivio chiavi esistente. Le istruzioni sono combinate dalle risposte in questa discussione e in altri siti. Queste istruzioni hanno funzionato per me (il keystore java):

  1. Correre

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

(Se richiesto, metti l'opzione -chain. Mettere quello non è riuscito per me). Ciò richiederà la password: è necessario fornire la password corretta, altrimenti si otterrà un errore (errore di intestazione o errore di riempimento, ecc.).

  1. Ti chiederà di inserire una nuova password - devi inserire una password qui - inserisci qualsiasi cosa ma ricordalo. (Supponiamo che tu entri in Aragorn).
  2. Questo creerà il file server.p12 nel formato pkcs.
  3. Ora per importarlo nell'esecuzione del *.jksfile:
    keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -destkeystore yourexistingjavakeystore.jks -deststoretype JKS -deststorepass existingjavastorepassword -destkeypass existingjavastorepassword
    (Molto importante - non tralasciare i parametri deststorepass e destkeypass.)
  4. Ti chiederà la password dell'archivio chiavi src. Inserisci Aragorn e premi invio. Il certificato e la chiave vengono ora importati nel keystore java esistente.

3

Le risposte precedenti indicano correttamente che è possibile farlo solo con gli strumenti JDK standard convertendo prima il file JKS nel formato PKCS # 12. Se sei interessato, ho messo insieme un'utilità compatta per importare le chiavi derivate da OpenSSL in un keystore formattato JKS senza dover prima convertire il keystore in PKCS # 12: http://commandlinefanatic.com/cgi-bin/showarticle. cgi? article = art049

Utilizzeresti l'utilità collegata in questo modo:

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

(firma il CSR, torna localhost.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

Il semplice collegamento alla propria libreria (o utilità) non è una buona risposta. Collegamento ad esso, spiegazione del motivo per cui risolve il problema, fornendo codice che lo utilizza per farlo e la dichiarazione di non responsabilità fornisce una risposta migliore. Vedi: Come posso collegarmi a una risorsa esterna in modo favorevole alla comunità?
Mogsdad,

Non sono sicuro di cosa intendi con "disclaim", ma ho aggiunto un esempio.
Joshua Davies,

Grande! Questo è un commento fisso, quindi una parte non si applica - disconoscere significa segnalare la tua affiliazione con il prodotto o servizio collegato, che hai fatto con "Ho messo insieme ..."
Mogsdad

3

Se si dispone di un file PEM (ad es. server.pem) Contenente:

  • il certificato attendibile
  • la chiave privata

quindi è possibile importare il certificato e la chiave in un keystore JKS in questo modo:

1 ) Copia la chiave privata dal file PEM in un file ASCII (ad es. server.key)

2 ) Copia il certificato dal file PEM in un file ASCII (ad es. server.crt)

3 ) Esporta il certificato e la chiave in un file PKCS12:

$ openssl pkcs12 -export -in server.crt -inkey server.key \
                 -out server.p12 -name [some-alias] -CAfile server.pem -caname root
  • il file PEM può essere usato come argomento per l' -CAfileopzione .
  • ti viene richiesta una password di 'esportazione'.
  • se lo fai in git bash, aggiungi winptyall'inizio del comando in modo da poter inserire la password di esportazione.

4 ) Convertire il file PKCS12 in un keystore JKS:

$ keytool -importkeystore -deststorepass changeit -destkeypass changeit \
          -destkeystore keystore.jks  -srckeystore server.p12 -srcstoretype PKCS12 \
          -srcstorepass changeit
  • la srcstorepasspassword deve corrispondere alla password di esportazione dal passaggio 3)

3

Quello che stavo cercando di ottenere era usare la chiave privata e il certificato già forniti per firmare il messaggio che stava andando in un posto che era necessario per assicurarsi che il messaggio provenisse da me (segno di chiavi private mentre le chiavi pubbliche crittografano).

Quindi se hai già un file .key e un file .crt?

Prova questo:

Passaggio 1: converti la chiave e esegui il cert in file .p12

openssl pkcs12 -export -in certificate.crt -inkey privateKey.key -name alias -out yourconvertedfile.p12

Passaggio 2: importare la chiave e creare un file .jsk con un singolo comando

keytool -importkeystore -deststorepass changeit -destkeystore keystore.jks -srckeystore umeme.p12 -srcstoretype PKCS12

Passaggio 3: nel tuo java:

char[] keyPassword = "changeit".toCharArray();

KeyStore keyStore = KeyStore.getInstance("JKS");
InputStream keyStoreData = new FileInputStream("keystore.jks");

keyStore.load(keyStoreData, keyPassword);
KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(keyPassword);
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry("alias", entryPassword);

System.out.println(privateKeyEntry.toString());

Se devi firmare una stringa usando questa chiave, procedi come segue:

Passaggio 1: converti il ​​testo che desideri crittografare

byte[] data = "test".getBytes("UTF8");

Passaggio 2: ottenere la chiave privata codificata base64

keyStore.load(keyStoreData, keyPassword);

//get cert, pubkey and private key from the store by alias
Certificate cert = keyStore.getCertificate("localhost");
PublicKey publicKey = cert.getPublicKey();
KeyPair keyPair = new KeyPair(publicKey, (PrivateKey) key);

//sign with this alg
Signature sig = Signature.getInstance("SHA1WithRSA");
sig.initSign(keyPair.getPrivate());
sig.update(data);
byte[] signatureBytes = sig.sign();
System.out.println("Signature:" + Base64.getEncoder().encodeToString(signatureBytes));

sig.initVerify(keyPair.getPublic());
sig.update(data);

System.out.println(sig.verify(signatureBytes));

Riferimenti:

  1. Come importare un certificato x509 esistente e una chiave privata nel keystore Java da utilizzare in SSL?
  2. http://tutorials.jenkov.com/java-cryptography/keystore.html
  3. http://www.java2s.com/Code/Java/Security/RetrievingaKeyPairfromaKeyStore.htm
  4. Come firmare la stringa con chiave privata

Programma finale

public static void main(String[] args) throws Exception {

    byte[] data = "test".getBytes("UTF8");

    // load keystore
    char[] keyPassword = "changeit".toCharArray();

    KeyStore keyStore = KeyStore.getInstance("JKS");
    //System.getProperty("user.dir") + "" < for a file in particular path 
    InputStream keyStoreData = new FileInputStream("keystore.jks");
    keyStore.load(keyStoreData, keyPassword);

    Key key = keyStore.getKey("localhost", keyPassword);

    Certificate cert = keyStore.getCertificate("localhost");

    PublicKey publicKey = cert.getPublicKey();

    KeyPair keyPair = new KeyPair(publicKey, (PrivateKey) key);

    Signature sig = Signature.getInstance("SHA1WithRSA");

    sig.initSign(keyPair.getPrivate());
    sig.update(data);
    byte[] signatureBytes = sig.sign();
    System.out.println("Signature:" + Base64.getEncoder().encodeToString(signatureBytes));

    sig.initVerify(keyPair.getPublic());
    sig.update(data);

    System.out.println(sig.verify(signatureBytes));
}

1

Basta creare un keystore PKCS12, Java può usarlo direttamente ora. Infatti, se si elenca un keystore in stile Java, lo stesso keytool avvisa che PKCS12 è ora il formato preferito.

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

Dovresti aver ricevuto tutti e tre i file (server.crt, server.key, ca.crt) dal tuo fornitore di certificati. Non sono sicuro di cosa significhi "root -caname", ma sembra che debba essere specificato in questo modo.

Nel codice Java, assicurarsi di specificare il tipo di archivio chiavi corretto.

KeyStore.getInstance("PKCS12")

Ho ottenuto che il mio certificato SSL rilasciato.com comodo funzionasse bene in NanoHTTPD in questo modo.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.