Generating ECC certificate authorities and certificates

Published on

The other day, I was trying to generate a self-signed ECC certificate for a web server. This turned out to be trickier than I thought.

First of all, almost all guides use RSA, while I was trying to use Elliptic Curve cryptography (“ECC”). ECC is considered better than RSA because it offers comparable security with much smaller key sizes, resulting in faster computations.

Secondly, it turns out that instead of self-signing the certificate, I needed to generate a Certificate Authority (“CA”) certificate, and sign the server certificate with the CA’s private key. This is necessary to be able to use the certificate in Firefox (more information about this). Besides, it also makes it easier to generate more certificates later on because as long as the CA is trusted, all certificates signed by the CA are trusted.

Lastly, I wanted to be able to automate the entire process, so none of the commands should ask for user input.

First, let’s pick a curve. For a list of supported curves by OpenSSL, run the following command:

openssl ecparam -list_curves

I am going to be using secp384r1 as it has great support.

Certificate authority

Generate a private key:

openssl ecparam -out ca.key -name secp384r1 -genkey

Create a certificate signing request, with “Example CA” as the Common Name (“CN”):

openssl req -new -key ca.key -out ca.csr -addext "basicConstraints=CA:TRUE" -subj "/CN=Example CA"

Generate the CA certificate:

openssl x509 -req -days 36500 -in ca.csr -signkey ca.key -out ca.crt -copy_extensions copy

To change the expiration of the CA, change the -days 36500 parameter.

The CA is now ready to go. You can add the ca.crt file to the trusted authority store of your operating system/browser.

Server certificate

Generate a private key:

openssl ecparam -out server.key -name secp384r1 -genkey

Create a certificate signing request:

openssl req -new -key server.key -out server.csr \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,DNS:\*.localhost,IP:127.0.0.1"

The CN can be anything. This certificate will be valid for localhost, *.localhost, and 127.0.0.1.

Generate the server certificate signed with the CA’s private key:

openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -out server.crt -days 36500 -copy_extensions copy

Your server certificate is now ready to go. Your server will need the server.crt and the server.key files.

You can inspect certificates using the following command:

openssl x509 -in ca.crt -text -noout

Trusting the CA

Debian-based systems:

cp ca.crt /usr/local/share/ca-certificates/ && update-ca-certificates

Windows: Double-click the certificate file -> Install Certificate… -> Next -> Place all certificates in the following store -> Browse… -> Trusted Root Certification Authorities -> OK -> Next -> Finish

Firefox: Settings -> Privacy & Security -> View Certificates… -> Authorities -> Import…

Connection verified by a certificate issuer that is not recognized by Mozilla

I really don’t need a CA

Here is how you generate a self-signed certificate:

Generate a private key:

openssl ecparam -out server.key -name secp384r1 -genkey

Create a certificate signing request:

openssl req -new -key server.key -out server.csr \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,DNS:\*.localhost,IP:127.0.0.1"

Generate certificate signed with the private key:

openssl x509 -req -days 36500 -in server.csr -signkey server.key -out server.crt -copy_extensions copy
Go back