Làm cách nào để nhập chứng chỉ X.509 và khóa riêng trong kho khóa Java để sử dụng trong SSL?


228

Tôi có cái này trong cấu hình ActiveMQ:

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

Tôi có một cặp chứng chỉ X.509 và một tệp chính.

Làm cách nào để nhập hai cái đó để sử dụng chúng trong các trình kết nối SSL và SSL +? Tất cả các ví dụ tôi có thể google luôn tự tạo khóa, nhưng tôi đã có khóa.

Tôi đã thử

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

nhưng điều này chỉ nhập chứng chỉ chứ không phải tệp chính và kết quả là

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.

Tôi đã thử ghép chứng chỉ và khóa nhưng nhận được kết quả tương tự.

Làm cách nào để nhập khóa?


1
Bạn thực sự phải viết một chút mã để làm điều này và các chi tiết phụ thuộc vào định dạng của khóa riêng mà bạn đang cố gắng nhập. Định dạng nào là chìa khóa của bạn? Bạn có thể giải thích những công cụ bạn đã sử dụng để tạo khóa và chứng chỉ mà bạn có không?
erickson

Đối với SSL hai chiều (chứng chỉ máy khách và máy chủ) với Spring Boot, hãy xem stackoverflow.com/a/59317888/548473
Grigory Kislin

Câu trả lời:


73

Dù tin hay không, keytool không cung cấp chức năng cơ bản như nhập khóa riêng vào kho khóa. Bạn có thể thử cách giải quyết này với việc hợp nhất tệp PKSC12 với khóa riêng vào kho khóa.

Hoặc chỉ sử dụng KeyMan thân thiện với người dùng hơn từ IBM để xử lý kho khóa thay vì keytool.exe.


11
Theo keytool câu trả lời của CoverosGene hỗ trợ nó kể từ Java 6. Đây là liên kết mà anh ấy cung cấp
Houtman

Đối với những gì đáng giá, đối với tất cả sự ồn ào về chủ đề này, liên kết tốt nhất là liên kết 'giải pháp' của @ Matej với bài đăng năm 2008 này: cucky.sharp.fm/2008/06/importing_private_keys_into_a.html
cloudurfin

2
Tôi đã làm theo câu trả lời được cung cấp bởi CoverosGene và nó đã hoạt động.
Robert3452

1
KeyMan dường như không thân thiện với tôi lắm.
Linh tinh

