Varun Priolkar

Hybrid ECDSA and RSA certificates with Nginx and Let’s Encrypt

There are a myriad of resources on the internet on how to get this working but not as well compiled together as I’d like. That is the reason I am writing this post. 🙂

I am not going to explain what Elliptic Curve Cryptography(ECC) is since Cloudflare has a very nice blog post on this. Basically you can get much higher security from smaller keys on ECC when compared to traditional RSA keys. A 384 bit elliptic curve key should provide as much protection as a 7680 bit asymmetric RSA key. This can help with faster and less resource intensive SSL negotiation with clients, the only caveat being slightly slower signature verification on client devices. However you would want RSA certificates for compatibility with legacy devices. So let’s dig in, shall we?


  • Nginx 1.11 or above

Nginx 1.11 supports dual certificates so you will need that for hybrid RSA/ECDSA certificates to work. You can get this from a repository for your Linux distribution of choice from here. Confirm that you are running version >1.11 with Nginx -V.

I run this blog along with a reverse proxy in a separate LXC container so it is easier for me to fiddle with OpenSSL/Nginx versions.

  • Relatively recent version of OpenSSL

I don’t know the minimum version required for a certain curve but having an updated version of OpenSSL helps. openssl version tells you what version of OpenSSL you are using. I’m running OpenSSL 1.0.2g 1 Mar 2016 at the time of writing this article. You can use openssl ecparam -list_curve to list elliptical curves available to you. I will be going with secp384r1 since it is relatively secure and widely supported by browsers. Also make sure Nginx is compiled against that version of OpenSSL. This shouldn’t be a problem unless you are compiling Nginx yourself.

You can probably use other cryptographic libraries as well like LibreSSL but I’m not going to cover them in this post.

  • Let’s Encrypt

Let’s Encrypt will give you free SSL certs(yay!). However support for ECDSA is planned by 31st March 2017. You can track the status here. Let’s Encrypt will automatically generate a RSA certificate but for now we have to manually sign the ECDSA certificate with their intermediate RSA certificate. Digitalocean has a nice primer on Let’s Encrypt here. Make sure you configure the webroot plugin how they say. I do SSL on my reverse proxy so the config for me is:

Where /var/www/blog/ is a directory I’ve created and assigned proper permissions for Nginx to read/write to with chown -R nginxuser:nginxgroup /var/www/blog.

RSA certificate

The Digitalocean blog post I linked earlier should help you out with this. For me it was:

Use the –hsts flag if you would like to enable HSTS.

RELATED  Backup your website to Backblaze B2 with encryption

ECDSA certificate

Firstly create the directory to save our private key and our certs with mkdir -p /etc/nginx/certificates and change directory to it by cd /etc/nginx/certificates. Generate your private key with:

It will be saved as ec.key . I’m using the secp384r1 curve as previously mentioned. Now we need to generate a Certificate Signing Request(CSR). For this let’s create a config.

Add in more domains that you may need with DNS.3, DNS.4 etc. Save that as somefile.cnf . Now use this command to generate your CSR:

Where IN is your countrycode, Goa is your state, Ponda is your location, Priolkar is your organisation, is your main domain name/FQDN and is your CSR name. Use this to generate your ECDSA certificate:

Replace the fields accordingly.

Putting it all together

You need to specify the RSA and ECDSA certificates, the elliptical curve used and SSL ciphers in your Nginx virtual host. Make sure you protect against Logjam attacks and POODLE. You can choose to include more things like OCSP stapling, HSTS and SSL session cache. You can use openssl ciphers -V “ALL:COMPLEMENTOFALL” to list all compatible cipher suites.

Now simply test the configuration with nginx -t and restart Nginx with systemctl restart nginx if you are using Systemd.

RELATED  Backing up LXC containers with automation

Testing it out

The simplest way of testing is simply clicking the SSL icon on your browser and clicking for More Information. I use Firefox so this is what I get.


But let’s do a comprehensive test, shall we? So head on over to SSL Labs to test out our config. This is how my website fares in the test.




Cipher Suites should have ECDSA enabled.


Handshake Simulation should tell you the compatibility of our chosen cipher suite and what cipher a particular client would use.


I get a grade A  in the test since I do not have HSTS enabled yet. Enabling it should give you a A+ grade.

Automated certificate renewal

Again the Digitalocean article referenced above tells you how to do this beautifully for RSA certificates. Type in crontab -e and type the following text.

This will try to renew the certificates created every Monday at 2:30 am and reload/restart Nginx at 2:35 am. However this will NOT work for ECDSA certificates. You will have to renew them manually. I will update this post if I find a solution for this.

Future considerations

Using Curve25519 instead of secp384r1 is gaining traction because this is supposedly faster and others are “compromised by NSA”.  Take that how you like. 😛


Curve25519 represent the right and secp256k1 represents the left

However this needs OpenSSL 1.1 and browser support is slowly coming together.

ChaCha20-Poly1305 cipher suites for encryption looks interesting too. But this again needs OpenSSL 1.1 and would be slower than AES-GCM on modern clients with AES-NI support. Android devices with ARMv8 do have AES-NI and I can only imagine more devices having AES-NI support in the future.

I hope you found this article useful. I do not claim to be an expert on cryptography. Do let me know if there are any errors in this post. 🙂


  1. I see your site is in the same niche like my
    page. Do you allow guest posts? I can write excellent posts for you.
    Let me know if you are interested.

  2. Hi Varun!

    Wonderfull post! Really usefull.

    One small issue on my side. I can’t managed to get the OSCP must stapled to work at all.

    Any idea ?

Leave a Reply