Bagaimana cara mengimpor sertifikat X.509 dan kunci pribadi yang ada di Java keystore untuk digunakan di SSL?

228

Saya memilikinya di konfigurasi ActiveMQ:

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

Saya memiliki sepasang sertifikat X.509 dan file kunci.

Bagaimana cara mengimpor keduanya untuk menggunakannya dalam konektor stomp SSL dan SSL +? Semua contoh saya bisa google selalu menghasilkan kunci sendiri, tetapi saya sudah punya kunci.

saya telah mencoba

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

tetapi ini hanya mengimpor sertifikat dan bukan file kunci dan menghasilkan

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.

Saya telah mencoba menggabungkan sertifikat dan kunci tetapi mendapatkan hasil yang sama.

Bagaimana cara mengimpor kunci?

Aleksandar Ivanisevic
sumber
1
Anda sebenarnya harus menulis sedikit kode untuk melakukan ini, dan detailnya tergantung pada format kunci pribadi yang Anda coba impor. Apa format kuncimu? Bisakah Anda menjelaskan alat apa yang Anda gunakan untuk membuat kunci dan sertifikat yang Anda miliki?
erickson
Untuk SSL dua arah (sertifikat klien dan server) dengan Spring Boot lihat stackoverflow.com/a/59317888/548473
Grigory Kislin

Jawaban:

73

Percaya atau tidak, keytool tidak menyediakan fungsionalitas dasar seperti mengimpor kunci pribadi ke keystore. Anda dapat mencoba solusi ini dengan menggabungkan file PKSC12 dengan kunci pribadi ke keystore.

Atau cukup gunakan lebih banyak KeyMan yang mudah digunakan dari IBM untuk penanganan keystore alih-alih keytool.exe.

Matej
sumber
11
Menurut keytool jawaban CoverosGene mendukungnya sejak Java 6. Ini adalah tautan yang ia berikan
Houtman
Untuk apa nilainya, untuk semua kebisingan pada subjek ini, tautan terbaik adalah tautan 'penyelesaian' @ @ Matej ke pos 2008 ini: cunning.sharp.fm/2008/06/importing_private_keys_into_a.html
cloudsurfin
2
Saya mengikuti jawaban yang diberikan oleh CoverosGene dan itu berhasil.
Robert3452
1
KeyMan sepertinya tidak ramah bagi saya.
Miscreant
15
Tautan rusak. Harap sertakan perincian solusi langsung ke jawaban :-(
lilalinux
536

Saya menggunakan dua langkah berikut yang saya temukan di komentar / posting yang tertaut dalam jawaban lain:

Langkah satu: Konversikan sertifikat x.509 dan kunci menjadi file pkcs12

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

Catatan: Pastikan Anda memasukkan kata sandi pada file pkcs12 - jika tidak, Anda akan mendapatkan pengecualian penunjuk nol saat Anda mencoba mengimpornya. (Kalau-kalau ada orang lain sakit kepala ini). ( Terima kasih jocull! )

Catatan 2: Anda mungkin ingin menambahkan -chainopsi untuk mempertahankan rantai sertifikat lengkap. ( Terima kasih, Mafuba )

Langkah dua: Konversikan file pkcs12 ke Java keystore

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

Jadi

OPSIONAL Langkah nol: Buat sertifikat yang ditandatangani sendiri

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

Bersulang!

reto
sumber
12
Pastikan Anda memasukkan kata sandi pada file p12 - jika tidak, Anda akan mendapatkan pengecualian referensi nol ketika Anda mencoba mengimpornya. (Kalau-kalau ada orang lain yang sakit kepala ini)
jocull
9
Dalam kasus saya pada langkah satu opsi -CAfile ca.crt -caname roottidak menghasilkan sertifikat CA dengan benar. Sebagai gantinya saya menggunakan-certfile concatenedCAFiles.pem
dcernahoschi
11
Jangan lupa untuk menggunakan -chainargumen dengan openssl untuk memasukkan rantai sertifikat lengkap dalam file pfx / p12 Anda jika Anda menginginkannya di penyimpanan kunci Anda.
Mafuba
3
Dalam lingkungan Windows, pvk2pfx(alat VS standar tersedia di VS cmdprompt) akan memuntahkan - .pfxsama dengan a .p12. Saran jocull masih relevan; letakkan kata sandi di atasnya. Tidak openssldibutuhkan
Ben Mosher
9
Untuk Tomcat khususnya, sangat penting bahwa keystore dan kata sandi utama sama. Ketika Anda mengimpor .p12kunci akan memiliki kata sandi .p12.Tomcat asli akan gagal java.security.UnrecoverableKeyException: Cannot recover key. Dengan kata lain: jika Anda perlu mengeksekusi -deststorepass changeit -srcstorepass some-passworddengan kata sandi yang berbeda , maka Anda harus memasukkan -destkeypass changeit(dengan kata sandi yang sama dengan -deststorepass)
Slav
127

Keytool di Java 6 memang memiliki kemampuan ini: Mengimpor kunci pribadi ke keystore Java menggunakan keytool

Berikut adalah rincian dasar dari pos itu.

  1. Konversikan sertifikat yang ada ke PKCS12 menggunakan OpenSSL. Kata sandi diperlukan saat ditanya atau langkah ke-2 akan mengeluh.

    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. Konversikan PKCS12 ke File Java Keystore.

    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]