15
Liên kết bị hỏng. Vui lòng bao gồm các chi tiết của giải pháp trực tiếp vào câu trả lời :-(
lilalinux

536

Tôi đã sử dụng hai bước sau đây mà tôi tìm thấy trong các nhận xét / bài đăng được liên kết trong các câu trả lời khác:

Bước một: Chuyển đổi chứng chỉ x.509 và khóa thành tệp pkcs12

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

Lưu ý: Đảm bảo bạn đặt mật khẩu vào tệp pkcs12 - nếu không, bạn sẽ nhận được ngoại lệ con trỏ null khi bạn cố gắng nhập mật khẩu. (Trong trường hợp bất cứ ai khác bị đau đầu này). ( Cảm ơn vui vẻ! )

Lưu ý 2: Bạn có thể muốn thêm -chaintùy chọn để bảo toàn chuỗi chứng chỉ đầy đủ. ( Cảm ơn Mafuba )

Bước hai: Chuyển đổi tệp pkcs12 sang kho khóa Java

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

Đã kết thúc

TÙY CHỌN Bước không: Tạo chứng chỉ tự ký

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

Chúc mừng!


12
Đảm bảo bạn đặt mật khẩu vào tệp p12 - nếu không, bạn sẽ nhận được ngoại lệ tham chiếu null khi bạn cố gắng nhập mật khẩu. (Trong trường hợp bất kỳ ai khác bị đau đầu này)
vui đùa

9
Trong trường hợp của tôi ở bước một, tùy chọn -CAfile ca.crt -caname rootkhông xuất chính xác các chứng chỉ CA. Thay vào đó tôi đã sử dụng-certfile concatenedCAFiles.pem
dcernahoschi

11
Đừng quên sử dụng -chainđối số với openssl để bao gồm chuỗi chứng chỉ đầy đủ trong tệp pfx / p12 của bạn nếu bạn muốn điều đó trong kho lưu trữ khóa của mình.
Mafuba

3
Trong môi trường Windows, pvk2pfx(một công cụ VS tiêu chuẩn có sẵn trong cmddấu nhắc VS ) sẽ tạo ra một .pfxtương đương với a .p12. Lời khuyên của @ jocull vẫn có liên quan; đặt mật khẩu vào nó Không opensslcần thiết.
Ben Mosher

9
Đối với Tomcat nói riêng, bắt buộc là kho khóa và mật khẩu chính giống nhau. Khi bạn nhập .p12khóa, mật khẩu của .p12.Tomcat ban đầu sẽ bị lỗi java.security.UnrecoverableKeyException: Cannot recover key. Nói cách khác: nếu bạn cần thực thi -deststorepass changeit -srcstorepass some-passwordvới các mật khẩu khác nhau , thì bạn phải bao gồm -destkeypass changeit(có cùng mật khẩu với -deststorepass)
Slav

127

Keytool trong Java 6 không có khả năng này: Nhập khóa riêng vào kho khóa Java bằng keytool

Dưới đây là các chi tiết cơ bản từ bài viết đó.

  1. Chuyển đổi chứng chỉ hiện có sang PKCS12 bằng OpenSSL. Mật khẩu là bắt buộc khi được hỏi hoặc bước 2 sẽ khiếu nại.

    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. Chuyển đổi PKCS12 thành tệp 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]

4
Câu trả lời của @reto chứa nội dung của liên kết này.
Mafuba

4
Như @Mafuba đã nêu, bạn vẫn phải tạo một kho khóa pkcs12 riêng biệt với công cụ không phải java như openssl - sau đó có thể được nhập vào một cửa hàng jks bằng keytool như được nêu trong câu trả lời bằng reto.
Mister_Tom

Một điều làm cho câu trả lời tốt này là thực tế là các certs đầu vào được chỉ định rõ ràng trong ngoặc.
Mr.Budris

FWIW, đầu ra của bước 1 phải có thể sử dụng được như là kho khóa Java (vì vậy bước 2 có thể không bắt buộc - trừ khi bạn không cần nhập khóa cert + vào kho khóa hiện có ) - như đã được đề cập trong câu trả lời trước của @ jaco0646
Janaka Bandara

9

Và một cái nữa:

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

Đầu tiên chuyển đổi sang p12:

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

Tạo JKS mới từ p12:

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

8

Vâng, thực sự đáng buồn là keytool không có chức năng nhập khóa riêng.

Đối với hồ sơ, cuối cùng tôi đã đi với giải pháp được mô tả ở đây


6

Trong trường hợp của tôi, tôi đã có một tệp pem chứa hai chứng chỉ và khóa riêng được mã hóa để sử dụng trong xác thực SSL lẫn nhau. Vì vậy, tập tin pem của tôi trông như thế này:

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

Đây là những gì tôi đã làm:

Chia tệp thành ba tệp riêng biệt, sao cho mỗi tệp chỉ chứa một mục nhập, bắt đầu bằng "--- BEGIN .." và kết thúc bằng dòng "--- END ..". Giả sử bây giờ chúng ta có ba tệp: cert1.pem cert2.pem và pkey.pem

Chuyển đổi pkey.pem sang định dạng DER bằng openssl và cú pháp sau:

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

