-
Notifications
You must be signed in to change notification settings - Fork 17.5k
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
crypto/tls: improve default performance of SupportsCertificate #35504
Comments
Change https://golang.org/cl/205059 mentions this issue: |
Now that we have a full implementation of the logic to check certificate compatibility, we can let applications just list multiple chains in Certificates (for example, an RSA and an ECDSA one) and choose the most appropriate automatically. NameToCertificate only maps each name to one chain, so simply deprecate it, and while at it simplify its implementation by not stripping trailing dots from the SNI (which is specified not to have any, see RFC 6066, Section 3) and by not supporting multi-level wildcards, which are not a thing in the WebPKI (and in crypto/x509). The performance of SupportsCertificate without Leaf is poor, but doesn't affect current users. For now document that, and address it properly in the next cycle. See #35504. While cleaning up the Certificates/GetCertificate/GetConfigForClient behavior, also support leaving Certificates/GetCertificate nil if GetConfigForClient is set, and send unrecognized_name when there are no available certificates. Fixes #29139 Fixes #18377 Change-Id: I26604db48806fe4d608388e55da52f34b7ca4566 Reviewed-on: https://go-review.googlesource.com/c/go/+/205059 Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Katie Hockman <katie@golang.org>
Looking at golang.org/cl/205059 it seems like the proposed solutions were:
(1) would likely be quite fast, but introduces the need for a second special x509 parser, which while likely to be relatively self contained due to the limit of what it'd parse is still not ideal (it could also have relatively sharp edges, likely you'd need it to output a partially populated Certificate, in order to use VerifyHostname, so you'd have to be very careful not to use it anywhere else where you might expect anything other than the SAN fields to be populated). (2) would introduce the typical problems with linked lists, circular lists, broken references, etc. This also is somewhat more likely to cause issues because you'd be relying on the user to properly build the list themselves (or use BuildNameToCertificate). Also given NameToCertificate/BuildNameToCertificate were deprecated in CL205059 it doesn't seem ideal to bring them back with new functionality in a subsequent release. (3) would generally increase memory usage, which is unlikely to incur significant problems for most users who only have a handful of certificates, and would change documented behavior that people may have been relying on (specifically expecting Leaf not to be set). Assuming this is how most people load certificates this way this is likely the option to that'd cause the least pain without the user having to do anything in the typical case. It seems there could also a third option, along similar lines to (3), which would be to add a once style lazy load in |
Perhaps another solution would be a slight hybrid of above. Add a private SAN field to Certificate which is lazy loaded (or populated via LoadX509KeyPair) and only used when Leaf is nil. Loadx509KeyPair could then retain the property of not populating Leaf, and the overall memory footprint of storing this would be significantly smaller than storing the full certificate. A special parse wouldn't be needed because we could just use ParseCertificate and would only have to pay the penalty once per certificate. |
I meet the same issue. Any progress on this? |
I just ran into this as well. I noticed the deprecation warning on It also doesn't seem right that my code, which previously only called It also seems a little silly that it parses the certificate twice (though it was doing that before, too, via Personally @rolandshoemaker's option (3) sounds fine to me, though I guess I haven't contemplated use cases where the memory usage would matter at all. His alternative option where we lazily store Another (3) variation (though unpleasant) is (1) and (2) would be okay as well, if they could be made invisible to me and were just as fast as what I'm currently doing, but they sound like an awful lot of mechanism to solve what seems like a simple problem. |
Performance improvements from #44299 may magically fix this, if not it also includes a fast SAN parser we can use. |
Is anything going to happen on this for 1.17? Thanks. |
This doesn't have an assignee and seems it doesn't have to happen in Go 1.17, so moving to Backlog. |
CC @golang/security Looks like this didn't make 1.19. Moving to backlog. Please recategorize as appropriate. |
I landed here after encountering a panic (my fault) when trying to access
I understood "[it] may be initialized using A more careful reading on my part would have avoided the bug in my code. However, it was surprising that to me that a something documented "to reduce per-handshake processing" wouldn't have set At the least, I think the documentation could be improved, but I agree with @cespare that setting |
I see there is some history here:
To me it is surprising that
|
As discussed in https://golang.org/cl/205059, SupportsCertificate requires c.Leaf to be set not to be extremely slow (because it needs to re-parse the leaf every time). This also impacts automatic selection from multiple Certificates candidates.
There are multiple solutions suggested on the CL, I will pick one and turn this into a proposal for further discussion.
The text was updated successfully, but these errors were encountered: