Below is what I want to achieve,
- Create my own certificate authority (CA).
- Create my own self-signed certificate.
- Allow the certificate to handle multiple domains.
- Make use of SHA2.
The benefits of creating my own CA is that later I can import its certificate into my machines and all signed certificates will be trusted. This, the certificate supporting the right domain, and a high enough level of encryption is the path to the green padlock.
Before we start, I should point out that I'm not doing anything new here, I'm just putting together bits and pieces from very useful sources I've found online. Please find the references at the end of the blog post.
Tweaking OpenSSL's configuration
One of our goals is to create a certificate that will support multiple domains, meaning that a service can be accessed by the names of service.domain1.com, service.domain2.com or just *.domain3.com. For that we need to tweak our OpenSSL's configuration. You can create a custom one or just edit the system-wide OpenSSL config. I went for the latter approach and in my case using Mac OS X, the configuration file was located in /System/Library/OpenSSL/openssl.cnf.
Look for the [req] section and add,
req_extensions = v3_req
Look for the [ v3_req ] and add,
[ v3_req ]
subjectAltName = @alt_names
Under the [ v3_req ] section, create a new [alt_names] one by writing,
DNS.1 = service.domain1.com
DNS.2 = service.domain2.com
DNS.3 = *.domain3.com
IP.1 = 192.168.0.1
IP.2 = 10.0.0.1
Please not the usage of * as a wildcard to allow the certificate to be valid for all subdomains under domain3.com.
Creation of our own CA
We create the key for our CA
openssl genrsa -out ca.key 4096
And then we create the CA certificate
openssl req -new -x509 -sha256 -days 1826 -key ca.key -out ca.crt
Creation of the self-signed certificate
We create a key for the certificate
openssl genrsa -out cert.key 4096
We issue the request
openssl req -new -key cert.key -out cert.csr
We sign it with our own CA
openssl x509 -req -sha256 -days 730 -in cert.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out cert.crt -extensions v3_req
In case you went for the option of not modifying the system-wide OpenSSL configuration and instead creating a new one, you should append the following string to the last command: -extfile /path/to/your/openssl.cnf
SSL certificate installation
Now that we have the certificate, we just need to install it on our servers. I won't cover this as it is well explained on some articles that you can find online. For installing it on NGINX, I've used Josh Reichardt's article.
CA's certificate installation
By now we should have our server serving content over SSL using our self-signed certificate. In order for our browsers to trust our certificate, our operating system should trust our CA. If we want to access the service programmatically (e.g. through a Java-based client), we should also tell our SDK to trust it. Let's do both.
Trusting a certificate in different operating systems is not within the scope of this post. However, if you happen to be on a Mac, go to Keychain access > System > Certificates > [Click on the + sign] > [Open ca.cert] > [Add it].
For Java to trust our CA certificate, it has to be added to the cacerts store. This can be done with the following command,
sudo keytool -import -trustcacerts -file ca.crt -alias my-own-CA -keystore $JAVA_HOME/jre/lib/security/cacerts
As I mentioned at the beginning, this post is based on some great resources I've found online. Thank you to the people that invested their time in providing them. Please find the links below.
- Didier Stevens's "Howto: Make Your Own Cert With OpenSSL"
- APE TEC's "Multiple Names on One Certificate"
- Ramya Santhosh's "How to generate x509 SHA256 hash self-signed certificate using OpenSSL"
- Josh Reichardt' "How To Configure Nginx with SSL as a Reverse Proxy for Jenkins"
- SSLShopper's "The Most Common Java Keytool Keystore Commands"