Lưu ý rằng nếu khóa riêng được mã hóa, bạn cần cung cấp mật khẩu (lấy từ nhà cung cấp tệp pem gốc) để chuyển đổi sang định dạng DER, openssl sẽ yêu cầu bạn nhập mật khẩu như sau: "nhập mật khẩu cho pkey .pem: "Nếu chuyển đổi thành công, bạn sẽ nhận được một tệp mới có tên là" pkey.der "

Tạo một kho lưu trữ khóa java mới và nhập khóa riêng và chứng chỉ:

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

(tùy chọn) Xác minh nội dung của kho lưu trữ khóa mới của bạn:

keytool -list -keystore mykeystore -storepass password

Loại kho khóa: JKS Nhà cung cấp khóa: SUN

Kho khóa của bạn chứa 3 mục

cn = ..., ou = ..., o = .., ngày 2 tháng 9 năm 2014, TrustedCertEntry, Chứng nhận dấu vân tay (SHA1): 2C: B8: ...

importkey, ngày 2 tháng 9 năm 2014, PrivateKeyEntry, Dấu vân tay (SHA1): 9C: B0: ...

cn = ..., o = ...., ngày 2 tháng 9 năm 2014, TrustedCertEntry, Chứng chỉ vân tay (SHA1): 83:63: ...