CoverosGene
sumber
4
Jawaban oleh @reto berisi konten tautan ini.
Mafuba
4
Seperti yang dinyatakan oleh @Mafuba, Anda masih harus membuat keystore pkcs12 terpisah dengan alat non-java seperti openssl - maka ini dapat diimpor ke toko jks oleh keytool seperti yang dinyatakan dalam jawaban oleh reto.
Mister_Tom
Satu hal yang menjadikan ini jawaban yang bagus adalah kenyataan bahwa sertifikat input secara jelas ditentukan dalam tanda kurung.
Mr.Budris
FWIW, output dari langkah 1 seharusnya sudah dapat digunakan sebagai Java keystore (jadi langkah 2 mungkin tidak diperlukan - kecuali Anda memang perlu mengimpor kunci cert + ke dalam keystore yang ada ) - seperti yang telah disebutkan dalam jawaban sebelumnya oleh @ jaco0646
Janaka Bandara
9

Dan satu lagi:

#!/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"
David Tonhofer
sumber
9

Konversi pertama ke p12:

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

Buat JKS baru dari p12:

keytool -importkeystore -deststorepass [password] -destkeystore [filename-new-keystore.jks] -srckeystore [filename-new-PKCS-12.p12] -srcstoretype PKCS12
Michał Jurczuk
sumber
7

Ya, memang fakta yang menyedihkan bahwa keytool tidak memiliki fungsionalitas untuk mengimpor kunci pribadi.

Sebagai catatan, pada akhirnya saya pergi dengan solusi yang dijelaskan di sini

Aleksandar Ivanisevic
sumber
6

Dalam kasus saya, saya memiliki file pem yang berisi dua sertifikat dan kunci pribadi terenkripsi untuk digunakan dalam otentikasi SSL bersama. Jadi file pem saya terlihat seperti ini:

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

Inilah yang saya lakukan:

Bagi file menjadi tiga file terpisah, sehingga masing-masing berisi hanya satu entri, dimulai dengan "--- BEGIN .." dan diakhiri dengan baris "--- END ..". Mari kita asumsikan kita sekarang memiliki tiga file: cert1.pem cert2.pem dan pkey.pem

Ubah pkey.pem ke dalam format DER menggunakan openssl dan sintaks berikut:

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

Perhatikan, bahwa jika kunci pribadi dienkripsi, Anda perlu memberikan kata sandi (mendapatkannya dari pemasok file pem yang asli) untuk mengonversi ke format DER, openssl akan meminta kata sandi seperti ini: "masukkan pass phraze for pkey .pem: "Jika konversi berhasil, Anda akan mendapatkan file baru bernama" pkey.der "

Buat penyimpanan kunci java baru dan impor kunci pribadi dan sertifikat:

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

(opsional) Verifikasi konten penyimpanan kunci baru Anda:

keytool -list -keystore mykeystore -storepass password

Jenis Keystore: JKS Keystore provider: SUN

Keystore Anda berisi 3 entri

cn = ..., ou = ..., o = .., 2 Sep 2014, trustCertEntry, Sertifikat sidik jari (SHA1): 2C: B8: ...

importkey, 2 Sep 2014, PrivateKeyEntry, Sertifikat sidik jari (SHA1): 9C: B0: ...

cn = ..., o = ...., 2 Sep 2014, trustCertEntry, Sertifikat sidik jari (SHA1): 83:63: ...

(opsional) Uji sertifikat dan kunci pribadi Anda dari penyimpanan kunci baru Anda terhadap server SSL Anda: (Anda mungkin ingin mengaktifkan debugging sebagai opsi VM: -Djavax.net.debug = semua)

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

Akhirnya daftarkan sertifikat Anda dengan HttpsURLConnection jika berencana untuk menggunakannya:

        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);
