How to import an existing X.509 certificate and private key in Java keystore to use in SSL?

前端 未结 15 859
说谎
说谎 2020-11-22 08:05

I have this in an ActiveMQ config:


        

        
相关标签:
15条回答
  • 2020-11-22 08:13

    And one more:

    #!/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"
    
    0 讨论(0)
  • 2020-11-22 08:17

    Keytool in Java 6 does have this capability: Importing private keys into a Java keystore using keytool

    Here are the basic details from that post.

    1. Convert the existing cert to a PKCS12 using OpenSSL. A password is required when asked or the 2nd step will complain.

      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. Convert the PKCS12 to a Java Keystore File.

      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]
      
    0 讨论(0)
  • 2020-11-22 08:17

    In my case I had a pem file which contained two certificates and an encrypted private key to be used in mutual SSL authentication. So my pem file looked like this:

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

    Here is what I did:

    Split the file into three separate files, so that each one contains just one entry, starting with "---BEGIN.." and ending with "---END.." lines. Lets assume we now have three files: cert1.pem cert2.pem and pkey.pem

    Convert pkey.pem into DER format using openssl and the following syntax:

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

    Note, that if the private key is encrypted you need to supply a password( obtain it from the supplier of the original pem file ) to convert to DER format, openssl will ask you for the password like this: "enter a pass phraze for pkey.pem: " If conversion is successful, you will get a new file called "pkey.der"

    Create a new java key store and import the private key and the certificates:

    String keypass = "password";  // this is a new password, you need to come up with to protect your java key store file
    String defaultalias = "importkey";
    KeyStore ks = KeyStore.getInstance("JKS", "SUN");
    
    // this section does not make much sense to me, 
    // but I will leave it intact as this is how it was in the original example I found on internet:   
    ks.load( null, keypass.toCharArray());
    ks.store( new FileOutputStream ( "mykeystore"  ), keypass.toCharArray());
    ks.load( new FileInputStream ( "mykeystore" ),    keypass.toCharArray());
    // end of section..
    
    
    // read the key file from disk and create a PrivateKey
    
    FileInputStream fis = new FileInputStream("pkey.der");
    DataInputStream dis = new DataInputStream(fis);
    byte[] bytes = new byte[dis.available()];
    dis.readFully(bytes);
    ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
    
    byte[] key = new byte[bais.available()];
    KeyFactory kf = KeyFactory.getInstance("RSA");
    bais.read(key, 0, bais.available());
    bais.close();
    
    PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key );
    PrivateKey ff = kf.generatePrivate (keysp);
    
    
    // read the certificates from the files and load them into the key store:
    
    Collection  col_crt1 = CertificateFactory.getInstance("X509").generateCertificates(new FileInputStream("cert1.pem"));
    Collection  col_crt2 = CertificateFactory.getInstance("X509").generateCertificates(new FileInputStream("cert2.pem"));
    
    Certificate crt1 = (Certificate) col_crt1.iterator().next();
    Certificate crt2 = (Certificate) col_crt2.iterator().next();
    Certificate[] chain = new Certificate[] { crt1, crt2 };
    
    String alias1 = ((X509Certificate) crt1).getSubjectX500Principal().getName();
    String alias2 = ((X509Certificate) crt2).getSubjectX500Principal().getName();
    
    ks.setCertificateEntry(alias1, crt1);
    ks.setCertificateEntry(alias2, crt2);
    
    // store the private key
    ks.setKeyEntry(defaultalias, ff, keypass.toCharArray(), chain );
    
    // save the key store to a file         
    ks.store(new FileOutputStream ( "mykeystore" ),keypass.toCharArray());
    

    (optional) Verify the content of your new key store:

    keytool -list -keystore mykeystore -storepass password

    Keystore type: JKS Keystore provider: SUN

    Your keystore contains 3 entries

    cn=...,ou=...,o=.., Sep 2, 2014, trustedCertEntry, Certificate fingerprint (SHA1): 2C:B8: ...

    importkey, Sep 2, 2014, PrivateKeyEntry, Certificate fingerprint (SHA1): 9C:B0: ...

    cn=...,o=...., Sep 2, 2014, trustedCertEntry, Certificate fingerprint (SHA1): 83:63: ...

    (optional) Test your certificates and private key from your new key store against your SSL server: ( You may want to enable debugging as an VM option: -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..
    

    Finally register your certificates with HttpsURLConnection if plan to use it:

            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);
    
    0 讨论(0)
  • 2020-11-22 08:19

    You can use these steps to import the key to an existing keystore. The instructions are combined from answers in this thread and other sites. These instructions worked for me (the java keystore):

    1. Run

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

    (If required put the -chain option. Putting that failed for me). This will ask for the password - you must give the correct password else you will get an error (heading error or padding error etc).

    1. It will ask you to enter a new password - you must enter a password here - enter anything but remember it. (Let us assume you enter Aragorn).
    2. This will create the server.p12 file in the pkcs format.
    3. Now to import it into the *.jks file run:
      keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -destkeystore yourexistingjavakeystore.jks -deststoretype JKS -deststorepass existingjavastorepassword -destkeypass existingjavastorepassword
      (Very important - do not leave out the deststorepass and the destkeypass parameters.)
    4. It will ask you for the src key store password. Enter Aragorn and hit enter. The certificate and key is now imported into your existing java keystore.
    0 讨论(0)
  • 2020-11-22 08:24

    Based on the answers above, here is how to create a brand new keystore for your java based web server, out of an independently created Comodo cert and private key using keytool (requires JDK 1.6+)

    1. Issue this command and at the password prompt enter somepass - 'server.crt' is your server's cert and 'server.key' is the private key you used for issuing the 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. Then use keytool to convert the p12 keystore into a jks keystore: keytool -importkeystore -deststorepass somepass -destkeypass somepass -destkeystore keystore.jks -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass somepass

    Then import the other two root/intermediate certs you received from Comodo:

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

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

    0 讨论(0)
  • 2020-11-22 08:26

    I used the following two steps which I found in the comments/posts linked in the other answers:

    Step one: Convert the x.509 cert and key to a pkcs12 file

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

    Note: Make sure you put a password on the pkcs12 file - otherwise you'll get a null pointer exception when you try to import it. (In case anyone else had this headache). (Thanks jocull!)

    Note 2: You might want to add the -chain option to preserve the full certificate chain. (Thanks Mafuba)

    Step two: Convert the pkcs12 file to a Java keystore

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

    Finished

    OPTIONAL Step zero: Create self-signed certificate

    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
    

    Cheers!

    0 讨论(0)
提交回复
热议问题