(tùy chọn) Kiểm tra chứng chỉ và khóa riêng từ kho lưu trữ khóa mới của bạn với máy chủ SSL của bạn: (Bạn có thể muốn bật gỡ lỗi dưới dạng tùy chọn 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..

Cuối cùng đăng ký chứng chỉ của bạn với HttpsURLCconnectection nếu có kế hoạch sử dụng nó:

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

Tuy nhiên, Bruno đã đề cập rằng trình xác minh tên máy chủ này là sai: "Trình xác minh tên máy chủ của bạn sai, session.getPeerhost () không trả lại tên trong chứng chỉ, nhưng tên bạn đã kết nối với (ví dụ: urlhostName ở đây), vì vậy điều đó luôn diễn ra thành sự thật. Dù sao bạn cũng luôn trở về đúng. - Bruno ". Nó làm việc cho tôi mặc dù, nhưng tôi sẽ đánh giá cao nếu ai đó chỉ cho tôi cách viết trình xác minh tên máy chủ tốt.
Interkot

1
Tất nhiên nó sẽ "làm việc" cho bạn, vì nó sẽ không bao giờ gây ra lỗi, ngay cả khi cần. Để lại trình xác minh tên máy chủ mặc định được sử dụng HttpsURLConnectionthay vì cố gắng tự viết. (Một vấn đề khác với ví dụ của bạn là bạn đang sử dụng các keystore giống như một keystore và truststore, mà không phải là luôn luôn là một ý tưởng tốt ...)
Bruno

6

Sử dụng chứng chỉ Let Encrypt

Giả sử bạn đã tạo chứng chỉ và khóa riêng với Let Encrypt in /etc/letsencrypt/live/you.com:

1. Tạo tệp PKCS # 12

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

Điều này kết hợp chứng chỉ SSL fullchain.pemvà khóa riêng của bạn privkey.pemthành một tệp duy nhất , pkcs.p12.

Bạn sẽ được nhắc nhập mật khẩu pkcs.p12.

Các exportquy định cụ thể tùy chọn một file PKCS # 12 sẽ được tạo ra chứ không phải là phân tích cú pháp (từ hướng dẫn ).

2. Tạo kho khóa Java

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

Nếu keystore.jkskhông tồn tại, nó sẽ được tạo có chứa pkcs.12tệp được tạo ở trên. Nếu không, bạn sẽ nhập pkcs.12vào kho khóa hiện có.


Các hướng dẫn này được bắt nguồn từ bài viết trên blog này .

Đây là nhiều hơn về các loại tập tin khác nhau trong /etc/letsencrypt/live/you.com/.


5

Dựa trên các câu trả lời ở trên, đây là cách tạo kho khóa hoàn toàn mới cho máy chủ web dựa trên java của bạn, ngoài chứng chỉ Comodo và khóa riêng được tạo độc lập bằng keytool (yêu cầu JDK 1.6+)

  1. Dùng lệnh này và tại dấu nhắc mật khẩu, hãy nhập somepass - 'server.crt' là chứng chỉ của máy chủ của bạn và 'server.key' là khóa riêng mà bạn đã sử dụng để cấp 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. Sau đó sử dụng keytool để chuyển đổi kho khóa p12 thành kho khóa jks: keytool -importkeystore -deststorepass somepass -destkeypass somepass -destkeystore keystore.jks -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass somepass

Sau đó nhập hai certs gốc / trung gian khác mà bạn nhận được từ Comodo:

  1. Nhập COMODORSAAddTrustCA.crt: keytool -import -trustcacerts -alias cert1 -file COMODORSAAddTrustCA.crt -keystore keystore.jks

  2. Nhập COMODORSADomainValidationSecureServerCA.crt: keytool -import -trustcacerts -alias cert2 -file COMODORSADomainValidationSecureServerCA.crt -keystore keystore.jks


4

Bạn có thể sử dụng các bước này để nhập khóa vào kho khóa hiện có. Các hướng dẫn được kết hợp từ câu trả lời trong chủ đề này và các trang web khác. Các hướng dẫn này đã làm việc cho tôi (kho khóa java):

  1. Chạy

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

(Nếu được yêu cầu, hãy đặt tùy chọn -chain. Đặt thất bại cho tôi). Điều này sẽ yêu cầu mật khẩu - bạn phải cung cấp mật khẩu chính xác nếu không bạn sẽ gặp lỗi (lỗi tiêu đề hoặc lỗi đệm, v.v.).

  1. Nó sẽ yêu cầu bạn nhập mật khẩu mới - bạn phải nhập mật khẩu tại đây - nhập bất cứ thứ gì nhưng hãy nhớ nó. (Hãy để chúng tôi giả sử bạn nhập Aragorn).
  2. Điều này sẽ tạo tệp server.p12 ở định dạng pkcs.
  3. Bây giờ để nhập tệp vào *.jkstệp chạy:
    keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -destkeystore yourexistingjavakeystore.jks -deststoretype JKS -deststorepass existingjavastorepassword -destkeypass existingjavastorepassword
    (Rất quan trọng - đừng bỏ qua các thông số Deststorepass và Destkeypass.)
  4. Nó sẽ hỏi bạn mật khẩu lưu trữ khóa src. Nhập Aragorn và nhấn enter. Chứng chỉ và khóa hiện được nhập vào kho khóa java hiện có của bạn.

3

Các câu trả lời trước chỉ ra một cách chính xác rằng bạn chỉ có thể làm điều này với các công cụ JDK tiêu chuẩn bằng cách chuyển đổi tệp JKS thành định dạng PKCS # 12 trước tiên. Nếu bạn quan tâm, tôi kết hợp một tiện ích nhỏ gọn để nhập các khóa có nguồn gốc OpenSSL vào kho khóa có định dạng JKS mà không phải chuyển đổi kho khóa thành PKCS # 12 trước: http://commandlinefanatic.com/cgi-bin/showarticle. cgi? bài viết = art049

Bạn sẽ sử dụng tiện ích được liên kết như thế này:

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

(ký CSR, lấy lại 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

Chỉ cần liên kết đến thư viện của riêng bạn (hoặc tiện ích) không phải là một câu trả lời tốt. Liên kết với nó, giải thích lý do tại sao nó giải quyết vấn đề, cung cấp mã sử dụng nó để làm như vậy và từ chối làm cho câu trả lời tốt hơn. Xem: Làm thế nào tôi có thể liên kết với một nguồn tài nguyên bên ngoài theo cách thân thiện với cộng đồng?
Mogsdad

Không chắc ý của bạn là "từ chối", nhưng tôi đã thêm một ví dụ.
Joshua Davies

Tuyệt quá! Đó là một nhận xét đóng hộp, vì vậy một phần không được áp dụng - từ chối nghĩa là báo cáo sự liên kết của bạn với sản phẩm hoặc dịch vụ được liên kết, mà bạn đã làm với "Tôi kết hợp lại với nhau ..."
Mogsdad 3/03/2016

3

Nếu bạn có tệp PEM (ví dụ server.pem) có chứa:

  • chứng chỉ tin cậy
  • khóa riêng

sau đó bạn có thể nhập chứng chỉ và khóa vào kho khóa JKS như thế này:

1 ) Sao chép khóa riêng từ tệp PEM vào tệp ascii (ví dụ server.key)

2 ) Sao chép chứng chỉ từ tệp PEM vào tệp ascii (ví dụ server.crt)