Interkot
sumber
Namun, Bruno menyebutkan bahwa verifier nama host ini salah: "Verifikasi nama host Anda salah, session.getPeerHost () tidak mengembalikan nama dalam sertifikat, tetapi nama yang terhubung dengan Anda (yaitu urlHostName di sini), jadi itu selalu terjadi untuk menjadi kenyataan. Anda selalu kembali benar pula -. Bruno ". Itu bekerja untuk saya, tetapi saya akan sangat menghargai jika seseorang menunjukkan kepada saya bagaimana menulis verifier nama host yang baik.
Interkot
1
Tentu saja itu akan "bekerja" untuk Anda, karena itu tidak akan pernah menghasilkan kesalahan, bahkan ketika itu seharusnya. Biarkan verifier nama host default digunakan dengan HttpsURLConnectionalih-alih mencoba menulis milik Anda sendiri. (Masalah lain dengan contoh Anda adalah bahwa Anda menggunakan keystore yang sama dengan keystore dan truststore, yang tidak selalu merupakan ide yang baik ...)
Bruno
6

Menggunakan sertifikat Mari Enkripsi

Anggap Anda telah membuat sertifikat dan kunci pribadi Anda dengan Let's Encrypt di /etc/letsencrypt/live/you.com:

1. Buat PKCS # 12 File

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

Ini menggabungkan sertifikat SSL Anda fullchain.pemdan kunci pribadi Anda privkey.pemke dalam satu file pkcs.p12,.

Anda akan dimintai kata sandi untuk pkcs.p12.

The exportpilihan menetapkan bahwa PKCS # 12 file yang akan dibuat bukan diurai (dari manual ).

2. Buat keystore Java

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

Jika keystore.jkstidak ada, itu akan dibuat berisi pkcs.12file yang dibuat di atas. Jika tidak, Anda akan mengimpor pkcs.12keystore yang ada.


Instruksi ini berasal dari posting blog ini .

Berikut ini lebih banyak tentang berbagai jenis file di /etc/letsencrypt/live/you.com/.

Matthias Braun
sumber
5

Berdasarkan jawaban di atas, berikut adalah cara membuat keystore baru untuk server web berbasis java Anda, dari sertifikat Comodo yang dibuat secara independen dan kunci pribadi menggunakan keytool (memerlukan JDK 1.6+)

  1. Keluarkan perintah ini dan pada prompt kata sandi masukkan somepass - 'server.crt' adalah sertifikat server Anda dan 'server.key' adalah kunci pribadi yang Anda gunakan untuk mengeluarkan 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. Kemudian gunakan keytool untuk mengubah keystore p12 menjadi keystore jks: keytool -importkeystore -deststorepass somepass -destkeypass somepass -destkeystore keystore.jks -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass somepass

Kemudian impor dua sertifikat root / perantara lainnya yang Anda terima dari Comodo:

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

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

Fotios Basagiannis
sumber
4

Anda dapat menggunakan langkah-langkah ini untuk mengimpor kunci ke keystore yang ada. Instruksi digabungkan dari jawaban di utas ini dan situs lainnya. Instruksi ini bekerja untuk saya (keystore java):

  1. Lari

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

(Jika perlu letakkan opsi-rantai. Menempatkan itu gagal untuk saya). Ini akan meminta kata sandi - Anda harus memberikan kata sandi yang benar jika tidak Anda akan mendapatkan kesalahan (heading error atau padding error dll).

  1. Ia akan meminta Anda untuk memasukkan kata sandi baru - Anda harus memasukkan kata sandi di sini - masukkan apa pun kecuali ingatlah. (Biarkan kami menganggap Anda memasuki Aragorn).
  2. Ini akan membuat file server.p12 dalam format pkcs.
  3. Sekarang untuk mengimpornya ke *.jksfile run:
    keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -destkeystore yourexistingjavakeystore.jks -deststoretype JKS -deststorepass existingjavastorepassword -destkeypass existingjavastorepassword
    (Sangat penting - jangan tinggalkan parameter deststorepass dan destkeypass.)
  4. Ini akan menanyakan kata sandi penyimpanan kunci src. Masukkan Aragorn dan tekan enter. Sertifikat dan kunci sekarang diimpor ke java keystore Anda yang ada.
vanval
sumber
3

Jawaban sebelumnya menunjukkan dengan benar bahwa Anda hanya dapat melakukan ini dengan alat JDK standar dengan mengonversi file JKS ke format PKCS # 12 terlebih dahulu. Jika Anda tertarik, saya mengumpulkan utilitas ringkas untuk mengimpor kunci yang diturunkan dari OpenSSL ke dalam keystore berformat JKS tanpa harus mengonversi keystore menjadi PKCS # 12 terlebih dahulu: http://commandlinefanatic.com/cgi-bin/showarticle. cgi? article = art049

