Skip to content

Instantly share code, notes, and snippets.

@elton-alves
Last active May 20, 2024 05:14
Show Gist options
  • Save elton-alves/871df55a00cc6b4759cafef496834406 to your computer and use it in GitHub Desktop.
Save elton-alves/871df55a00cc6b4759cafef496834406 to your computer and use it in GitHub Desktop.
Self signed certificates with keytool

Creating self signed certificates with keytool

Content

  1. Self signed certificate
  2. Multiple domain names
  3. Certificates for 2wayTLS
  4. Certificate chain

NOTE: Do not use self signed certificates in PRODUCTION, for that use a certificate signed by some CA (Certification Authority), and then avoid man-in-the-middle attack.

1. Self signed certificate

keytool -genkeypair -alias server \
-storetype PKCS12 \
-keyalg RSA -keysize 2048 \
-keystore server-keystore.p12 -storepass keystore-pass \
-dname "CN=server.mycompany.com,OU=My Company Dev Team,O=My Company,L=State,S=City,C=Country" \
-ext ku:c=dig,keyEncipherment \
-validity 365;

Command notes:

-genkeypair -alias server: Generate a keypair, private + public key in this keystore identified (alias) by 'server'

-keyalg RSA -keysize 2048: Key algorithm and size used for genkeypar

-storetype PKCS12: keystore format, PCKS12 is one of the most common format used by Certificate Authorities

-keystore server-keystore.p12 -storepass keystore-pass: keystore file name and password respectively

-validity 365: validate in days

-ext ku:c=dig,keyEncipherment: 'ku' from Key Usage, used for express what this certificate will be used for. These two are common key usage.

  1. 'dig': Digital Signature, used for data origin authentication
  2. 'keyEncipherment': Indicate that the public and private key will be used to encrypt key exchange.
  3. Other key usages and more details in 4

-dname "CN=server.mycompany.com,OU=My Company Dev Team,O=My Company,L=State,S=City,C=Country": inline for the follow keytool questions during the keypair generation:

What is your first and last name (CN)?
  [Unknown]: 
What is the name of your organizational unit (OU)?
  [Unknown]:  
What is the name of your organization (O)?
  [Unknown]:  
What is the name of your City or Locality (L)?
  [Unknown]:  
What is the name of your State or Province (S)?
  [Unknown]:  
What is the two-letter country code for this unit (C)?
  [Unknown]:  

A little attention for CN (Common Name), this property is general used to put host domain name. But seems that the usage of this field is deprecated 9.

2. Multiple domain names (quite useful)

The certificate host verification look for matches in Common Name (CN) property and in SubjectAlternativeName (SAN) property 6. Set it with the extension parameter highlight below:

keytool -genkeypair -keyalg RSA -keysize 2048 -storetype PKCS12 \
-keystore server-keystore.p12 -storepass keystore-pass \
-alias server-multi-domain \
-dname "CN=My Server,OU=My Company Dev Team,O=My Company,L=State,S=City,C=Country" \
-ext san=dns:server1.mycompany.com,dns:server2.mycompany.com,ip:198.164.8.1 \
-validity 365;

-ext san=dns:server1.mycompany.com,dns:server2.mycompany.com,ip:198.164.8.1: add 2 domains and 1 IP address that can be used as a validate server resource internet node.

Checking the server-multi-domain properties:

keytool -list -v -alias server-multi-domain -keystore server-keystore.p12 -storepass keystore-passAlias
name: server-multi-domain
...
Owner: CN=My Server, OU=My Company Dev Team, O=My Company, L=State, ST=City, C=Country
Issuer: CN=My Server, OU=My Company Dev Team, O=My Company, L=State, ST=City, C=Country
...
SubjectAlternativeName [
  DNSName: server1.mycompany.com
  DNSName: server2.mycompany.com
  IPAddress: 198.164.8.1
]
...

3. Certificates for 2wayTLS

A detail that may go unnoticed when using certificates for 2WayTLS is the ExtendedkeyUsage (eku). It is used to attribute different roles from KeyUsage, between then the ones need for 2wayTLS connection like serverAuth (sa) and clientAuth (ca). For that just add the extension -ext eku=sa like the example below:

keytool -genkeypair -keyalg RSA -keysize 2048 -storetype PKCS12 \
-keystore server-keystore.p12 -storepass keystore-pass \
-alias server-for-2wayTLS \
-dname "CN=My Server,OU=My Company Dev Team,O=My Company,L=State,S=City,C=Country" \
-ext eku=sa \
-ext ku:c=dig,keyEncipherment \
-validity 365;

