Nginx 1.11.0 dual ECDSA + RSA ssl certificate support

I know @ScottHelme has already played with Nginx 1.11.0 and dual ECDSA + RSA ssl certificate support. Anyone else ?

I just started playing with it https://community.centminmod.com/dualsslcerts via letsencrypt test staging ssl certificates for ECDSA and RSA via @Neilpang’s acme.sh client with some work arounds as it isn’t supporting dual certs out of the box yet

using testssl and ssllabs i can see RSA and ECDSA in use for browser clients :slight_smile:

Running browser simulations (experimental)

Android 2.3.7                 TLSv1 AES128-SHA
Android 4.0.4                 TLSv1 ECDHE-RSA-AES128-SHA
Android 4.1.1                 TLSv1 ECDHE-RSA-AES128-SHA
Android 4.2.2                 TLSv1 ECDHE-RSA-AES128-SHA
Android 4.3                   TLSv1.0 ECDHE-RSA-AES128-SHA
Android 4.4.2                 TLSv1.1 ECDHE-RSA-AES128-SHA
Android 5.0.0                 TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305
Baidu Jan 2015                TLSv1 ECDHE-RSA-AES128-SHA
BingPreview Jan 2015          TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384
Chrome 47 / OSX               TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256
Firefox 31.3.0ESR / Win7      TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256
Firefox 42 / OSX              TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256
GoogleBot Feb 2015            TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256
IE6 / XP                      No connection
IE7 / Vista                   TLSv1.0 ECDHE-RSA-AES128-SHA
IE8 / XP                      No connection
IE8-10 / Win7                 TLSv1.0 ECDHE-RSA-AES128-SHA
IE11 / Win7                   TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384
IE11 / Win8.1                 TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384
IE10 / Win Phone 8.0          TLSv1.0 ECDHE-RSA-AES128-SHA
IE11 / Win Phone 8.1          TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384
IE11 / Win Phone 8.1 Update   TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384
IE11 / Win10                  TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384
Edge 13 / Win10               TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384
Edge 12 / Win Phone 10        TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384
Java 6u45                     TLSv1 AES128-SHA
Java 7u25                     TLSv1 ECDHE-RSA-AES128-SHA
Java 8u31                     TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256
OpenSSL 0.9.8y                TLSv1 AES128-SHA
OpenSSL 1.0.1l                TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384
OpenSSL 1.0.2e                TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384
Safari 5.1.9/ OSX 10.6.8      TLSv1 ECDHE-RSA-AES128-SHA
Safari 6 / iOS 6.0.1          TLSv1.2 ECDHE-ECDSA-AES256-SHA384
Safari 6.0.4/ OS X 10.8.4     TLSv1 ECDHE-RSA-AES128-SHA
Safari 7 / iOS 7.1            TLSv1.2 ECDHE-ECDSA-AES256-SHA384
Safari 7 / OS X 10.9          TLSv1.2 ECDHE-ECDSA-AES256-SHA384
Safari 8 / iOS 8.4            TLSv1.2 ECDHE-ECDSA-AES256-SHA384
Safari 8 / OS X 10.10         TLSv1.2 ECDHE-ECDSA-AES256-SHA384
Safari 9 / iOS 9              TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384
Safari 9 / OS X 10.11         TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384

cipherscan output

cipherscan https://domain.com              
..........................................................................................................................................
Target: domain.com:443

