This guide will walk you through signing your java code using a legitimate certificate (instead of a self-signed certificate).

Step 1: Generate a key pair

You will need to generate a key as well as a certificate signing request (CSR). You must keep your key private. The CSR will be sent to the certificate authority (such as DigiCert for them to sign.

First, we need to generate a key/certificate pair and store it in a java key store. Make sure you specify actual values for -storepass and -keypass, which are the passwords for the keystore, and the keypair, respectively.

$ keytool -genkey -alias acme -keyalg RSA -keysize 2048 \
    -keystore mykeystore.jks \
    -storepass "changeme123" \
    -keypass "password123" \
    -dname "CN=Acme Company, O=Acme Company, L=New York City, ST=New York, C=US" 

This will create the file mykeystore.jks which will contain a single keypair under the alias of acme. Right now, you have a self-signed certificate. When a user tries to start your program, they will be shown an error saying that the code was signed by an untrusted source. This is what we want to prevent.

Step 2: Generate a certificate signing request

Next, you will need to generate the CSR that can be sent to the certificate authority. The following command will export a CSR corresponding with the keypair that was generated above. You will be prompted to enter the keystore password (-storepass) as well as the key password for “acme” (-keypass).

$ keytool -certreq -alias acme -file acme_csr.csr -keystore mykeystore.jks

You now have a file called acme_csr.csr. You will send this to the certificate authority of your choice and they will sign it. You may be offered the option of various formats for them to give you the signed certificate in. I find the easiest is a single .p7b file with the entire certificate chain added.

Step 3: Import certificate authority reply

Now that you have your .p7b file (we will call it acme_certs.p7b) from the certificate authority, you need to import it into your keystore. Currently in your keystore, you have a key and a certificate (that form a “keypair”). The key must remain, but we want to overwrite the self-signed certificate with the certificate from the certificate authority.

To inspect the response, and make sure we have the certificate we need, you can run the following command:

$ openssl pkcs7 -in acme_certs.p7b -print_certs

Scroll to the top, and you should see subject=CN=Acme Company/O=Acme Company/L=New York City/ST=New York/C=US. If you do not see this anywhere in the output, then you have the wrong certificate or something went horribly wrong.

Once we verified we have the correct certificate, we need to import the reply. To import the response, run the following command:

$ keytool -import -trustcacerts -alias acme -file acme_certs.p7b -keystore mykeystore.jks

Step 4: Convert Java keystore to PFX (optional)

This step is only needed if you want to sign executables for Windows. Microsoft code-signing uses a .pfx file which is a PKCS12 keystore. (A PKCS12 keystore is very similar to Java’s keystore except that it only stores a single keypair).

To convert from your JKS to PFX, do the following:

$ keytool -importkeystore \
    -srckeystore mykeystore.jks -srcstoretype JKS \
    -destkeystore mykeystore.pfx -deststoretype PKCS12

You now have an acceptable certificate that can be used to sign JAR files and executables.