Checking the certificate content:

~:$ keytool -list -v -alias server-for-2wayTLS -keystore server-keystore.p12 -storepass keystore-passAlias

name: server-for-2wayTLS
...
ExtendedKeyUsages [
  serverAuth
]

#2: ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
  DigitalSignature
  Key_Encipherment
]
...

For an application that works as a client: -ext eku=sa.

For both roles: -ext eku=sa,ca.

4. Certificate chain

Creating root and intermediate certificate

The certificates will be saved in truststore-ca.p12 keystore, just to be used as a "CA" reference, CA here means a root or a intermediate certificate.

Root CA

keytool \
-genkeypair -keyalg RSA -keysize 2048 -storetype PKCS12 \
-keystore truststore-ca.p12 -storepass keystore-pass \
-alias root-ca -ext bc=ca:true \
-dname "CN=root-ca.mycompany.com,OU=My Company Root CA,O=My Company,L=State,S=City,C=Country" \
-validity 365;

Command notes:

  1. The "root-ca" keypair is the self signed entity that will start the certification chain as root
  2. -ext bc=ca:true certificate extension indicating that this certificate is a CA

Checking root-ca keypair

keytool -list -alias root-ca -v -keystore truststore-ca.p12 -storepass keystore-pass
Alias name: root-ca
...
Certificate chain length: 1
Certificate[1]:
Owner: CN=root-ca.mycompany.com, OU=My Company Root CA, O=My Company, L=State, ST=City, C=Country
Issuer: CN=root-ca.mycompany.com, OU=My Company Root CA, O=My Company, L=State, ST=City, C=Country
...
BasicConstraints:[
  CA:true
  PathLen:2147483647
]
...

NOTE that the BasicConstrains indicate that root-ca can be used as CA (intermediate or root level in the certificate chain), and accept MAX_INTEGER amount of subordinates.

Intermediate CA

1. First create the keypair for the intermediate-ca.

No news here the command is almost the same as to generate the root-ca:

keytool -genkeypair -keyalg RSA -keysize 2048 -storetype PKCS12 \
-keystore truststore-ca.p12 -storepass keystore-pass \
-alias intermediate-ca -ext bc=ca:true \
-dname "CN=inter-ca.mycompany.com,OU=My Comp. Intermediate CA,O=My Company,L=State,S=City,C=Country" \
-validity 365;
2. Generate a CSR (certificate signing request) for intermediate-ca certificate.
keytool -certreq -alias intermediate-ca -file intermediate-ca.csr \
-keystore truststore-ca.p12 -storepass keystore-pass;

Command notes:

  1. -certreq: command to generate the csr
  2. -alias intermediate-ca: requesting the csr for the intermediate-ca
  3. -file intermediate-ca.csr: output file
3. Generate the intermediate-ca certificate signed by root-ca
keytool -gencert \
-infile intermediate-ca.csr -outfile intermediate-ca-cert.pem \
-alias root-ca \
-ext BC=0 \
-rfc \
-keystore truststore-ca.p12 -storepass keystore-pass;

Command notes:

  1. -gencert: command to generate the certificate (public key)
  2. -infile intermediate-ca.csr: based on intermediate-ca csr
  3. -outfile intermediate-ca-cert.pem: certificate output file
  4. -alias root-ca: signed by root-ca
  5. -ext BC=0: certificate extension indicating that the next level for this certificate path should be the last one. It means, that the intermediate-ca will not accept more intermediate levels and it can only sign the final certificate in this certificate chain. NOTE: use this moment to set fields/properties extensions like keyUsage and ExtendedkeyUsage

Checking intermediate-ca keypair:

keytool -list -alias intermediate-ca -v -keystore truststore-ca.p12 -storepass keystore-pass
Alias name: intermediate-ca
...
Certificate chain length: 1
Certificate[1]:
Owner: CN=inter-ca.mycompany.com, OU=My Comp. Intermediate CA, O=My Company, L=State, ST=City, C=Country
Issuer: CN=inter-ca.mycompany.com, OU=My Comp. Intermediate CA, O=My Company, L=State, ST=City, C=Country
...
#1: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:true
  PathLen:2147483647
]

Not much different from root-ca so far

4. Binding the intermediate-ca certificate root-ca certificate.

This procedure, need to be done manually when using keytool.

1- Export root-ca certificate

keytool -exportcert -rfc -file root-ca-cert.pem \
-alias root-ca \
-keystore truststore-ca.p12 -storepass keystore-pass 

2- Build the chain concatenating the certificates in the follow order:

