Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple certificate support (e.g. ECDSA & RSA) #1575

Closed
lenovouser opened this issue Apr 13, 2017 · 27 comments
Closed

Multiple certificate support (e.g. ECDSA & RSA) #1575

lenovouser opened this issue Apr 13, 2017 · 27 comments
Labels
feature ⚙️ New feature or request help wanted 🆘 Extra attention is needed
Milestone

Comments

@lenovouser
Copy link

Like e.g. NGINX supports it

@mholt mholt added the feature ⚙️ New feature or request label Apr 14, 2017
@mholt
Copy link
Member

mholt commented Apr 17, 2017

I'm not sure how this works (or should work with Caddy). Can you or someone elaborate?

@francislavoie
Copy link
Member

I think this is for the tls cert key manual SSL, so that you can specify multiple versions of a cert, signed with a different key, i.e. an ECDSA key or an RSA key.

We can already specify multiple cert/key pairs:

You can use this directive multiple times to specify multiple certificate and key pairs.
https://caddyserver.com/docs/tls

e.g.

tls example.com.rsa.crt example.com.rsa.key
tls example.com.ecdsa.crt example.com.ecdsa.key

@lenovouser does that answer your issue? Seems to me like Caddy can already do this.

@lenovouser
Copy link
Author

@francislavoie yep, you can specify this - but it always uses only the last directive instead of deciding between rsa and ecdsa

@mholt
Copy link
Member

mholt commented Apr 17, 2017

Okay, what determines which one to use?

@lenovouser
Copy link
Author

It's determined by client support (based on the signature_algorithms extension in the handshake: ​ietf.org/rfc5246#signature_algorithms)

@lenovouser
Copy link
Author

Also, some notes taken from the NGINX issue:

  • 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 and 0.9.8y+. This is due to a bug in OpenSSL fixed in the versions specified.

Just found out Apache supports this too

@lenovouser
Copy link
Author

Just had another thought - in case #1576 will be implemented and this here too, you should keep an eye on that the correct *.sct's get taken for the correct certificate in case multiple are specified. The NGINX extension also took care of that like this:

ssl_ct on;

ssl_certificate /path/to/rsa.pem;
ssl_certificate_key /path/to/rsa.key;
ssl_ct_static_scts /path/to/rsa/scts;

ssl_certificate /path/to/ecdsa.pem;
ssl_certificate_key /path/to/ecdsa.key;
ssl_ct_static_scts /path/to/ecdsa/scts;

@neilstuartcraig
Copy link

Hi all
FWIW i'd love to see this feature too (i found this ticket because i was going to request the same feature). My usage would be that i'd server pref EC ciphersuites but support RSA's for the minority of older clients which don't (and never will, e.g. XP) support EC.

It would be awesome if Caddy could create/manage both an EC and an RSA LetsEncypt cert - i'd see that as being pretty essential as part of this.

Very happy to help with any testing/nginx-based input (i use EC & RSA concurrently in nginx right now).

One final note, i don't think you need to have different session secret(s) for EC and RSA - unless that's something specific to Caddy and/or Go.

Cheers!

@mholt
Copy link
Member

mholt commented Jun 7, 2017

@neilstuartcraig I'll look into this; I'm definitely interested in Caddy using ECC over RSA. I am hoping we could just switch over to ECC without having to manage certs with obsolete crypto. I think having to manage both is just temporary and am not yet sure how complex this will be. Does someone want to throw together a proof of concept?

@mholt mholt added the help wanted 🆘 Extra attention is needed label Jun 7, 2017
@neilstuartcraig
Copy link

neilstuartcraig commented Jun 8, 2017

@mholt - I'm probably missing something here (apologies if so) but Caddy already works for ECC. Specifying key_type as e.g. p256 with an LE cert results in that cert being ECC. This is great and works really well, i use it currently in a personal project i'm developing.