prio  ciphersuite                    protocols              pubkey_size  signature_algoritm       trusted  ticket_hint  ocsp_staple  pfs                 curves                                                                                                                                                curves_ordering
1     ECDHE-ECDSA-CHACHA20-POLY1305  TLSv1.2                384          sha256WithRSAEncryption  False    3600         False        ECDH,P-256,256bits  prime256v1,secp521r1,brainpoolP512r1,brainpoolP384r1,secp384r1                                                                                        server
2     ECDHE-ECDSA-AES256-GCM-SHA384  TLSv1.2                384          sha256WithRSAEncryption  False    3600         False        ECDH,P-256,256bits  prime256v1,secp521r1,brainpoolP512r1,brainpoolP384r1,secp384r1                                                                                        server
3     ECDHE-ECDSA-AES128-GCM-SHA256  TLSv1.2                384          sha256WithRSAEncryption  False    3600         False        ECDH,P-256,256bits  prime256v1,secp521r1,brainpoolP512r1,brainpoolP384r1,secp384r1                                                                                        server
4     ECDHE-ECDSA-AES256-SHA384      TLSv1.2                384          sha256WithRSAEncryption  False    3600         False        ECDH,P-256,256bits  prime256v1,secp521r1,brainpoolP512r1,brainpoolP384r1,secp384r1                                                                                        server
5     ECDHE-ECDSA-AES128-SHA256      TLSv1.2                384          sha256WithRSAEncryption  False    3600         False        ECDH,P-256,256bits  prime256v1,secp521r1,brainpoolP512r1,brainpoolP384r1,secp384r1                                                                                        server
6     ECDHE-RSA-AES128-GCM-SHA256    TLSv1.2                2048         sha256WithRSAEncryption  False    3600         False        ECDH,P-256,256bits  prime256v1,secp521r1,brainpoolP512r1,brainpoolP384r1,secp384r1,brainpoolP256r1,secp256k1,sect571r1,sect571k1,sect409k1,sect409r1,sect283k1,sect283r1  server
7     ECDHE-RSA-AES128-SHA256        TLSv1.2                2048         sha256WithRSAEncryption  False    3600         False        ECDH,P-256,256bits  prime256v1,secp521r1,brainpoolP512r1,brainpoolP384r1,secp384r1,brainpoolP256r1,secp256k1,sect571r1,sect571k1,sect409k1,sect409r1,sect283k1,sect283r1  server
8     ECDHE-RSA-AES128-SHA           TLSv1,TLSv1.1,TLSv1.2  2048         sha256WithRSAEncryption  False    3600         False        ECDH,P-256,256bits  prime256v1,secp521r1,brainpoolP512r1,brainpoolP384r1,secp384r1,brainpoolP256r1,secp256k1,sect571r1,sect571k1,sect409k1,sect409r1,sect283k1,sect283r1  server
9     ECDHE-ECDSA-AES128-SHA         TLSv1,TLSv1.1,TLSv1.2  384          sha256WithRSAEncryption  False    3600         False        ECDH,P-256,256bits  prime256v1,secp521r1,brainpoolP512r1,brainpoolP384r1,secp384r1                                                                                        server
10    AES128-GCM-SHA256              TLSv1.2                2048         sha256WithRSAEncryption  False    3600         False        None                None                                                                                                                                                  server
11    AES128-SHA256                  TLSv1.2                2048         sha256WithRSAEncryption  False    3600         False        None                None                                                                                                                                                  server
12    AES128-SHA                     TLSv1,TLSv1.1,TLSv1.2  2048         sha256WithRSAEncryption  False    3600         False        None                None                                                                                                                                                  server
13    ECDHE-RSA-AES256-GCM-SHA384    TLSv1.2                2048         sha256WithRSAEncryption  False    3600         False        ECDH,P-256,256bits  prime256v1,secp521r1,brainpoolP512r1,brainpoolP384r1,secp384r1,brainpoolP256r1,secp256k1,sect571r1,sect571k1,sect409k1,sect409r1,sect283k1,sect283r1  server
14    ECDHE-RSA-AES256-SHA384        TLSv1.2                2048         sha256WithRSAEncryption  False    3600         False        ECDH,P-256,256bits  prime256v1,secp521r1,brainpoolP512r1,brainpoolP384r1,secp384r1,brainpoolP256r1,secp256k1,sect571r1,sect571k1,sect409k1,sect409r1,sect283k1,sect283r1  server
15    ECDHE-RSA-AES256-SHA           TLSv1,TLSv1.1,TLSv1.2  2048         sha256WithRSAEncryption  False    3600         False        ECDH,P-256,256bits  prime256v1,secp521r1,brainpoolP512r1,brainpoolP384r1,secp384r1,brainpoolP256r1,secp256k1,sect571r1,sect571k1,sect409k1,sect409r1,sect283k1,sect283r1  server
16    ECDHE-ECDSA-AES256-SHA         TLSv1,TLSv1.1,TLSv1.2  384          sha256WithRSAEncryption  False    3600         False        ECDH,P-256,256bits  prime256v1,secp521r1,brainpoolP512r1,brainpoolP384r1,secp384r1                                                                                        server
17    AES256-GCM-SHA384              TLSv1.2                2048         sha256WithRSAEncryption  False    3600         False        None                None                                                                                                                                                  server
18    AES256-SHA256                  TLSv1.2                2048         sha256WithRSAEncryption  False    3600         False        None                None                                                                                                                                                  server
19    AES256-SHA                     TLSv1,TLSv1.1,TLSv1.2  2048         sha256WithRSAEncryption  False    3600         False        None                None                                                                                                                                                  server

OCSP stapling: not supported
Cipher ordering: server
Curves ordering: server - fallback: no
Server supports secure renegotiation
Server supported compression methods: NONE
TLS Tolerance: yes

