0
votes

My objective is to use keytool to create a certificate signing request (CSR), then take that CSR and make an actual cert to add to the keystore, add it, such that SSL (HTTPS//my.site.com) will work. This is for testing purposes.

So far I have done the following steps:

  1. Generate a keystore for my CSR:

    keytool -genkey -dname "CN=test.com, OU=TEST, O=Test, L=TestCity, ST=Florida, C=US" -alias tomcat -keyalg RSA -keysize 2048 -keystore test.keystore -storepass changeit

  2. Generate the CSR:

    keytool -certreq -alias tomcat -file request.csr -keystore test.keystore -storepass changeit

  3. Generate a server key to use with openSSL to create a signed cert. This required a password "changeit" and then a conversion to remove the password for the server.key:

    openssl genrsa -des3 -out server.key 2048

    cp server.key server.key.org

    openssl rsa -in server.key.org -out server.key

  4. Generate my signed cert using the CSR:

    openssl x509 -req -days 365 -in request.csr -signkey server.key -out server.crt

  5. Finally, import the cert into my keystore.

    keytool -import -trustcacerts -file server.crt -keystore test.keystore -alias tomcat -storepass changeit

The result is the following error:

keytool error: java.lang.Exception: Public keys in reply and keystore don't match

3

3 Answers

0
votes

I am not sure the following is right, but it seems to work. Cobbling some steps together from various web sites, executing these commands generate a keystore that works for SSL connections via tomcat. It does it pieces parts which will let me test each piece of my system.

  1. Generate the keystore

keytool -genkey -dname "CN=test.com, OU=TEST, O=Test, L=TestCity, ST=Florida, C=US" -alias tomcat -keyalg RSA -keysize 2048 -keystore test.keystore -storepass changeit

  1. Generate the CSR

keytool -certreq -alias tomcat -file request.csr -keystore test.keystore -storepass changeit

  1. Export the private key from my keystore for use in creating a signed cert

keytool -v -importkeystore -srckeystore test.keystore -srcalias tomcat -destkeystore myp12file.p12 -deststoretype PKCS12

openssl pkcs12 -in myp12file.p12 -out server.key

  1. Create the signed cert from the CSR

openssl x509 -req -days 365 -in request.csr -signkey server.key -out server.crt

  1. Finally import it to the keystore, with success

keytool -import -trustcacerts -file server.crt -keystore test.keystore -alias tomcat -storepass changeit

0
votes

keytool -genkey -dname "CN=test.com, OU=TEST, O=Test, L=TestCity, ST=Florida, C=US" -alias tomcat

This does more than generating a key pair, it also generates a self-signed certificate with this DN, which is then used as a basis to generate a CSR with -certreq (it may sound odd, but a self-signed cert and a PKCS#10 CSR are actually very similar: the CSR is more or less a self-signed cert without the validity timestamps).

This is in the documentation:

-genkeypair

[...]

Generates a key pair (a public key and associated private key). Wraps the public key into an X.509 v3 self-signed certificate, which is stored as a single-element certificate chain. This certificate chain and the private key are stored in a new keystore entry identified by alias.

[...] This command was named -genkey in earlier releases.

What you would normally do when submitting the CSR to a CA is re-import the cert issued by the CA into the same alias (where your private key is), thereby overwriting that temporary self-signed certificate.

You can skip the steps with keytool -certreq and openssl: simply export the certificate with keytool, and re-import it a separate truststore to use with your Java clients if necessary.


If you want to simulate a CA, openssl x509 is not the command you should use:

openssl x509 -req -days 365 -in request.csr -signkey server.key -out server.crt

As the documentation for openssl x509 -signkey states:

-signkey filename

this option causes the input file to be self signed using the supplied private key.

If the input file is a certificate it sets the issuer name to the subject name (i.e. makes it self signed) changes the public key to the supplied value and changes the start and end dates. The start date is set to the current time and the end date is set to a value determined by the -days option. Any certificate extensions are retained unless the -clrext option is supplied.

If the input is a certificate request then a self signed certificate is created using the supplied private key using the subject name in the request.

So, essentially, the public key material also comes from this private key. Hence, it will not match the public key in the CSR you provided. The CSR is only used to provide the certificate identity information and attributes in this case.

Indeed, turning a CSR into a certificate is something that can have many parameters. While keytool generates a reasonable default self-signed certificate from the parameters you provide, OpenSSL generally requires a bit more configuration. For what you're trying to do, openssl ca would certainly be more relevant, although I would suggest using the CA.pl wrapper for convenience (it will keep track of the certificates you've issued, serial numbers, and so on).

Since this seems to be mainly for testing, possibly on an occasional basis, you may also find other tools like xca to be more convenient to perform that step.

0
votes

The following procedure describes the creation of a JKS keystore that works perfectly with JBoss 5.0 application server. Tomcat probably uses the same type of keystore.

Create private key and Certificate Signing Request

You can create a private key in a Linux OS with the help of openssl utility.

Set umask to 077 so that the created file is only readable by the current user:

$ OLD_UMASK=`umask`   (umask is inside backtick characters)
$ umask 077

Create a private key of 2048 bits length and store it in file private_key.pem:

$ openssl genrsa 2048 > private_key.pem

Restore the file creation mask:

$ umask $OLD_MASK

You can create a Certificate Signing Request (CSR) with the command:

$ openssl req -new -key private_key.pem -nodes

Next you will have to answer various questions. Give special attention to the Common Name field that must match the Fully Qualified Domain Name of your server. The command generates the following text that comprises the CSR:

-----BEGIN CERTIFICATE REQUEST-----

MIIBZYnPGQZK06tI6EKLGp7qmaFAIAe ...

....

-----END CERTIFICATE REQUEST-----

Generate a chain certificate

The procedure assumes that you have a (a) private key in file private_key.pem, (b) a digital certificate that you have received from a Certificate Authority (CA) in file certificate.pem and (c) a chain certificate that certifies the CA in file ca_chain_cert.pem.

In case that your CA is certified by another authority CA1 that is finally certified by a root CA CA_ROOT (CA -> CA1 -> CA_ROOT) and the respective certificates are available in individual files ca_cert.pem, ca1_cert.pem and ca_root.pem respectively, you can create the ca_chain_cert.pem through the command:

$ cat ca_cert.pem ca1_cert.pem ca_root.pem > ca_chain_cert.pem

The chain certificate is generated by combining certificate.pem with the ca_chain_cert.pem:

$ cat certificate.pem ca_chain_cert.pem > chain.pem

The concept is that you must have a file that includes all certificates with the order:

  1. host certificate
  2. CA certificate
  3. CA1 certificate
  4. root CA certificate

Generate the JKS keystore

This step assumes that file chain.pem includes the chain of certificates ,private_key.pem the private key and certificate.pem the server certificate that you received from the CA (first part of the chain).

Create a PKCS12 keystore in file keystore.p12 from the certificate chain and the private key with the following command:

$ openssl pkcs12 -export -name server_cert -in chain.pem -inkey private_key.pem -certfile certificate.pem -out keystore.p12

Write down the Export password as it will be used in all the following steps to have access to the keystore.

Create a JKS keystore in file server.keystore from the PKCS12 keystore:

$ keytool -importkeystore -destkeystore server.keystore -srckeystore keystore.p12 -srcstoretype pkcs12 -alias server_cert

You can list the certificates with the following command:

$ keytool -list -v -keystore server.keystore

Verify that the command output states the correct size of the certificate chain. In the case of CA, CA1 and CA_ROOT the size must be 4.