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:<ol><li>
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</li> <li>
Generate the CSR:
keytool -certreq -alias tomcat -file request.csr -keystore test.keystore -storepass changeit</li> <li>
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</li> <li>
Generate my signed cert using the CSR:
openssl x509 -req -days 365 -in request.csr -signkey server.key -out server.crt</li> <li>
Finally, import the cert into my keystore.
keytool -import -trustcacerts -file server.crt -keystore test.keystore -alias tomcat -storepass changeit</li> </ol>
The result is the following error:<blockquote>
keytool error: java.lang.Exception: Public keys in reply and keystore don't match</blockquote> Answer1:
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.<ol><li>Generate the keystore</li> </ol><blockquote>
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</blockquote> <ol start="2"><li>Generate the CSR</li> </ol><blockquote>
keytool -certreq -alias tomcat -file request.csr -keystore test.keystore -storepass changeit</blockquote> <ol start="3"><li>Export the private key from my keystore for use in creating a signed cert</li> </ol><blockquote>
keytool -v -importkeystore -srckeystore test.keystore -srcalias tomcat -destkeystore myp12file.p12 -deststoretype PKCS12
openssl pkcs12 -in myp12file.p12 -out server.key</blockquote> <ol start="4"><li>Create the signed cert from the CSR</li> </ol><blockquote>
openssl x509 -req -days 365 -in request.csr -signkey server.key -out server.crt</blockquote> <ol start="5"><li>Finally import it to the keystore, with success</li> </ol><blockquote>
keytool -import -trustcacerts -file server.crt -keystore test.keystore -alias tomcat -storepass changeit</blockquote> Answer2:
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 <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html#keytool_option_genkeypair" rel="nofollow">documentation</a>:<blockquote>
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.</blockquote>
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</blockquote>
As the <a href="https://www.openssl.org/docs/apps/x509.html" rel="nofollow">documentation for
openssl x509 -signkey</a> states:
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.
<strong>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.</strong></blockquote>
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, <a href="https://www.openssl.org/docs/apps/ca.html" rel="nofollow">
openssl ca</a> would certainly be more relevant, although I would suggest using the <a href="https://www.openssl.org/docs/apps/CA.pl.html" rel="nofollow">
CA.pl</a> 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 <a href="http://xca.sourceforge.net/" rel="nofollow">xca</a> to be more convenient to perform that step.Answer3:
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.<h3>Create private key and <em>Certificate Signing Request</em></h3>
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:<blockquote>
$ OLD_UMASK=`umask` (umask is inside backtick characters) $ umask 077</blockquote>
Create a private key of 2048 bits length and store it in file
$ openssl genrsa 2048 > private_key.pem</blockquote>
Restore the file creation mask:<blockquote>
$ umask $OLD_MASK</blockquote>
You can create a Certificate Signing Request (CSR) with the command:<blockquote>
$ openssl req -new -key private_key.pem -nodes</blockquote>
Next you will have to answer various questions. Give special attention to the <em>Common Name</em> field that must match the <em>Fully Qualified Domain Name</em> of your server. The command generates the following text that comprises the CSR:<blockquote>
-----BEGIN CERTIFICATE REQUEST-----
-----END CERTIFICATE REQUEST-----</blockquote> <h3>Generate a chain certificate</h3>
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
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_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</blockquote>
The chain certificate is generated by combining
certificate.pem with the
$ cat certificate.pem ca_chain_cert.pem > chain.pem</blockquote>
The concept is that you must have a file that includes all certificates with the order:<ol><li>host certificate</li> <li>CA certificate</li> <li>CA1 certificate</li> <li>root CA certificate</li> </ol><h3>Generate the JKS keystore</h3>
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</blockquote>
Write down the <em>Export password</em> 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</blockquote>
You can list the certificates with the following command:<blockquote>
$ keytool -list -v -keystore server.keystore</blockquote>
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.