curious how HPKP should be setup for dual ECDSA + RSA certs ? pin both certs private keys ? acme.sh workaround right now needs me to force a private key recreation so i suspect on renewal i’d need to regenerate the HPKP pins too

Do you get any certificate chain issues flagged in SSL Labs now you’re using dual certs? I see to have a chain issue reported (intermediate is presented twice) that I can’t track down.

no chain issues here but i am just using the staging test letsencrypt ssl certs for ecdsa and rsa right now. Haven't tried live certs yet

There are a couple of issues with multiple certificates in nginx 1.11.0 at present.

  1. ssl_stapling_file can only be set once per server block. Unless there is a way to get OCSP responses for multiple certificates/chains into a single file (RFC 6961?) then OCSP stapling using ssl_stapling_file will only work for one certificate. If the ssl_stapling_file is for the ECDSA certificate, then connections using the RSA certificate will be served an OCSP response for the wrong certificate. This therefore breaks Must-Staple.

  2. The nginx-ct module does not currently support multiple certificates, with it sending all SCTs instead of just those for that particular certificate.

I have disabled ssl_stapling_file for the time being, and I’m not too concerned with some invalid SCTs being sent as long as it is eventually fixed.

Although I don’t use HPKP yet, you’d just chuck the hash of every key that you might use in the header. In my case that would be hashes for 4 keys: my current RSA key (and the backup RSA key) and my ECDSA key (and the backup ECDSA key).

Since SSL Labs doesn’t currently show multiple certificates, it will (depending on server cipher order) most likely show the chain for the ECDSA certificate. That will make it a bit harder to diagnose things.

To check OCSP stapling and certificate chains, I used the following commands (Ubuntu 16.04 openssl):

openssl s_client -connect web.johncook.uk:443 -CAfile /etc/ssl/certs/ca-certificates.crt -showcerts -status -tlsextdebug -cipher RSA </dev/null

openssl s_client -connect web.johncook.uk:443 -CAfile /etc/ssl/certs/ca-certificates.crt -showcerts -status -tlsextdebug -cipher ECDSA </dev/null

1 Like

cheers @WatfordJC - i think @ScottHelme ran into those OCSP stapling issues ?

I did hit the OCSP stapling issues and had to disable OCSP stapling for now too.

ECDSA OCSP Response (Pastebin)

scott@Middle-Earth:~$ echo QUIT | openssl s_client -cipher 'ECDHE-ECDSA-AES128-GCM-SHA256' -connect ecdsa.scotthelme.co.uk:443 -status
CONNECTED(00000003)
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify error:num=20:unable to get local issuer certificate
verify return:0
OCSP response:
======================================
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response
    Version: 1 (0x0)
    Responder Id: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
    Produced At: May 25 00:05:00 2016 GMT
    Responses:
    Certificate ID:
      Hash Algorithm: sha1
      Issuer Name Hash: 7EE66AE7729AB3FCF8A220646C16A12D6071085D
      Issuer Key Hash: A84A6A63047DDDBAE6D139B7A64565EFF3A8ECA1
      Serial Number: 03DF883A976B71EC74AAEB9A8CAAAC2387B7
    Cert Status: good
    This Update: May 25 00:00:00 2016 GMT
    Next Update: Jun  1 00:00:00 2016 GMT

    Signature Algorithm: sha256WithRSAEncryption
         59:76:af:0b:d6:22:ea:4f:7f:57:e0:3b:5c:d2:6c:aa:25:ab:
         33:e9:4f:58:d3:d4:fc:70:c2:39:5c:5a:eb:48:64:b1:e1:14:
         cc:22:9c:7f:58:2a:b4:26:86:63:7f:c5:74:90:ae:38:51:9b:
         d9:a2:ba:77:5d:c7:b8:4e:5b:4f:8b:4f:36:10:58:a9:a4:5e:
         7f:7f:22:23:12:e9:f6:aa:f4:a9:9f:60:7d:d0:2c:6c:22:c8:
         76:28:c1:85:ee:87:44:a9:1a:b0:0a:12:2e:2f:d9:ce:14:3c:
         b4:c6:04:ba:95:1d:09:5b:9d:81:4d:bc:9c:4d:db:0b:3f:f2:
         27:f8:6c:3c:f0:aa:66:5d:bd:be:cb:38:8c:8f:3a:fa:08:50:
         21:c2:84:fb:bc:eb:04:41:f0:a8:b9:d8:4c:0a:f9:44:78:4f:
         39:89:a8:19:c8:f9:0e:e3:ed:5b:f5:8f:a5:f9:03:43:4c:84:
         18:49:cd:97:bd:cb:42:41:03:79:e5:cd:c6:5b:41:7f:1f:c6:
         8e:1d:79:ff:e1:41:92:cc:cb:eb:6e:a3:19:a6:a7:4d:a4:d5:
         c6:27:a9:14:67:56:17:f8:0c:a6:c0:5d:3d:45:b4:8f:de:75:
         33:ff:25:f9:46:20:c0:31:27:40:c1:d8:fa:60:28:7c:c5:db:
         e3:33:36:cf
======================================
---
Certificate chain
 0 s:/CN=scotthelme.co.uk
   i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
 2 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIEZzCCA0+gAwIBAgISA4WkcAqj64nKdX6QFFcpIfE2MA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNjA1MjQxNjE3MDBaFw0x
NjA4MjIxNjE3MDBaMBsxGTAXBgNVBAMTEHNjb3R0aGVsbWUuY28udWswWTATBgcq
hkjOPQIBBggqhkjOPQMBBwNCAASCKm6uKC+amuRGFOTtXo0Bh+nNIlbs5XsEVWaP
1Ly7igGeofm+tgvE7LcyHndWAWvNaXT2MmWE2DaIoQ81MZp8o4ICPzCCAjswDgYD
VR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNV
HRMBAf8EAjAAMB0GA1UdDgQWBBSB4hotSU3n5hqucTUKcHtpoNypRTAfBgNVHSME
GDAWgBSoSmpjBH3duubRObemRWXv86jsoTBwBggrBgEFBQcBAQRkMGIwLwYIKwYB
BQUHMAGGI2h0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcvMC8GCCsG
AQUFBzAChiNodHRwOi8vY2VydC5pbnQteDMubGV0c2VuY3J5cHQub3JnLzBJBgNV
HREEQjBAghZlY2RzYS5zY290dGhlbG1lLmNvLnVrghBzY290dGhlbG1lLmNvLnVr
ghR3d3cuc2NvdHRoZWxtZS5jby51azCB/gYDVR0gBIH2MIHzMAgGBmeBDAECATCB
5gYLKwYBBAGC3xMBAQEwgdYwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2Vu
Y3J5cHQub3JnMIGrBggrBgEFBQcCAjCBngyBm1RoaXMgQ2VydGlmaWNhdGUgbWF5
IG9ubHkgYmUgcmVsaWVkIHVwb24gYnkgUmVseWluZyBQYXJ0aWVzIGFuZCBvbmx5
IGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgQ2VydGlmaWNhdGUgUG9saWN5IGZvdW5k
IGF0IGh0dHBzOi8vbGV0c2VuY3J5cHQub3JnL3JlcG9zaXRvcnkvMA0GCSqGSIb3
DQEBCwUAA4IBAQB5qz2EhCJwIGkKS0UGiEl8c+8Yuu2BLhrEl/AqtfHlv6Ow4ZKt
RE5eufRZWy8VF6pXXutKPDmVbeLPx/Q3ln2PbSK2RHefPvd8bUEASOuMKoL70T5+
MPPE7htQn70AoIbdzGFpL4ZfmcIokZs8RpQ8AeH/je8CgQnE3oQ+eKfgoQIPaMf/
IgqhKg2cPDb0uqD814SNl0JenQZcT5iMmC1sSY5WgfveZg7RFu4td9BFGzRwhLrC
qKEDVFIuT75xiJk5ASTGRYbBXxT2o9cjhGqjDqOJpxIaHP7eLl99w67ZC6r7o7q0
dzhGfa8wgE4vbCx7BbHJiQI3gil32WbUkKvU
-----END CERTIFICATE-----
subject=/CN=scotthelme.co.uk
issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
---
No client certificate CA names sent
---
SSL handshake has read 4524 bytes and written 298 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-ECDSA-AES128-GCM-SHA256
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-ECDSA-AES128-GCM-SHA256
    Session-ID: 92C7D7AF21368A058E7C8B874D1C533828B17F34652556E5665135E20CF43A9B
    Session-ID-ctx:
    Master-Key: 31671D575B521FEB1923FF0386ADFDA81EB597545B4C0C531B5261A9E3BAD88415C8FA6ADE2C100769636D178EB35DD8
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 600 (seconds)
    TLS session ticket:
    0000 - 00 8b 7e 1c de 88 b3 7a-06 56 8e 2c af f7 68 ca   ..~....z.V.,..h.
    0010 - b1 19 e9 87 a9 98 fa 59-a6 e5 26 ef b3 94 f7 79   .......Y..&....y
    0020 - 21 9e 7f 30 6b 8b db 9a-31 25 cf 15 0e 21 6e 24   !..0k...1%...!n$
    0030 - 8a 58 30 fd 40 d2 bd 28-a6 49 c3 a8 d3 46 4f 7f   .X0.@..(.I...FO.
    0040 - 89 b4 58 90 76 e9 53 e9-e7 e7 f9 af 07 9a bf 73   ..X.v.S........s
    0050 - de 55 0e 5e dd 82 76 08-b8 14 59 b8 82 21 a5 ff   .U.^..v...Y..!..
    0060 - 14 f9 d4 09 0b 97 09 04-95 4e e6 93 a7 64 71 52   .........N...dqR
    0070 - e0 91 fa c2 1b 78 3b 22-bf 11 02 19 88 d8 b3 b4   .....x;"........
    0080 - b1 91 3c c9 5b 3f 6e 67-6c a2 81 b5 e3 2d 13 83   ..<.[?ngl....-..
    0090 - 26 bb fb 74 00 e5 19 af-15 0f d6 4b c8 3d fb f8   &..t.......K.=..
    00a0 - 9a 8e 75 2d 3d f9 59 42-0d 2c 7e 91 02 39 50 ad   ..u-=.YB.,~..9P.

    Start Time: 1464256300
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---
DONE

RSA OCSP Response (Pastebin)

scott@Middle-Earth:~$ echo QUIT | openssl s_client -cipher 'ECDHE-RSA-AES128-GCM-SHA256' -connect ecdsa.scotthelme.co.uk:443 -status
CONNECTED(00000003)
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify error:num=20:unable to get local issuer certificate
verify return:0
OCSP response:
======================================
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response
    Version: 1 (0x0)
    Responder Id: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
    Produced At: May 25 00:05:00 2016 GMT
    Responses:
    Certificate ID:
      Hash Algorithm: sha1
      Issuer Name Hash: 7EE66AE7729AB3FCF8A220646C16A12D6071085D
      Issuer Key Hash: A84A6A63047DDDBAE6D139B7A64565EFF3A8ECA1
      Serial Number: 03DF883A976B71EC74AAEB9A8CAAAC2387B7
    Cert Status: good
    This Update: May 25 00:00:00 2016 GMT
    Next Update: Jun  1 00:00:00 2016 GMT

    Signature Algorithm: sha256WithRSAEncryption
         59:76:af:0b:d6:22:ea:4f:7f:57:e0:3b:5c:d2:6c:aa:25:ab:
         33:e9:4f:58:d3:d4:fc:70:c2:39:5c:5a:eb:48:64:b1:e1:14:
         cc:22:9c:7f:58:2a:b4:26:86:63:7f:c5:74:90:ae:38:51:9b:
         d9:a2:ba:77:5d:c7:b8:4e:5b:4f:8b:4f:36:10:58:a9:a4:5e:
         7f:7f:22:23:12:e9:f6:aa:f4:a9:9f:60:7d:d0:2c:6c:22:c8:
         76:28:c1:85:ee:87:44:a9:1a:b0:0a:12:2e:2f:d9:ce:14:3c:
         b4:c6:04:ba:95:1d:09:5b:9d:81:4d:bc:9c:4d:db:0b:3f:f2:
         27:f8:6c:3c:f0:aa:66:5d:bd:be:cb:38:8c:8f:3a:fa:08:50:
         21:c2:84:fb:bc:eb:04:41:f0:a8:b9:d8:4c:0a:f9:44:78:4f:
         39:89:a8:19:c8:f9:0e:e3:ed:5b:f5:8f:a5:f9:03:43:4c:84:
         18:49:cd:97:bd:cb:42:41:03:79:e5:cd:c6:5b:41:7f:1f:c6:
         8e:1d:79:ff:e1:41:92:cc:cb:eb:6e:a3:19:a6:a7:4d:a4:d5:
         c6:27:a9:14:67:56:17:f8:0c:a6:c0:5d:3d:45:b4:8f:de:75:
         33:ff:25:f9:46:20:c0:31:27:40:c1:d8:fa:60:28:7c:c5:db:
         e3:33:36:cf
======================================
---
Certificate chain
 0 s:/CN=scotthelme.co.uk
   i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
 2 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIGdzCCBV+gAwIBAgISA9+IOpdrcex0quuajKqsI4e3MA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNjA0MzAyMzAwMDBaFw0x
NjA3MjkyMzAwMDBaMBsxGTAXBgNVBAMTEHNjb3R0aGVsbWUuY28udWswggIiMA0G
CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/pIu/3B1clN5GjZoicAEqz/wKEoGN
Hpt3PcPC5FhCISQTSXCU/66bRys6yxjvnJMBNobIYlgzmGNRzpioQqNl4X+QJJA2
qjfQUYO+2QhUoxYVEXPUIjKAHgB52Od5NYTpW+0q089caZankodhcQhC23viSeLM
YgdKG3sEdaL7+zJuNdgZhxg6jvb2GXMGQNRRSL10RHR6f6R2S5zWUHBjXLHOJX9u
PrwfDLHnZGelXpWiYy5bM2Y6tXSxllKxkBi6HwHhrGwh8P6jOO4uFFoFiv43UBFe
k1tgWreDLPZggEnWHzOLOhABWDriIE192Awa39yNxcBj5Yyys+Z0IF8QYbQsGzG8
qqMYqn0h5Vd9eT8wa2KorB1FNrRGORpkG1P1WSjEWvaLH0LFkHhvJmNEufYE7uTl
zJnZsZyy1pMyXCylXfPdmDfb2tx0WeiSqPL/G+EDVGc5lEgq/K0bgTrQUqoafe1m
s7wlIa2BPqtbSdtkJ8nrJgvnzBuXHs0qf1TLTmMjn8/lQJdjDFx0I8tAtEko2DQb
C6O++xxRvBJ5Py8UDf8ycoFVD0hsf9RXpeZxZfU2Qn9WEkVnNiBC6ZlbEX/YDaBx
K2yb7s1RV4HO77TOxhSxQRrneFfmRZSkjmh7GMTsw4ZCrcWPR4cTU2s1YiPGmrBL
PMgvfo0DpsZeQQIDAQABo4IChDCCAoAwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW
MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTV
HTl98kIQzpO9fthz10g1jUr/FjAfBgNVHSMEGDAWgBSoSmpjBH3duubRObemRWXv
86jsoTBwBggrBgEFBQcBAQRkMGIwLwYIKwYBBQUHMAGGI2h0dHA6Ly9vY3NwLmlu
dC14My5sZXRzZW5jcnlwdC5vcmcvMC8GCCsGAQUFBzAChiNodHRwOi8vY2VydC5p
bnQteDMubGV0c2VuY3J5cHQub3JnLzCBjQYDVR0RBIGFMIGCghBzY290dGhlbG1l
LmNvLnVrgg5zY290dGhlbG1lLmNvbYIac3Ryb25nc3NsLnNjb3R0aGVsbWUuY28u
dWuCGHdlYWtzc2wuc2NvdHRoZWxtZS5jby51a4IUd3d3LnNjb3R0aGVsbWUuY28u
dWuCEnd3dy5zY290dGhlbG1lLmNvbTCB/gYDVR0gBIH2MIHzMAgGBmeBDAECATCB
5gYLKwYBBAGC3xMBAQEwgdYwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2Vu
Y3J5cHQub3JnMIGrBggrBgEFBQcCAjCBngyBm1RoaXMgQ2VydGlmaWNhdGUgbWF5
IG9ubHkgYmUgcmVsaWVkIHVwb24gYnkgUmVseWluZyBQYXJ0aWVzIGFuZCBvbmx5
IGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgQ2VydGlmaWNhdGUgUG9saWN5IGZvdW5k
IGF0IGh0dHBzOi8vbGV0c2VuY3J5cHQub3JnL3JlcG9zaXRvcnkvMA0GCSqGSIb3
DQEBCwUAA4IBAQBQv9MlNU9MgjiwwNP12zyKoQIKdNf/uroR7bAzCcf64pGhrV8n
EmkQLbpE3yOctT8NVV3TcyaV5re2MZ6zE1cYgSQB0IWdcsp3slLPXa1TMebST8cg
JNsqiSLkR8q+h0Ff8Pma1Wl20Rb3OrjjR2SGtM6xbEDj9Z/wxyvQpVOacpQAhzHJ
O1aN24EGJ7QXdweA+3ObYHpFkEJ+j98bBroBAWG28npxsClrj6ZlSoogyFzTJc2t
EPxGsZTDiTkisDPHlj8VAm3/hm6DpwK3s3vzXaTlahVzYPcVvNZ9eKauufjf8GcT
LXMa2N0neG/7N38l/MY154an/+N/6myxbdfy
-----END CERTIFICATE-----
subject=/CN=scotthelme.co.uk
issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
---
No client certificate CA names sent
---
SSL handshake has read 5493 bytes and written 298 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 4096 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: 1092BE2A73315E7AB99AE0428F0602293F1D89EBB80487930C2E848FCEDB0CD2
    Session-ID-ctx:
    Master-Key: 03D2A94D02C3A7755E025D471068865383C271B9AC97B38A08F69E8F0674D3A34285C5F5F1A9AC0377EDA111E9D44BD1
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 600 (seconds)
    TLS session ticket:
    0000 - 00 8b 7e 1c de 88 b3 7a-06 56 8e 2c af f7 68 ca   ..~....z.V.,..h.
    0010 - 8d 29 0e 20 7e fc e3 b1-64 31 3d f1 f1 87 c0 53   .). ~...d1=....S
    0020 - 5f 58 6d 1d 87 0f 6f 1d-4b ea 03 76 7a aa e9 ee   _Xm...o.K..vz...
    0030 - 05 3f 97 98 64 8b 6e 9d-8b a1 b8 a0 16 74 98 0b   .?..d.n......t..
    0040 - 13 d7 90 c2 3a 12 d7 a2-93 2d eb e0 e1 b8 df 27   ....:....-.....'
    0050 - 2f 44 08 68 e5 f4 0f 83-bb 00 7f 61 51 ea 9e 7a   /D.h.......aQ..z
    0060 - eb b3 39 c7 f0 a3 01 71-e2 6f ab 78 af 69 1a 44   ..9....q.o.x.i.D
    0070 - 0b 99 f0 d4 ce ff 9e 92-47 37 5b ec a6 4c ef 2c   ........G7[..L.,
    0080 - 3c a8 6f 62 bb de 2e ec-b7 2d 05 81 52 f0 f4 a7   <.ob.....-..R...
    0090 - 89 e3 7f 31 30 24 60 7f-9b 49 09 db e3 4b a4 4f   ...10$`..I...K.O
    00a0 - 43 6e 41 5a 34 19 e6 26-02 91 b7 93 63 af c3 7b   CnAZ4..&....c..{

    Start Time: 1464256328
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---
DONE
1 Like

In both of the certificate chains returned in the 2 requests above you can see the intermediate certificate is duplicated, yet there is no duplication anywhere in my config files. When I disable dual certificates, the problem stops with no change to the files themselves.

What’s your TLS setup in your nginx.conf, what’s the contents of your certificate files? My nginx-1.11.0 works flawlessly with dual-cert. The only issue I see is OCSP Stapling which for some connections doesn’t work: quite randomly no stapling is provided by the server. This might be due to this https://community.qualys.com/thread/12315 and could be independent from the dual-cert setup.

Here’s the relevant part of my config. With the –manual– preference for ECDSA ciphers, SSL Labs test shows that certificate as the certificate of the site. No issues with the certificate chain either: ssl-ecdsa.pem only contains the ECDSA server certificate and the LE intermediate, just like the ssl-rsa.pem only contains the RSA server certificate and the LE intermediate. I generated trusted.pem like the following: $ cat ssl-ecdsa.pem ssl-rsa.pem > trusted.pem. Note that upcoming SSL versions will prefer ECDSA ciphers automatically, so I won’t have to manually order aECDSA ciphers ahead of aRSA ciphers.

        […]
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

        ssl_prefer_server_ciphers on;
        ssl_ciphers 'ECDHE+aECDSA+CHACHA20:ECDHE+aRSA+CHACHA20:ECDHE+aECDSA+AESGCM:ECDHE+aRSA+AESGCM:ECDHE+aECDSA+AES256+SHA384:ECDHE+aRSA+AES256+SHA384:ECDHE+aECDSA+AES256+SHA:ECDHE+aRSA+AES256+SHA';
        ssl_ecdh_curve secp384r1;

        ssl_certificate /etc/ssl/nginx/mysite/ssl-ecdsa.pem;
        ssl_certificate_key /etc/ssl/nginx/mysite/ssl-ecdsa.key;
        ssl_certificate /etc/ssl/nginx/mysite/ssl-rsa.pem;
        ssl_certificate_key /etc/ssl/nginx/mysite/ssl-rsa.key;
        ssl_trusted_certificate /etc/ssl/nginx/mysite/trusted.pem;

        ssl_stapling on;
        ssl_stapling_verify on;
        resolver mydns.local valid=300s;
        […]
1 Like

testssl.sh does display and test the certificates independently and even shows separate OCSP Stapling results. You might need to download the development version from github to use that feature, however.

1 Like

I tried your configuration now by adding
ssl_stapling_verify on;
and using ssl_trusted_certificate option.

Still:
Nginx returns 2 intermediate certificates (both the same).
I’ve checked this with the following 2 commands:
openssl s_client -connect ip.of.my.server:443 -servername www.myservername.com cipher RSA -showcerts -status -tlsextdebug
openssl s_client -connect ip.of.my.server:443 -servername www.myservername.com cipher ECDSA -showcerts -status -tlsextdebug

The RSA certificate and the ECDSA certificate both use the LE intermediate X3 cert - it’s this one:

-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----

And this cert is returned twice by nginx 1.11.0.
My nginx uses libressl 2.3.4 by the way.

To me this seems to be a bug or something missing in documentation.

I’ve found the following workaround to fix the issue:
Leave out the intermediate certificate from either the ECDSA or the RSA cert file.

I’m only a beginner C programmer so can’t yet look at the NGINX source code and go “ah, that’s how it does things”, plus the OpenSSL C API is so hard to understand I gave up and used GnuTLS in a project I’m slowly working on.

As a purely speculative guess, the issue could be because your certificates have different SANs. nginx is sending the correct certificate based on cipher, but it is getting confused with the intermediates because it isn’t seeing them as identical due to how it stores them during parsing.

As for OCSP, I have filed a bug with nginx for the ssl_stapling_file issue, so the OCSP issues mentioned in this thread are (as far as I know) now logged in their bug tracker.

  1. NGINX Ticket #990: ssl_stapling_file does not work with multiple certificates

  2. NGINX Ticket #812: Fetch OCSP responses on startup, and store across restarts

As far as the nginx-ct module is concerned, there are two open issues on GitHub that are related:

  1. nginx-ct issue #9: nginx 1.11.0 multiple certificate support

  2. nginx-ct issue #8: Auto-detect applicable SCTs in multi-vhost setups

2 Likes

so nginx is using nginx-ct ? if so then according to nginx-ct only boringssl and openssl 1.0.2 are supported not libressl https://github.com/grahamedgecombe/nginx-ct

No, it doesn’t come bundled with nginx-ct. I use NGINX Mainline and compile the nginx-ct module as a dynamic module.

It is a bit more work when upgrading nginx, but less work than if I were running my own build of nginx.

@ScottHelme @WatfordJC

well looks like Maxim from nginx confirmed dual certs only works with openssl 1.0.2+ not libressl Re: Multi certificate support returns Letsencrypt Intermediate Certificate twice

Only OpenSSL 1.0.2 and higher support separate chains for
different certificates. With older versions (including LibreSSL)
there is only one chain for all certificates, and all chained
certificates will be added to it. That is, if chains are the same
you have to leave only one of them.

--
Maxim Dounin
http://nginx.org/

1 Like

This is actually bad news for LibreSSL as they are a little stuck with their OpenSSL-1.0.1 compatibility, I think. Haven’t heard of any plans of pushing LibreSSL to more recent standards, any news appreciated. And, as you can guess from my happy dual-cert posting, I’m currently back with OpenSSL 1.0.2.

1 Like

Yeah would be great if anybody knows more about LibreSSL plans.

The current situation, to my knowledge, is the following:

OpenSSL 1.0.2:
does support separate chains for different certificates
No support for ed25519 curve
Chacha20-Poly1305 support can be patched in
worse security track record than LibreSSL

OpenSSL 1.1.0:
does support separate chains for different certificates
builtin support for ed25519 curve
builtin Chacha20-Poly1305 support
security standards?
No stable release yet

LibreSSL 2.3.4:
No support for separate chains for different certificates
No support for ed25519 curve
builtin Chacha20-Poly1305 support
good security track record

BoringSSL:
does support separate chains for different certificates (?)
builtin support for ed25519 curve
builtin Chacha20-Poly1305 support
good security track record (?)
No support for OCSP stapling

So, for the time being, I guess I’ll have to wait for an OpenSSL 1.1.0 release…

1 Like

Yeah it’s a shame LibreSSL isn’t keeping up with OpenSSL :frowning:

And also a shame OpenSSL 1.1.0 is late (though most of my clients are PCs and thus the existing AES is still likely the fastest, and of course it is the fastest server-side because I have AES-NI; Sandy Bridge based VPS)

I just downloaded and chmod +x’ed the certbot-auto (certbot isn’t yet in Yakkety), and will give ECDSA a shot.

If anyone is still having issues with OCSP stapling and using hybrid/dual certificates, you need to compile NginX against OpenSSL 1.0.2, I made some notes in the update at the bottom of my article: https://scotthel.me/hybrid

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.