cat root-ca-cert.pem intermediate-ca-cert.pem > intermediate-ca-chain-cert.pem

3- Updating intermediate-ca certificate/publickey with the certificate chain

keytool -importcert -file intermediate-ca-chain-cert.pem -alias intermediate-ca \
-keystore truststore-ca.p12 -storepass keystore-pass -noprompt

Checking intermediate-ca so far

:~$ keytool -list -alias intermediate-ca -v -keystore truststore-ca.p12 -storepass keystore-pass

Alias name: intermediate-ca
...
Certificate chain length: 2
Certificate[1]:
Owner: CN=inter-ca.mycompany.com, OU=My Comp. Intermediate CA, O=My Company, L=State, ST=City, C=Country
Issuer: CN=root-ca.mycompany.com, OU=My Company Root CA, O=My Company, L=State, ST=City, C=Country
...
#2: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:true
  PathLen:0
]
...
Certificate[2]:
Owner: CN=root-ca.mycompany.com, OU=My Company Root CA, O=My Company, L=State, ST=City, C=Country
Issuer: CN=root-ca.mycompany.com, OU=My Company Root CA, O=My Company, L=State, ST=City, C=Country
....
#1: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:true
  PathLen:2147483647
]
...

Now intermediate-ca is issued by root-ca and his BasicConstrains are update in accordance with the root-ca signing command.

** With that the root and intermediate level are ready to be used for create the services certificates **

Creating a server certificate issue by intermediate level

Basically repeating the steps for Intermediate CA. In this case the keypair for the server will be saved in server-keystore.p12 keystore, but no problem if it was saved in truststore-ca.p12.

#server keypair
keytool -genkeypair -keyalg RSA -keysize 2048 -storetype PKCS12 \
-keystore server-keystore.p12 -storepass keystore-pass \
-alias server \
-dname "CN=server.mycompany.com:test,OU=My Company Dev Team,O=My Company,L=State,S=City,C=Country" \
-validity 365;

#server certificate signing request
keytool -certreq -alias server -file server.csr \
-keystore server-keystore.p12 -storepass keystore-pass;

#Making intermediate-ca generate and signing the server certificate
keytool -gencert \
-infile server.csr -outfile server-cert.pem \
-alias intermediate-ca \
-ext ku:c=dig,keyEncipherment \
-rfc \
-keystore truststore-ca.p12 -storepass keystore-pass;

NOTE: opening the server-cert.pem will appear 2 certificates, the intermediate and server. That indicate the chain is still incomplete, missing the root certificate. That one need to be added manually like intermediate chain, check the server-cert-chain.pem below.

#Completing server certificate chain
cat server-cert.pem root-ca-cert.pem > server-cert-chain.pem;

Last step is update the server certificate in server-keystore.p12.

#Updating server public key
keytool -importcert -file server-cert-chain.pem -alias server \
-keystore server-keystore.p12 -storepass keystore-pass -noprompt

#Checking server keychain
keytool -list -v -alias server \
-keystore server-keystore.p12 -storepass keystore-pass

...
Alias name: server
...
Certificate chain length: 3
Certificate[1]:
Owner: CN=server.mycompany.com:test, OU=My Company Dev Team, O=My Company, L=State, ST=City, C=Country
Issuer: CN=inter-ca.mycompany.com, OU=My Comp. Intermediate CA, O=My Company, L=State, ST=City, C=Country
...
#2: ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
  DigitalSignature
  Key_Encipherment
]

Certificate[2]:
Owner: CN=inter-ca.mycompany.com, OU=My Comp. Intermediate CA, O=My Company, L=State, ST=City, C=Country
Issuer: CN=root-ca.mycompany.com, OU=My Company Root CA, O=My Company, L=State, ST=City, C=Country
...
Certificate[3]:
Owner: CN=root-ca.mycompany.com, OU=My Company Root CA, O=My Company, L=State, ST=City, C=Country
Issuer: CN=root-ca.mycompany.com, OU=My Company Root CA, O=My Company, L=State, ST=City, C=Country
...

Finally a server keystore with certificate composed by full chain, server + intermediate + root level, ready to be used.

References

This simple document is a compilation of the following references, thank you guys for all that useful texts:

  1. Using keytool to create certificate chain
  2. Stack Overview - How to create a certificate chain using keytool
  3. Creating an SSL Keystore Using the Java Keytool
  4. Keytool Java 7 docs
  5. KeyUsage
  6. Server fault - Keytool serverAlternateName
  7. Constraints what they are and how they are used
  8. Details digital certificate mean
  9. Stack Overview - CN vs SAN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment