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

src: modify SecureContext::SetCACert to not create root certificate store #56301

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

ShenHongFei
Copy link
Contributor

@ShenHongFei ShenHongFei commented Dec 18, 2024

This modification is mainly to optimize the startup performance of http2 and https servers (or may be tls clients's first connection?) When the user specifies a ca, it skips loading more than 100 root certificates built into node.js, and the startup speed is 15 ms faster.

In SecureContext::SetCACert funciton we cound get the existing cert store from the SSL context instead of GetCertStoreOwnedByThisSecureContext() (in which calls NewRootCertStore()) to avoid creating X509_STORE based on root_certs (more than 130), which is very slow.

According to the documentation, when passing in the ca option, you do not add it to the node.js built-in root certificates but replace them, so you do not need to use the built-in root certificate to initialize the x509 store.

node/doc/api/tls.md

Lines 1984 to 2004 in 8253290

* `options` {Object}
* `allowPartialTrustChain` {boolean} Treat intermediate (non-self-signed)
certificates in the trust CA certificate list as trusted.
* `ca` {string|string\[]|Buffer|Buffer\[]} Optionally override the trusted CA
certificates. Default is to trust the well-known CAs curated by Mozilla.
Mozilla's CAs are completely replaced when CAs are explicitly specified
using this option. The value can be a string or `Buffer`, or an `Array` of
strings and/or `Buffer`s. Any string or `Buffer` can contain multiple PEM
CAs concatenated together. The peer's certificate must be chainable to a CA
trusted by the server for the connection to be authenticated. When using
certificates that are not chainable to a well-known CA, the certificate's CA
must be explicitly specified as a trusted or the connection will fail to
authenticate.
If the peer uses a certificate that doesn't match or chain to one of the
default CAs, use the `ca` option to provide a CA certificate that the peer's
certificate can match or chain to.
For self-signed certificates, the certificate is its own CA, and must be
provided.
For PEM encoded certificates, supported types are "TRUSTED CERTIFICATE",
"X509 CERTIFICATE", and "CERTIFICATE".
See also [`tls.rootCertificates`][].

The slow loading of root certificates is a known issue of openssl3 (openssl/openssl#16871) and has not been fixed. @mhdawson
There are also related issues in node.js:

before optimization

slow

after optimization

optimized

cc @nodejs/crypto @nodejs/tls

If anyone can help me benchmark it, I'd be very grateful.

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/crypto

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. crypto Issues and PRs related to the crypto subsystem. needs-ci PRs that need a full CI run. labels Dec 18, 2024
@ShenHongFei ShenHongFei force-pushed the fix-set-ca-cert branch 2 times, most recently from 13674e5 to f61b98f Compare December 18, 2024 08:00
Copy link

codecov bot commented Dec 18, 2024

Codecov Report

Attention: Patch coverage is 65.51724% with 10 lines in your changes missing coverage. Please review.

Project coverage is 88.54%. Comparing base (a73c41c) to head (5efa9aa).
Report is 12 commits behind head on main.

Files with missing lines Patch % Lines
src/crypto/crypto_context.cc 65.51% 7 Missing and 3 partials ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #56301   +/-   ##
=======================================
  Coverage   88.54%   88.54%           
=======================================
  Files         657      657           
  Lines      190290   190323   +33     
  Branches    36533    36547   +14     
=======================================
+ Hits       168488   168525   +37     
+ Misses      14984    14981    -3     
+ Partials     6818     6817    -1     
Files with missing lines Coverage Δ
src/crypto/crypto_context.cc 68.04% <65.51%> (-0.12%) ⬇️

... and 30 files with indirect coverage changes

@meixg meixg added the performance Issues and PRs related to the performance of Node.js. label Dec 18, 2024
@ShenHongFei ShenHongFei force-pushed the fix-set-ca-cert branch 4 times, most recently from db9d305 to 79172cf Compare December 18, 2024 18:15
@ShenHongFei
Copy link
Contributor Author

node.exe D:/1/nodejs/benchmark/compare.js --old T:/node.v23.4.0.exe --new D:/1/nodejs/node.exe --runs 20 --filter create-secure-context tls

                                       confidence improvement accuracy (*)   (**)  (***)
tls\\create-secure-context.js ca=0 n=1        ***     -6.47 %       ±1.09% ±1.48% ±1.99%
tls\\create-secure-context.js ca=0 n=5        ***     -7.62 %       ±0.49% ±0.66% ±0.87%
tls\\create-secure-context.js ca=1 n=1        ***    849.45 %       ±3.56% ±4.86% ±6.59%
tls\\create-secure-context.js ca=1 n=5        ***    847.31 %       ±4.21% ±5.75% ±7.81%

benchmark

const common = require('../common.js');
const fixtures = require('../../test/common/fixtures');
const tls = require('tls');

const bench = common.createBenchmark(main, {
  n: [1, 5],
  ca: [0, 1],
});

function main(conf) {
  const n = conf.n;

  const options = {
    key: fixtures.readKey('rsa_private.pem'),
    cert: fixtures.readKey('rsa_cert.crt'),
    ca: conf.ca === 1 ? [fixtures.readKey('rsa_ca.crt')] : undefined,
  };

  bench.start();
  tls.createSecureContext(options);
  bench.end(n);
}

@ShenHongFei ShenHongFei force-pushed the fix-set-ca-cert branch 2 times, most recently from 6b87eab to 15e8061 Compare December 19, 2024 02:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. crypto Issues and PRs related to the crypto subsystem. needs-ci PRs that need a full CI run. performance Issues and PRs related to the performance of Node.js.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants