#814 closed enhancement (fixed)
Support for parallel ECDSA / RSA certificates
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | nginx-core | Version: | 1.9.x |
Keywords: | Cc: | ||
uname -a: | N/A | ||
nginx -V: | 1.9.2 |
Description
I'd like to be able to deploy an ECDSA certificate alongside an RSA certificate, and have Nginx choose which certificate to serve based on the signature_algorithms extension in the handshake: https://tools.ietf.org/html/rfc5246#page-45.
ECDSA certificates are much smaller, and so allow faster handshake times on limited bandwidth. But they are not yet broadly supported. Allowing deployment of dual certificates on Nginx would help greatly with a gradual rollout of ECDSA certificates, which would in turn help client adoption and promote a faster Internet.
Change History (13)
comment:1 by , 9 years ago
comment:2 by , 9 years ago
As acclimed Apache httpd 2.4 has dual certificate support:
https://blog.joelj.org/dual-rsaecdsa-certificates-in-apache-2-4/
comment:3 by , 9 years ago
Simultaneous usage of RSA and ECDSA certificates would be perfect. That way, you can request Let's Encrypt certificates for both types and use them with priority of ECDSA ciphers over RSA ciphers in order to keep the server load down. Therefore, I was thinking about using Apache, but turned the idea down, because Nginx is easier to configure for me and more lightweight. Hopefully, Nginx will support this in the near future.
comment:6 by , 8 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Support for multiple certificates was committed and will be available in nginx 1.11.0.
follow-up: 8 comment:7 by , 8 years ago
I've installed 1.11.0 and there seems to be some issue around OCSP stapling when specifying multiple ssl_certificate and ssl_certificate_key directives. Has anyone experienced any issues?
comment:8 by , 8 years ago
There are two things to consider when using multiple certificates:
- Only OpenSSL 1.0.2+ supports separate chains for different certificates. With older versions, things will only work properly if chains are exactly the same for all certificates used (or there are no chains at all).
- OCSP stapling won't work properly with multiple certificates with OpenSSL versions before 1.0.1d+, 1.0.0k, 0.9.8y+ (see a2d5d45f1525). This is due to a bug in OpenSSL fixed in the versions specified.
Check nginx -V
output to find out the version of the OpenSSL library you are using.
comment:9 by , 8 years ago
I got my RSA and ECDSA certificates from Let's Encrypt. So, both intermediate certificates are identical. Do I have to append the intermediate certificate to both certificates? e.g.:
cat rsa_example.org.pem intermediate.pem > rsa_chain.pem cat ecdsa_example.org.pem intermediate.pem > ecdsa_chain.pem
Doing it that way leads to an error in ssllabs:
Certificates provided 3 (3663 bytes) Chain issues Incorrect order, Extra certs
comment:10 by , 8 years ago
The error reported suggests that you are using an old OpenSSL (before 1.0.2), so you have to append the chain to only one of the certificates (it will be used for both).
comment:11 by , 8 years ago
Some additional info about my Gentoo Linux Nginx server:
netcup88 ~ # nginx -V nginx version: nginx/1.11.1 built with LibreSSL 2.4.1 TLS SNI support enabled configure arguments: --prefix=/usr --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error_log --pid-path=/run/nginx.pid --lock-path=/run/lock/nginx.lock --with-cc-opt=-I/usr/include --with-ld-opt=-L/usr/lib --http-log-path=/var/log/nginx/access_log --http-client-body-temp-path=/var/lib/nginx/tmp/client --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --with-http_v2_module --with-ipv6 --with-pcre --without-http_autoindex_module --without-http_browser_module --without-http_charset_module --without-http_empty_gif_module --without-http_fastcgi_module --without-http_geo_module --without-http_gzip_module --without-http_limit_req_module --without-http_limit_conn_module --without-http_map_module --without-http_memcached_module --without-http_scgi_module --without-http_ssi_module --without-http_split_clients_module --without-http_upstream_ip_hash_module --without-http_userid_module --without-http_uwsgi_module --with-http_realip_module --add-module=external_module/headers-more-nginx-module-0.30 --with-http_ssl_module --without-stream_upstream_hash_module --without-stream_upstream_least_conn_module --without-stream_upstream_zone_module --without-stream_upstream_hash_module --without-stream_upstream_least_conn_module --without-stream_upstream_zone_module --without-stream_upstream_hash_module --without-stream_upstream_least_conn_module --without-stream_upstream_zone_module --without-mail_imap_module --without-mail_pop3_module --without-mail_smtp_module --user='nginx --group=nginx'
netcup88 ~ # cat /etc/nginx/nginx.conf user nginx nginx; worker_processes auto; events { worker_connections 1024; use epoll; } http { include /etc/nginx/mime.types; default_type application/octet-stream; include /etc/nginx/conf.d/http_ssl.conf; include /etc/nginx/conf.d/http_harden.conf; include /etc/nginx/pages/*.conf; server { listen 80; listen [::]:80; listen 443 ssl http2; listen [::]:443 ssl http2; return 444; } }
david@netcup88 ~ $ cat /etc/nginx/conf.d/http_ssl.conf # certs and private keys ssl_certificate /etc/nginx/ssl/ecdsa.pem; ssl_certificate_key /etc/nginx/ssl/ecdsa.key; ssl_certificate /etc/nginx/ssl/rsa.pem; ssl_certificate_key /etc/nginx/ssl/rsa.key; # OCSP Stapling ssl_stapling on; # protocols and ciphers ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES256-SHA384'; ssl_ecdh_curve prime256v1; ssl_prefer_server_ciphers on; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # sessions ssl_session_cache shared:SSL:50m; ssl_session_tickets off; ssl_session_timeout 1d;
comment:12 by , 8 years ago
And some additional info. As you can see both ECDSA and RSA based ciphers are offered, which is only the case if LibreSSL has access to key pairs of both types. The Nginx's docs do not explain the correct way to include the intermediate certificate if both RSA and ECDSA is in use. If I append the intermediate certificate only to the ECDSA certificate, referenced in above Nginx config, ssllabs doesn't throw the error. But, I don't know whether this is the correct way. The docs should also cover the scenario where the ECDSA and RSA certificates are issued by different CAs with differing intermediate certificates.
########################################################### testssl.sh 2.6 from https://testssl.sh/ (1.379B 2015/09/25 12:35:41) This program is free software. Distribution and modification under GPLv2 permitted. USAGE w/o ANY WARRANTY. USE IT AT YOUR OWN RISK! Please file bugs @ https://testssl.sh/bugs/ ########################################################### Using "OpenSSL 1.0.2-chacha (1.0.2d-dev)" [~181 ciphers] on xxx:./bin/openssl.Linux.x86_64 (built: "Jul 6 18:05:33 2015", platform: "linux-x86_64") Testing now (2016-07-03 23:28) ---> xxx.xxx.xxx.xxx:443 (www.xxx.com) <--- rDNS (xxx.xxx.xxx.xxx): xxx Service detected: HTTP --> Testing protocols (via sockets except TLS 1.2 and SPDY/NPN) SSLv2 not offered (OK) SSLv3 not offered (OK) TLS 1 offered TLS 1.1 offered TLS 1.2 offered (OK) SPDY/NPN not offered --> Testing ~standard cipher lists Null Ciphers not offered (OK) Anonymous NULL Ciphers not offered (OK) Anonymous DH Ciphers not offered (OK) 40 Bit encryption not offered (OK) 56 Bit encryption not offered (OK) Export Ciphers (general) not offered (OK) Low (<=64 Bit) not offered (OK) DES Ciphers not offered (OK) Medium grade encryption not offered (OK) Triple DES Ciphers not offered (OK) High grade encryption offered (OK) --> Testing (perfect) forward secrecy, (P)FS -- omitting 3DES, RC4 and Null Encryption here PFS is offered (OK) ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-SHA384 ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES256-SHA ECDHE-ECDSA-AES256-SHA ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES128-SHA256 ECDHE-RSA-AES128-SHA256 ECDHE-RSA-AES128-SHA ECDHE-ECDSA-AES128-SHA --> Testing server preferences Has server cipher order? yes (OK) Negotiated protocol TLSv1.2 Negotiated cipher ECDHE-ECDSA-AES128-GCM-SHA256, 256 bit ECDH Cipher order TLSv1: ECDHE-ECDSA-AES128-SHA ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES128-SHA ECDHE-RSA-AES256-SHA TLSv1.1: ECDHE-ECDSA-AES128-SHA ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES128-SHA ECDHE-RSA-AES256-SHA TLSv1.2: ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-SHA ECDHE-ECDSA-AES128-SHA256 ECDHE-ECDSA-AES256-SHA ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES128-SHA ECDHE-RSA-AES128-SHA256 ECDHE-RSA-AES256-SHA ECDHE-RSA-AES256-SHA384 --> Testing server defaults (Server Hello) TLS server extensions server name, renegotiation info, EC point formats Session Tickets RFC 5077 (none) Server key size EC 256 bit Signature Algorithm SHA256 with RSA Fingerprint / Serial SHA1 xxx / xxx SHA256 xxx Common Name (CN) www.xxx.com (works w/o SNI) subjectAltName (SAN) xxx.de xxx.eu xxx.com xxx.de xxx.eu xxx.com xxx.de xxx.eu www.xxx.de www.xxx.eu www.xxx.com www.xxx.de www.xxx.eu www.xxx.com www.xxx.de www.xxx.eu Issuer Let's Encrypt Authority X3 (Let's Encrypt from US) EV cert (experimental) no Certificate Expiration >= 60 days (2016-06-28 22:02 --> 2016-09-26 22:02 +0200) # of certificates provided 2 Certificate Revocation List OCSP URI http://ocsp.int-x3.letsencrypt.org/ OCSP stapling not offered TLS timestamp random values, no fingerprinting possible --> Testing HTTP header response @ "/" HTTP Status Code 200 OK HTTP clock skew -2 sec from localtime Strict Transport Security 182 days=15768000 s, just this domain Public Key Pinning # of keys: 32, 182 days=15768000 s, just this domain matching host key: xxx Server banner lol Application banner X-Powered-By: lol Cookie(s) (none issued at "/") Security headers X-Frame-Options: deny X-XSS-Protection: 1; mode=block X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'self'; font-src 'self' data: https://fonts.gstatic.com; img-src 'self' data: https://code.jquery.com https://secure.gravatar.com https://*.w.org https://wordpress.org; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://code.jquery.com https://fonts.googleapis.com Reverse Proxy banner -- --> Testing vulnerabilities Heartbleed (CVE-2014-0160) not vulnerable (OK) CCS (CVE-2014-0224) not vulnerable (OK) Secure Renegotiation (CVE-2009-3555) not vulnerable (OK) Secure Client-Initiated Renegotiation not vulnerable (OK) CRIME, TLS (CVE-2012-4929) not vulnerable (OK) BREACH (CVE-2013-3587) no HTTP compression (OK) (only "/" tested) POODLE, SSL (CVE-2014-3566) not vulnerable (OK) TLS_FALLBACK_SCSV (RFC 7507), experim. Downgrade attack prevention supported (OK) FREAK (CVE-2015-0204) not vulnerable (OK) LOGJAM (CVE-2015-4000), experimental not vulnerable (OK), common primes not checked. See below for any DH ciphers + bit size BEAST (CVE-2011-3389) no CBC ciphers for TLS1 (OK) RC4 (CVE-2013-2566, CVE-2015-2808) no RC4 ciphers detected (OK) --> Testing all locally available 181 ciphers against the server, ordered by encryption strength Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits Cipher Suite Name (RFC) ----------------------------------------------------------------------------------------------------------------------- xc030 ECDHE-RSA-AES256-GCM-SHA384 ECDH 256 AESGCM 256 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 xc02c ECDHE-ECDSA-AES256-GCM-SHA384 ECDH 256 AESGCM 256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 xc028 ECDHE-RSA-AES256-SHA384 ECDH 256 AES 256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 xc024 ECDHE-ECDSA-AES256-SHA384 ECDH 256 AES 256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 xc014 ECDHE-RSA-AES256-SHA ECDH 256 AES 256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA xc00a ECDHE-ECDSA-AES256-SHA ECDH 256 AES 256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA xc02f ECDHE-RSA-AES128-GCM-SHA256 ECDH 256 AESGCM 128 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 xc02b ECDHE-ECDSA-AES128-GCM-SHA256 ECDH 256 AESGCM 128 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 xc027 ECDHE-RSA-AES128-SHA256 ECDH 256 AES 128 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 xc023 ECDHE-ECDSA-AES128-SHA256 ECDH 256 AES 128 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 xc013 ECDHE-RSA-AES128-SHA ECDH 256 AES 128 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA xc009 ECDHE-ECDSA-AES128-SHA ECDH 256 AES 128 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA Done now (2016-07-03 23:29) ---> xxx.xxx.xxx.xxx:443 (www.xxx.com) <---
comment:13 by , 8 years ago
LibreSSL doesn't have support for multiple certificate chains and mostly similar to OpenSSL 1.0.1.
There were patches for this that made the rounds at some point in time, have not heard anything about it since then. I wonder what happened.