Anda akan menggunakan utilitas tertaut seperti ini:

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

(masuk CSR, dapatkan kembali 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
Joshua Davies
sumber
Hanya menautkan ke perpustakaan Anda sendiri (atau utilitas) bukanlah jawaban yang baik. Menautkannya, menjelaskan mengapa ini memecahkan masalah, menyediakan kode untuk menggunakannya, dan penafian membuat jawaban yang lebih baik. Lihat: Bagaimana saya bisa menautkan ke sumber daya eksternal dengan cara yang ramah komunitas?
Mogsdad
Tidak yakin apa yang Anda maksud dengan "disclaim", tetapi saya menambahkan contoh.
Joshua Davies
Bagus! Itu adalah komentar kalengan, jadi sebagian tidak berlaku - sanggahan berarti melaporkan afiliasi Anda dengan produk atau layanan yang ditautkan, yang Anda lakukan dengan "Saya mengumpulkan ..."
Mogsdad
3

Jika Anda memiliki file PEM (mis. server.pem) Yang berisi:

  • sertifikat tepercaya
  • kunci pribadi

maka Anda dapat mengimpor sertifikat dan kunci ke keystore JKS seperti ini:

1 ) Salin kunci pribadi dari file PEM ke file ascii (mis. server.key)

2 ) Salin sertifikat dari file PEM ke file ascii (mis. server.crt)

3 ) Ekspor sertifikat dan kunci ke file PKCS12:

$ openssl pkcs12 -export -in server.crt -inkey server.key \
                 -out server.p12 -name [some-alias] -CAfile server.pem -caname root
  • file PEM dapat digunakan sebagai argumen untuk -CAfileopsi .
  • Anda dimintai kata sandi 'ekspor'.
  • jika melakukan ini di git bash kemudian tambahkan winptyke awal perintah sehingga kata sandi ekspor dapat dimasukkan.

4 ) Konversikan file PKCS12 ke keystore JKS:

$ keytool -importkeystore -deststorepass changeit -destkeypass changeit \
          -destkeystore keystore.jks  -srckeystore server.p12 -srcstoretype PKCS12 \
          -srcstorepass changeit
  • yang srcstorepasssandi harus sesuai dengan sandi ekspor dari langkah 3)
Joman68
sumber
3

Apa yang saya coba capai adalah menggunakan kunci pribadi dan sertifikat yang sudah disediakan untuk menandatangani pesan yang akan dikirim ke suatu tempat yang perlu memastikan bahwa pesan itu datang dari saya (tanda kunci pribadi saat kunci publik mengenkripsi).

Jadi, jika Anda sudah memiliki file .key dan file .crt?

Coba ini:

Langkah1: Konversi kunci dan cert ke file .p12

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

Langkah 2: Impor kunci dan buat file .jsk dengan satu perintah

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

Langkah 3: Di java Anda:

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

Jika Anda perlu menandatangani beberapa string menggunakan kunci ini lakukan hal berikut:

Langkah 1: Konversi teks yang ingin Anda enkripsi

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

Langkah 2: Dapatkan kunci pribadi yang disandikan 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));

Referensi:

  1. Bagaimana cara mengimpor sertifikat x509 dan kunci pribadi yang ada di Java keystore untuk digunakan di SSL?
  2. http://tutorials.jenkov.com/java-cryptography/keystore.html
  3. http://www.java2s.com/Code/Java/Security/RetrievingaKeyPairfromaKeyStore.htm
  4. Cara menandatangani string dengan kunci pribadi

Program akhir

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));
}
Joe Mwa
sumber
1

Buat saja keystore PKCS12, Java dapat menggunakannya langsung sekarang. Bahkan, jika Anda mendaftar keystore gaya-Jawa, keytool sendiri mengingatkan Anda pada kenyataan bahwa PKCS12 sekarang merupakan format yang disukai.

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

Anda seharusnya menerima ketiga file (server.crt, server.key, ca.crt) dari penyedia sertifikat Anda. Saya tidak yakin apa arti "-caname root" sebenarnya, tetapi tampaknya harus ditentukan seperti itu.

Dalam kode Java, pastikan untuk menentukan jenis keystore yang tepat.

KeyStore.getInstance("PKCS12")

Saya mendapatkan sertifikat SSL yang dikeluarkan comodo.com saya bekerja dengan baik di NanoHTTPD dengan cara ini.

Stefan Reich
sumber