Being able to use both is currently mandatory for our audience demographics, we have anything from about 0.5% up to ~17% (i've checked this several times) of our audience who use clients which can't handle ECC. This variation is chiefly down to geography, for example, many of our users in Africa and also parts of Asia require RSA-based certs. This means that we absolutely must support at least RSA but we'd love to pref ECC above it in our server pref lists so that the majority of users on modern clients can reap the benefits.

NGINX handles this really nicely so the same sort of operational model would be great - selecting the appropriate cert based on the client hello vs the server ciphersuite pref list. FWIW, I believe NGINX essentially hands off this whole procedure to OpenSSL, not sure if that would/wouldn't be the same for Go/Caddy but from memory, OpenSSL 1.01f+ handle it properly.

I have literally never written a line of Go so it'd take me an age to produce anything but i'd be more than happy to help in any other way.

Cheers

@mholt
Copy link
Member

mholt commented Jun 9, 2017

@neilstuartcraig I need to see if the underlying lego library would support this; we'd request a second cert using an already-obtained authz, probably. But I don't know how this affects rate limits with Let's Encrypt and such, for the second issuance.

@neilstuartcraig
Copy link

@mholt - Yep, for sure. Do let me know if i can do anything useful (research, contacting people, docs, testing etc.). Really appreciate you spending time looking into this. Cheers

@mholt
Copy link
Member

mholt commented Jun 30, 2017

The LE folks say that getting two of the same certificate (but of a different key type) still use two queries against the rate limit. Is it worth implementing this feature that is mainly useful only during this transitionary period to ECC that adds complexity and doubles the rate limit usage?

@neilstuartcraig
Copy link

neilstuartcraig commented Jun 30, 2017

My opinion would be that it's worth it for at least some use cases. As i mentioned previously, some of our audiences have ~17% of folk who can't do EC - so for them we need RSA, but it seems a shame to "punish" the majority, 83%, of that demographic (not to mention other geographies who are ~0.5% who can't do EC) with ~7x slower TLS handshakes.

If the code complexity in Caddy is sufficiently high, perhaps it makes sense to ask Caddy users to manually manage their certs but if it's not so bad, it'd be a particularly nice feature (IMO). Of course, since Caddy supports TLS session tickets, handshake time is only a problem for first-time (per ticket secret lifetime) visitors - that too will obviously vary massively by user-base. FWIW, we're currently rotating TLS session secrets ~every 24h with a primary and secondary, thus a maximum session lifetime of ~48h - since we want to limit the scope of a compromised session secret.

If number of LE API queries is the major issue, i think if it's clearly documented that EC + RSA means 2x API queries, it's a conscious choice for the user which puts the decision in their hands.

Does that help? Apologies if i'm rambling nonsense :-)

@lenovouser
Copy link
Author

@mholt Your point about the rate limit is valid, even though I think it should be no problem if you make it opt-in (only if it is configured for dual certificate support) because the admin then chooses to do so.

Also it could at least be implemented as a config file option for non-LE certificates if is too complex for LE and / or rate limiting.

@mholt
Copy link
Member

mholt commented Jun 30, 2017

Okay. Well, we can give it a go, but I have other things on my priority list right now (API, proxy rewrite, telemetry, updates to the dev portal, etc...) so if somebody would like to take a stab at it, let us know!

@giuem
Copy link

giuem commented Jul 23, 2017

It's a nice feature. Currently I still use Nginx mainly because of this.

In Nginx, there is a key called ssl_ciphers that can specify the enabled ciphers.

To use ECDSA + RSA key, I set it to EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5;

Here is SSL Server Test, you can see the server choose certificate correctly.

I hope this is helpful

@ghost
Copy link

ghost commented Sep 9, 2018

Any update on this?

@neilstuartcraig
Copy link

neilstuartcraig commented Jan 10, 2019 via email

@francislavoie
Copy link
Member

@WhaleHub just wondering if there was ever any progress with that ad you put out?

@may573
Copy link

may573 commented Feb 12, 2020

Is there any update for this requirement?

@mholt
Copy link
Member

mholt commented Feb 12, 2020

This can be supported in Caddy 2 after Go 1.14 is released. But someone will have to propose and implement it.

@may573
Copy link

may573 commented Feb 12, 2020

Great, looking forward to it will come soon.

@ghost
Copy link

ghost commented Feb 12, 2020

@mholt Just curious, what feature is planned for Go 1.14 that makes this possible?

@welwood08
Copy link

@WhaleHub Presumably:

When multiple certificate chains are provided through the Config.Certificates field, the first one compatible with the peer is now automatically selected. This allows for example providing an ECDSA and an RSA certificate, and letting the package automatically select the best one.

@mholt
Copy link
Member

mholt commented Feb 12, 2020

Yep, although we don't use Certificates, so technically it's this one:

The new (*ClientHelloInfo).SupportsCertificate and (*CertificateRequestInfo).SupportsCertificate methods expose whether a peer supports a certain certificate.

Ooo and unrelated, but... it looks like this:

Config.Certificates and Config.GetCertificate can now both be nil if Config.GetConfigForClient is set. If the callbacks return neither certificates nor an error, the unrecognized_name is now sent.

Will finally fix #2404.

@mholt mholt closed this as completed in 6ca5828 Apr 2, 2020
@mholt
Copy link
Member

mholt commented Apr 2, 2020

Attention @lenovouser @neilstuartcraig @giuem @may573 and others: This was a lot of work, but it's implemented in 6ca5828. Please try it out! Release candidates will be cut very shortly!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature ⚙️ New feature or request help wanted 🆘 Extra attention is needed
Projects
None yet
Development

No branches or pull requests

7 participants