3 ) Xuất chứng chỉ và khóa thành tệp PKCS12:

$ openssl pkcs12 -export -in server.crt -inkey server.key \
                 -out server.p12 -name [some-alias] -CAfile server.pem -caname root
  • tệp PEM có thể được sử dụng làm đối số cho -CAfiletùy chọn .
  • bạn được nhắc nhập mật khẩu 'xuất'.
  • nếu làm điều này trong git bash thì hãy thêm winptyvào đầu lệnh để có thể nhập mật khẩu xuất.

4 ) Chuyển đổi tệp PKCS12 sang kho khóa JKS:

$ keytool -importkeystore -deststorepass changeit -destkeypass changeit \
          -destkeystore keystore.jks  -srckeystore server.p12 -srcstoretype PKCS12 \
          -srcstorepass changeit
  • các srcstorepassmật khẩu phải phù hợp với mật khẩu xuất khẩu từ bước 3)

3

Những gì tôi đã cố gắng đạt được là sử dụng khóa riêng và chứng chỉ đã được cung cấp để ký tin nhắn đang diễn ra ở một nơi nào đó cần thiết để đảm bảo rằng tin nhắn đến từ tôi (ký hiệu khóa riêng trong khi mã hóa khóa công khai).

Vậy nếu bạn đã có tệp .key và tệp .crt?

Thử cái này:

Bước 1: Chuyển đổi khóa và cert thành tệp .p12

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

Bước 2: Nhập khóa và tạo tệp .jsk bằng một lệnh duy nhất

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

Bước 3: Trong java của bạn:

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

Nếu bạn cần ký một số chuỗi bằng phím này, hãy làm như sau:

Bước 1: Chuyển đổi văn bản bạn muốn mã hóa

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

Bước 2: Nhận khóa riêng được mã hóa 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));

Người giới thiệu:

  1. Làm cách nào để nhập chứng chỉ x509 và khóa riêng trong kho khóa Java để sử dụng trong SSL?
  2. http://tutorials.jenkov.com/java-cryptography/keystore.html
  3. http://www.java2s.com/Code/Java/Security/RetrievingaKeyPairfromaKeyStore.htmlm
  4. Cách ký chuỗi bằng khóa riêng

Chương trình cuối cùng

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

Chỉ cần tạo kho khóa PKCS12, Java có thể sử dụng trực tiếp ngay bây giờ. Trong thực tế, nếu bạn liệt kê một kho khóa kiểu Java, chính keytool sẽ cảnh báo bạn về thực tế rằng PKCS12 hiện là định dạng ưa thích.

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

Bạn đã nhận được cả ba tệp (server.crt, server.key, ca.crt) từ nhà cung cấp chứng chỉ của bạn. Tôi không chắc chắn "rootcan" thực sự có nghĩa là gì, nhưng dường như nó phải được chỉ định theo cách đó.

Trong mã Java, đảm bảo chỉ định đúng loại kho khóa.

KeyStore.getInstance("PKCS12")

Tôi đã nhận được chứng chỉ SSL do comodo.com cấp của tôi hoạt động tốt trong NanoHTTPD theo cách này.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.