Skip to content

crypto: remove key mutexes - #66413

Open
panva wants to merge 5 commits into
nodejs:mainfrom
panva:crypto-key-mutexes
Open

panva wants to merge 5 commits into
nodejs:mainfrom
panva:crypto-key-mutexes

Conversation

@panva

@panva panva commented Sep 30, 2026

Copy link
Copy Markdown
Member

Remove the shared KeyObjectData mutex and its 18 acquisitions, allowing RSA-OAEP and KEM jobs to run concurrently on the same backing key. This also removes unnecessary locking around verify setup, key exports, and metadata queries, plus unused mutex allocations for secret keys.

Assisted-by: Codex

Secret key bytes are immutable after KeyObjectData construction. AES,
ChaCha20-Poly1305, MAC, and KDF jobs read those bytes without acquiring
KeyObjectData::mutex(), and secret-key export and equality do the same.

Do not allocate a shared mutex that none of these operations uses.
Asymmetric key mutex initialization remains eager so copies continue to
share the same lock while asymmetric acquisitions remain.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
RSA_Cipher delegates to ncrypto::Rsa with a new EVP_PKEY_CTX per
operation. Padding, digests, labels, and output buffers belong to that
context. OpenSSL and BoringSSL synchronize RSA blinding and Montgomery
caches internally.

The lock was introduced for early OpenSSL 3 key downgrading that cleared
shared provider fields. Current OpenSSL publishes a separate legacy
cache under its own lock.

Cover cold shared CryptoKeys and worker clones with concurrent
encrypt/decrypt, synchronous KeyObject aliases, and checked plaintexts.

Refs: nodejs#36825
Refs: https://docs.openssl.org/3.5/man7/openssl-threads/
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
ncrypto::KEM creates a new EVP_PKEY_CTX per operation. Parameters,
entropy, scratch buffers, and outputs are private to each call. ML-KEM
expansion finishes during import, and operations read an immutable key.
EC and X25519 retain read-only recipient keys. RSA synchronizes mutable
caches internally.

Remove the outer locks serializing jobs that share a KeyObject or
CryptoKey. Cover cold keys and worker clones across RSA, EC, X25519, and
ML-KEM, checking every resulting shared secret.

Refs: https://docs.openssl.org/3.5/man7/openssl-threads/
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
@panva
panva requested a review from jasnell September 30, 2026 13:14
@panva panva added crypto Issues and PRs related to the crypto subsystem. webcrypto Issues and PRs related to the Web Crypto API. commit-queue-rebase PRs the Commit Queue should land as multiple self-contained commits. labels Sep 30, 2026
@nodejs-github-bot

Copy link
Copy Markdown
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++. lib / src Issues and PRs involving general changes in the lib/ or src/ directories. needs-ci PRs that need a full CI run. labels Sep 30, 2026
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark GHA (crypto / kem.js): https://github.com/nodejs/node/actions/runs/36720318950

Results

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

Benchmark results:

                                                                                                              confidence improvement accuracy (*)    (**)   (***)
crypto/kem.js n=1000 op='decapsulate' keyFormat='der' mode='sync' keyType='ml-kem-768'                                       -2.43 %       ±8.88% ±11.70% ±15.01%
crypto/kem.js n=1000 op='decapsulate' keyFormat='der' mode='sync' keyType='p-256'                                             0.56 %       ±8.29% ±10.92% ±14.02%
crypto/kem.js n=1000 op='decapsulate' keyFormat='der' mode='sync' keyType='rsa'                                               0.19 %      ±11.18% ±14.73% ±18.90%
crypto/kem.js n=1000 op='decapsulate' keyFormat='der' mode='sync' keyType='x25519'                                            0.72 %       ±7.85% ±10.35% ±13.28%
crypto/kem.js n=1000 op='decapsulate' keyFormat='jwk' mode='sync' keyType='ml-kem-768'                                       -0.11 %       ±7.73% ±10.19% ±13.08%
crypto/kem.js n=1000 op='decapsulate' keyFormat='jwk' mode='sync' keyType='p-256'                                             0.41 %       ±7.12%  ±9.38% ±12.04%
crypto/kem.js n=1000 op='decapsulate' keyFormat='jwk' mode='sync' keyType='rsa'                                               1.29 %      ±11.14% ±14.69% ±18.85%
crypto/kem.js n=1000 op='decapsulate' keyFormat='jwk' mode='sync' keyType='x25519'                                           -0.27 %       ±7.42%  ±9.78% ±12.55%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject.unique' mode='async-parallel' keyType='ml-kem-768'                 0.53 %       ±8.05% ±10.61% ±13.62%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject.unique' mode='async-parallel' keyType='p-256'                     -0.92 %       ±6.47%  ±8.53% ±10.94%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject.unique' mode='async-parallel' keyType='rsa'                        1.79 %       ±7.68% ±10.12% ±12.98%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject.unique' mode='async-parallel' keyType='x25519'                    -0.88 %       ±6.78%  ±8.94% ±11.47%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='async-parallel' keyType='ml-kem-768'               ***    164.82 %      ±16.45% ±21.72% ±27.94%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='async-parallel' keyType='p-256'                    ***    193.50 %      ±14.44% ±19.07% ±24.54%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='async-parallel' keyType='rsa'                      ***    162.68 %      ±18.29% ±24.13% ±30.99%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='async-parallel' keyType='x25519'                   ***    177.27 %      ±14.44% ±19.07% ±24.54%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='async' keyType='ml-kem-768'                                -1.20 %       ±9.01% ±11.87% ±15.23%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='async' keyType='p-256'                                      1.10 %       ±8.36% ±11.02% ±14.14%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='async' keyType='rsa'                                        1.91 %      ±13.17% ±17.36% ±22.27%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='async' keyType='x25519'                                    -0.07 %       ±8.91% ±11.75% ±15.07%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='sync' keyType='ml-kem-768'                                 -0.74 %       ±7.70% ±10.15% ±13.03%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='sync' keyType='p-256'                                       2.06 %       ±6.18%  ±8.15% ±10.45%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='sync' keyType='rsa'                                         0.51 %      ±13.83% ±18.22% ±23.38%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='sync' keyType='x25519'                                      0.15 %       ±7.15%  ±9.42% ±12.08%
crypto/kem.js n=1000 op='decapsulate' keyFormat='pem' mode='sync' keyType='ml-kem-768'                                        0.41 %       ±9.39% ±12.38% ±15.89%
crypto/kem.js n=1000 op='decapsulate' keyFormat='pem' mode='sync' keyType='p-256'                                             0.68 %       ±8.09% ±10.66% ±13.67%
crypto/kem.js n=1000 op='decapsulate' keyFormat='pem' mode='sync' keyType='rsa'                                               0.96 %      ±11.32% ±14.92% ±19.14%
crypto/kem.js n=1000 op='decapsulate' keyFormat='pem' mode='sync' keyType='x25519'                                           -1.08 %       ±8.27% ±10.89% ±13.98%
crypto/kem.js n=1000 op='decapsulate' keyFormat='raw-private' mode='sync' keyType='p-256'                                     1.74 %       ±7.49%  ±9.88% ±12.67%
crypto/kem.js n=1000 op='decapsulate' keyFormat='raw-private' mode='sync' keyType='x25519'                                   -1.66 %       ±6.93%  ±9.14% ±11.73%
crypto/kem.js n=1000 op='decapsulate' keyFormat='raw-seed' mode='sync' keyType='ml-kem-768'                                   0.44 %       ±7.74% ±10.21% ±13.10%
crypto/kem.js n=1000 op='encapsulate' keyFormat='der' mode='sync' keyType='ml-kem-768'                                        1.22 %       ±9.65% ±12.72% ±16.33%
crypto/kem.js n=1000 op='encapsulate' keyFormat='der' mode='sync' keyType='p-256'                                             0.96 %       ±8.31% ±10.95% ±14.05%
crypto/kem.js n=1000 op='encapsulate' keyFormat='der' mode='sync' keyType='rsa'                                               2.32 %      ±10.28% ±13.56% ±17.39%
crypto/kem.js n=1000 op='encapsulate' keyFormat='der' mode='sync' keyType='x25519'                                           -0.14 %       ±8.16% ±10.75% ±13.80%
crypto/kem.js n=1000 op='encapsulate' keyFormat='jwk' mode='sync' keyType='ml-kem-768'                                       -1.64 %       ±9.28% ±12.24% ±15.70%
crypto/kem.js n=1000 op='encapsulate' keyFormat='jwk' mode='sync' keyType='p-256'                                             0.97 %       ±7.18%  ±9.47% ±12.15%
crypto/kem.js n=1000 op='encapsulate' keyFormat='jwk' mode='sync' keyType='rsa'                                               1.70 %       ±9.15% ±12.06% ±15.48%
crypto/kem.js n=1000 op='encapsulate' keyFormat='jwk' mode='sync' keyType='x25519'                                           -0.61 %       ±7.72% ±10.17% ±13.05%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject.unique' mode='async-parallel' keyType='ml-kem-768'                 0.74 %       ±9.38% ±12.37% ±15.87%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject.unique' mode='async-parallel' keyType='p-256'                     -0.82 %       ±6.71%  ±8.84% ±11.34%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject.unique' mode='async-parallel' keyType='rsa'                        3.94 %       ±8.92% ±11.76% ±15.08%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject.unique' mode='async-parallel' keyType='x25519'                    -0.43 %       ±7.24%  ±9.54% ±12.25%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='async-parallel' keyType='ml-kem-768'               ***    142.10 %      ±15.66% ±20.67% ±26.58%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='async-parallel' keyType='p-256'                    ***    201.81 %      ±15.51% ±20.48% ±26.36%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='async-parallel' keyType='rsa'                      ***    164.76 %      ±16.04% ±21.19% ±27.27%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='async-parallel' keyType='x25519'                   ***    201.94 %      ±16.71% ±22.07% ±28.41%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='async' keyType='ml-kem-768'                                 0.07 %       ±9.45% ±12.45% ±15.97%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='async' keyType='p-256'                                     -0.67 %       ±8.18% ±10.78% ±13.83%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='async' keyType='rsa'                                        1.01 %       ±9.44% ±12.44% ±15.96%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='async' keyType='x25519'                                     0.20 %       ±8.59% ±11.32% ±14.52%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='sync' keyType='ml-kem-768'                                  0.91 %       ±8.77% ±11.55% ±14.83%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='sync' keyType='p-256'                                       1.47 %       ±6.39%  ±8.43% ±10.81%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='sync' keyType='rsa'                                         2.01 %       ±8.36% ±11.01% ±14.13%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='sync' keyType='x25519'                                      0.37 %       ±7.15%  ±9.42% ±12.09%
crypto/kem.js n=1000 op='encapsulate' keyFormat='pem' mode='sync' keyType='ml-kem-768'                                       -1.35 %       ±9.87% ±13.01% ±16.70%
crypto/kem.js n=1000 op='encapsulate' keyFormat='pem' mode='sync' keyType='p-256'                                             1.18 %       ±8.03% ±10.58% ±13.58%
crypto/kem.js n=1000 op='encapsulate' keyFormat='pem' mode='sync' keyType='rsa'                                               1.08 %      ±10.66% ±14.05% ±18.03%
crypto/kem.js n=1000 op='encapsulate' keyFormat='pem' mode='sync' keyType='x25519'                                           -0.31 %       ±8.23% ±10.85% ±13.92%
crypto/kem.js n=1000 op='encapsulate' keyFormat='raw-public' mode='sync' keyType='ml-kem-768'                                 0.55 %       ±9.09% ±11.98% ±15.37%
crypto/kem.js n=1000 op='encapsulate' keyFormat='raw-public' mode='sync' keyType='p-256'                                      0.90 %       ±7.54%  ±9.94% ±12.75%
crypto/kem.js n=1000 op='encapsulate' keyFormat='raw-public' mode='sync' keyType='x25519'                                    -1.78 %       ±7.71% ±10.16% ±13.04%
crypto/kem.js n=1000 op='encapsulate' keyFormat='raw-seed' mode='sync' keyType='ml-kem-768'                                  -0.30 %       ±8.01% ±10.55% ±13.54%

Be aware that when doing many comparisons the risk of a false-positive
result increases. In this case, there are 63 comparisons, you can thus
expect the following amount of false-positive results:
  3.15 false positives, when considering a   5% risk acceptance (*, **, ***),
  0.63 false positives, when considering a   1% risk acceptance (**, ***),
  0.06 false positives, when considering a 0.1% risk acceptance (***)

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='async-parallel' keyType='ml-kem-768'               ***    164.82 %      ±16.45% ±21.72% ±27.94%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='async-parallel' keyType='p-256'                    ***    193.50 %      ±14.44% ±19.07% ±24.54%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='async-parallel' keyType='rsa'                      ***    162.68 %      ±18.29% ±24.13% ±30.99%
crypto/kem.js n=1000 op='decapsulate' keyFormat='keyObject' mode='async-parallel' keyType='x25519'                   ***    177.27 %      ±14.44% ±19.07% ±24.54%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='async-parallel' keyType='ml-kem-768'               ***    142.10 %      ±15.66% ±20.67% ±26.58%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='async-parallel' keyType='p-256'                    ***    201.81 %      ±15.51% ±20.48% ±26.36%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='async-parallel' keyType='rsa'                      ***    164.76 %      ±16.04% ±21.19% ±27.27%
crypto/kem.js n=1000 op='encapsulate' keyFormat='keyObject' mode='async-parallel' keyType='x25519'                   ***    201.94 %      ±16.71% ±22.07% ±28.41%

@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark GHA (crypto / verify.js): https://github.com/nodejs/node/actions/runs/36720331582

Results

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

Benchmark results:

                                                                                                       confidence improvement accuracy (*)    (**)   (***)
crypto/oneshot-verify.js n=1000 keyFormat='der' mode='sync' keyType='ec'                                              -0.41 %       ±5.75%  ±7.58%  ±9.73%
crypto/oneshot-verify.js n=1000 keyFormat='der' mode='sync' keyType='ed25519'                                          1.34 %       ±6.20%  ±8.18% ±10.49%
crypto/oneshot-verify.js n=1000 keyFormat='der' mode='sync' keyType='ml-dsa-44'                                       -0.35 %       ±7.46%  ±9.84% ±12.62%
crypto/oneshot-verify.js n=1000 keyFormat='der' mode='sync' keyType='rsa'                                              1.03 %       ±7.06%  ±9.31% ±11.94%
crypto/oneshot-verify.js n=1000 keyFormat='jwk' mode='sync' keyType='ec'                                               2.58 %       ±5.44%  ±7.17%  ±9.20%
crypto/oneshot-verify.js n=1000 keyFormat='jwk' mode='sync' keyType='ed25519'                                          0.62 %       ±5.93%  ±7.81% ±10.02%
crypto/oneshot-verify.js n=1000 keyFormat='jwk' mode='sync' keyType='ml-dsa-44'                                       -2.36 %       ±7.54%  ±9.94% ±12.76%
crypto/oneshot-verify.js n=1000 keyFormat='jwk' mode='sync' keyType='rsa'                                              0.42 %       ±6.36%  ±8.39% ±10.76%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject.unique' mode='async-parallel' keyType='ec'                       -1.13 %       ±6.65%  ±8.76% ±11.24%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject.unique' mode='async-parallel' keyType='ed25519'                  -0.35 %       ±9.81% ±12.93% ±16.59%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject.unique' mode='async-parallel' keyType='ml-dsa-44'                 0.22 %       ±8.19% ±10.80% ±13.86%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject.unique' mode='async-parallel' keyType='rsa'                       3.23 %       ±9.33% ±12.29% ±15.78%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject' mode='async-parallel' keyType='ec'                               0.23 %       ±6.51%  ±8.59% ±11.02%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject' mode='async-parallel' keyType='ed25519'                         -1.07 %       ±9.71% ±12.80% ±16.42%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject' mode='async-parallel' keyType='ml-dsa-44'                        0.91 %       ±8.43% ±11.11% ±14.25%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject' mode='async-parallel' keyType='rsa'                              2.45 %       ±8.57% ±11.30% ±14.50%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject' mode='async' keyType='ec'                                       -0.08 %       ±6.94%  ±9.15% ±11.74%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject' mode='async' keyType='ed25519'                                   0.78 %       ±6.97%  ±9.18% ±11.78%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject' mode='async' keyType='ml-dsa-44'                                 1.18 %       ±8.05% ±10.61% ±13.61%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject' mode='async' keyType='rsa'                                       1.88 %       ±8.02% ±10.57% ±13.57%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject' mode='sync' keyType='ec'                                         0.61 %       ±4.44%  ±5.85%  ±7.51%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject' mode='sync' keyType='ed25519'                                   -0.41 %       ±5.88%  ±7.76%  ±9.95%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject' mode='sync' keyType='ml-dsa-44'                                 -1.13 %       ±6.76%  ±8.91% ±11.43%
crypto/oneshot-verify.js n=1000 keyFormat='keyObject' mode='sync' keyType='rsa'                                       -0.32 %       ±5.79%  ±7.63%  ±9.79%
crypto/oneshot-verify.js n=1000 keyFormat='pem' mode='sync' keyType='ec'                                               1.77 %       ±5.70%  ±7.51%  ±9.63%
crypto/oneshot-verify.js n=1000 keyFormat='pem' mode='sync' keyType='ed25519'                                          1.33 %       ±6.22%  ±8.20% ±10.52%
crypto/oneshot-verify.js n=1000 keyFormat='pem' mode='sync' keyType='ml-dsa-44'                                       -0.64 %       ±7.42%  ±9.78% ±12.54%
crypto/oneshot-verify.js n=1000 keyFormat='pem' mode='sync' keyType='rsa'                                              0.64 %       ±7.23%  ±9.53% ±12.23%
crypto/oneshot-verify.js n=1000 keyFormat='raw-public' mode='sync' keyType='ec'                                        1.53 %       ±5.34%  ±7.04%  ±9.03%
crypto/oneshot-verify.js n=1000 keyFormat='raw-public' mode='sync' keyType='ed25519'                                  -0.31 %       ±6.03%  ±7.95% ±10.20%
crypto/oneshot-verify.js n=1000 keyFormat='raw-public' mode='sync' keyType='ml-dsa-44'                                -1.05 %       ±7.45%  ±9.81% ±12.59%
crypto/webcrypto-verify.js n=1000 keyReuse='shared' mode='parallel' keyType='ec'                                       0.35 %       ±7.36%  ±9.71% ±12.45%
crypto/webcrypto-verify.js n=1000 keyReuse='shared' mode='parallel' keyType='ed25519'                                  0.07 %       ±9.85% ±12.99% ±16.67%
crypto/webcrypto-verify.js n=1000 keyReuse='shared' mode='parallel' keyType='ml-dsa-44'                                1.80 %       ±9.14% ±12.05% ±15.46%
crypto/webcrypto-verify.js n=1000 keyReuse='shared' mode='parallel' keyType='rsa-pss'                                  2.03 %      ±10.71% ±14.12% ±18.12%
crypto/webcrypto-verify.js n=1000 keyReuse='shared' mode='parallel' keyType='rsassa-pkcs1-v1_5'                        1.06 %      ±11.10% ±14.62% ±18.77%
crypto/webcrypto-verify.js n=1000 keyReuse='shared' mode='serial' keyType='ec'                                         0.38 %       ±8.76% ±11.54% ±14.81%
crypto/webcrypto-verify.js n=1000 keyReuse='shared' mode='serial' keyType='ed25519'                                    0.47 %       ±7.91% ±10.43% ±13.38%
crypto/webcrypto-verify.js n=1000 keyReuse='shared' mode='serial' keyType='ml-dsa-44'                                 -0.10 %       ±9.43% ±12.43% ±15.95%
crypto/webcrypto-verify.js n=1000 keyReuse='shared' mode='serial' keyType='rsa-pss'                                    1.38 %       ±9.31% ±12.27% ±15.74%
crypto/webcrypto-verify.js n=1000 keyReuse='shared' mode='serial' keyType='rsassa-pkcs1-v1_5'                          1.34 %       ±9.19% ±12.12% ±15.55%
crypto/webcrypto-verify.js n=1000 keyReuse='unique' mode='parallel' keyType='ec'                                      -0.01 %       ±7.39%  ±9.75% ±12.51%
crypto/webcrypto-verify.js n=1000 keyReuse='unique' mode='parallel' keyType='ed25519'                                  0.20 %       ±9.26% ±12.21% ±15.66%
crypto/webcrypto-verify.js n=1000 keyReuse='unique' mode='parallel' keyType='ml-dsa-44'                                1.30 %       ±9.38% ±12.37% ±15.87%
crypto/webcrypto-verify.js n=1000 keyReuse='unique' mode='parallel' keyType='rsa-pss'                                  2.09 %       ±9.29% ±12.25% ±15.72%
crypto/webcrypto-verify.js n=1000 keyReuse='unique' mode='parallel' keyType='rsassa-pkcs1-v1_5'                       -0.79 %       ±9.54% ±12.58% ±16.14%

Be aware that when doing many comparisons the risk of a false-positive
result increases. In this case, there are 46 comparisons, you can thus
expect the following amount of false-positive results:
  2.30 false positives, when considering a   5% risk acceptance (*, **, ***),
  0.46 false positives, when considering a   1% risk acceptance (**, ***),
  0.05 false positives, when considering a 0.1% risk acceptance (***)

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

Verify configuration only copies signature bytes and reads DSA/EC order
width for P1363 conversion. Conversion constructs independent DER and
BIGNUM values. Signing and verification already run without the mutex
using separate operation contexts.

Cover cold shared public keys and worker clones with checked P1363
verification while signatures, derivation, exports, metadata queries,
and equality checks overlap.

Compare source PKCS8 encoding after workers finish. OpenSSL's ordinary
EC PKCS8 encoder temporarily changes source flags and races even on the
unmodified base. Keep WebCrypto PKCS8 exports concurrent through their
independent clones.

Refs: nodejs#36825
Refs: nodejs#37816
Refs: https://docs.openssl.org/3.5/man7/openssl-threads/
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
Raw and JWK getters return independently owned bytes or BIGNUMs. RSA
metadata snapshots public parameters and PSS restrictions. EC fallback
paths reconstruct or duplicate the source key. EC PKCS8 export changes
encoding flags only on its own clone.

Early OpenSSL 3 key downgrading mutated shared provider fields. Current
OpenSSL publishes separate legacy and provider conversion caches under
internal read/write locks. Ordinary DER/PEM export, equality, signing,
and key derivation already access the same keys without these locks.

Remove export and metadata acquisitions, including their coverage of V8
allocation and encoding, and remove the now-unused shared mutex storage.
Retain shared immutable key ownership. The concurrent reuse test checks
that EC PKCS8 export leaves the original flags intact.

Refs: nodejs#36825
Refs: https://docs.openssl.org/3.5/man7/openssl-threads/
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark GHA (crypto / export.js): https://github.com/nodejs/node/actions/runs/36720345253

Results

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

Benchmark results:

                                                                                                 confidence improvement accuracy (*)    (**)   (***)
crypto/ec-jwk-export.js n=10000 type='private' namedCurve='prime256v1'                                          -1.48 %       ±7.82% ±10.31% ±13.23%
crypto/ec-jwk-export.js n=10000 type='private' namedCurve='secp256k1'                                            3.69 %       ±9.89% ±13.04% ±16.74%
crypto/ec-jwk-export.js n=10000 type='private' namedCurve='secp384r1'                                            1.33 %      ±17.04% ±22.46% ±28.82%
crypto/ec-jwk-export.js n=10000 type='private' namedCurve='secp521r1'                                            1.84 %      ±17.08% ±22.51% ±28.88%
crypto/ec-jwk-export.js n=10000 type='public' namedCurve='prime256v1'                                           -0.26 %       ±7.59% ±10.01% ±12.84%
crypto/ec-jwk-export.js n=10000 type='public' namedCurve='secp256k1'                                             1.56 %      ±10.22% ±13.48% ±17.29%
crypto/ec-jwk-export.js n=10000 type='public' namedCurve='secp384r1'                                             0.32 %      ±18.12% ±23.89% ±30.65%
crypto/ec-jwk-export.js n=10000 type='public' namedCurve='secp521r1'                                             3.18 %      ±18.23% ±24.03% ±30.83%
crypto/ec-raw-export.js n=10000 type='compressed' format='raw-public' namedCurve='prime256v1'                    2.49 %       ±6.69%  ±8.82% ±11.32%
crypto/ec-raw-export.js n=10000 type='compressed' format='raw-public' namedCurve='secp384r1'                     1.35 %      ±16.36% ±21.57% ±27.68%
crypto/ec-raw-export.js n=10000 type='compressed' format='raw-public' namedCurve='secp521r1'                    -0.69 %      ±15.12% ±19.94% ±25.58%
crypto/ec-raw-export.js n=10000 type='uncompressed' format='raw-private' namedCurve='prime256v1'                -0.27 %       ±5.65%  ±7.45%  ±9.56%
crypto/ec-raw-export.js n=10000 type='uncompressed' format='raw-private' namedCurve='secp384r1'                  2.00 %       ±6.20%  ±8.17% ±10.49%
crypto/ec-raw-export.js n=10000 type='uncompressed' format='raw-private' namedCurve='secp521r1'                  1.71 %       ±6.28%  ±8.28% ±10.62%
crypto/ec-raw-export.js n=10000 type='uncompressed' format='raw-public' namedCurve='prime256v1'                 -0.73 %       ±5.49%  ±7.24%  ±9.29%
crypto/ec-raw-export.js n=10000 type='uncompressed' format='raw-public' namedCurve='secp384r1'                   3.31 %      ±21.71% ±28.62% ±36.72%
crypto/ec-raw-export.js n=10000 type='uncompressed' format='raw-public' namedCurve='secp521r1'                  -0.35 %      ±20.95% ±27.61% ±35.43%
crypto/webcrypto-export.js n=100000 keyType='aes-gcm'                                                            1.00 %       ±8.75% ±11.54% ±14.81%
crypto/webcrypto-export.js n=100000 keyType='ecdsa-private'                                                      0.95 %       ±7.84% ±10.33% ±13.25%
crypto/webcrypto-export.js n=100000 keyType='hmac'                                                               0.23 %       ±8.60% ±11.33% ±14.54%
crypto/webcrypto-export.js n=100000 keyType='rsa-private'                                                       -0.40 %       ±5.91%  ±7.79% ±10.00%
crypto/webcrypto-export.js n=100000 keyType='rsa-public'                                                        -0.39 %       ±5.84%  ±7.69%  ±9.87%

Be aware that when doing many comparisons the risk of a false-positive
result increases. In this case, there are 22 comparisons, you can thus
expect the following amount of false-positive results:
  1.10 false positives, when considering a   5% risk acceptance (*, **, ***),
  0.22 false positives, when considering a   1% risk acceptance (**, ***),
  0.02 false positives, when considering a 0.1% risk acceptance (***)

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark GHA (crypto / key-details.js): https://github.com/nodejs/node/actions/runs/36720356022

Results

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

Benchmark results:

                                                                   confidence improvement accuracy (*)    (**)   (***)
crypto/ec-key-details.js n=10000 type='private' namedCurve='P-256'                 3.89 %       ±7.43%  ±9.79% ±12.57%
crypto/ec-key-details.js n=10000 type='private' namedCurve='P-384'                 4.83 %       ±7.44%  ±9.81% ±12.59%
crypto/ec-key-details.js n=10000 type='private' namedCurve='P-521'                 2.99 %       ±7.53%  ±9.93% ±12.74%
crypto/ec-key-details.js n=10000 type='public' namedCurve='P-256'                  4.48 %       ±7.36%  ±9.70% ±12.44%
crypto/ec-key-details.js n=10000 type='public' namedCurve='P-384'                  4.93 %       ±7.36%  ±9.70% ±12.44%
crypto/ec-key-details.js n=10000 type='public' namedCurve='P-521'                  4.21 %       ±7.75% ±10.21% ±13.11%
crypto/rsa-key-details.js n=10000 type='private'                                   1.70 %       ±4.77%  ±6.28%  ±8.06%
crypto/rsa-key-details.js n=10000 type='public'                                    0.04 %       ±5.07%  ±6.68%  ±8.57%
crypto/rsa-pss-key-details.js n=5000 restrictions='absent'                         3.89 %       ±5.96%  ±7.85% ±10.07%
crypto/rsa-pss-key-details.js n=5000 restrictions='defaults'                       1.97 %       ±5.53%  ±7.29%  ±9.36%
crypto/rsa-pss-key-details.js n=5000 restrictions='sha256'                         1.37 %       ±6.17%  ±8.14% ±10.44%

Be aware that when doing many comparisons the risk of a false-positive
result increases. In this case, there are 11 comparisons, you can thus
expect the following amount of false-positive results:
  0.55 false positives, when considering a   5% risk acceptance (*, **, ***),
  0.11 false positives, when considering a   1% risk acceptance (**, ***),
  0.01 false positives, when considering a 0.1% risk acceptance (***)

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark GHA (crypto / keyobject-serialization.js): https://github.com/nodejs/node/actions/runs/36720367101

Results

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

Benchmark results:

                                                                                                                             confidence improvement accuracy (*)    (**)   (***)
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='export' keyType='ed25519'                                   0.08 %       ±7.59% ±10.01% ±12.84%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='export' keyType='ml-dsa-44'                                 1.25 %       ±7.49%  ±9.87% ±12.67%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='export' keyType='ml-kem-768'                                0.72 %       ±7.52%  ±9.91% ±12.72%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='export' keyType='p-256'                                     0.38 %       ±6.82%  ±8.99% ±11.54%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='export' keyType='rsa-pss'                                   0.29 %       ±6.62%  ±8.73% ±11.20%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='export' keyType='rsa'                                      -0.37 %       ±6.53%  ±8.60% ±11.04%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='export' keyType='slh-dsa-sha2-128s'                         1.38 %       ±7.57%  ±9.98% ±12.81%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='export' keyType='x25519'                                   -0.24 %       ±7.52%  ±9.92% ±12.72%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='import' keyType='ed25519'                                   1.52 %       ±6.74%  ±8.88% ±11.40%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='import' keyType='ml-dsa-44'                                 2.38 %       ±5.36%  ±7.06%  ±9.06%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='import' keyType='ml-kem-768'                                1.90 %       ±7.12%  ±9.39% ±12.05%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='import' keyType='p-256'                                     2.30 %       ±8.64% ±11.39% ±14.62%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='import' keyType='rsa-pss'                                   0.58 %       ±7.98% ±10.51% ±13.49%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='import' keyType='rsa'                                       1.49 %       ±8.18% ±10.79% ±13.84%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='import' keyType='slh-dsa-sha2-128s'                         2.89 %       ±8.86% ±11.68% ±14.99%
crypto/keyobject-serialization.js n=10000 type='private' format='der' operation='import' keyType='x25519'                                    1.70 %       ±6.77%  ±8.93% ±11.45%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='export' keyType='ed25519'                                   2.79 %       ±7.07%  ±9.32% ±11.97%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='export' keyType='ml-dsa-44'                                 1.36 %       ±6.83%  ±9.00% ±11.55%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='export' keyType='ml-kem-768'                                2.26 %       ±6.18%  ±8.15% ±10.45%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='export' keyType='p-256'                                     1.74 %       ±5.42%  ±7.14%  ±9.16%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='export' keyType='rsa'                                       0.15 %       ±4.11%  ±5.42%  ±6.95%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='export' keyType='slh-dsa-sha2-128s'                         1.63 %       ±6.89%  ±9.09% ±11.66%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='export' keyType='x25519'                                    3.57 %       ±7.09%  ±9.35% ±11.99%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='import' keyType='ed25519'                                   1.52 %       ±6.18%  ±8.15% ±10.45%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='import' keyType='ml-dsa-44'                                 3.47 %       ±5.30%  ±6.98%  ±8.96%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='import' keyType='ml-kem-768'                                2.17 %       ±5.68%  ±7.48%  ±9.60%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='import' keyType='p-256'                                     2.08 %       ±7.03%  ±9.27% ±11.89%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='import' keyType='rsa'                                       1.10 %       ±6.41%  ±8.45% ±10.84%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='import' keyType='slh-dsa-sha2-128s'                         7.35 %       ±8.10% ±10.67% ±13.69%
crypto/keyobject-serialization.js n=10000 type='private' format='jwk' operation='import' keyType='x25519'                                    1.76 %       ±6.10%  ±8.03% ±10.31%
crypto/keyobject-serialization.js n=10000 type='private' format='raw-private' operation='export' keyType='ed25519'                           3.27 %       ±7.63% ±10.06% ±12.91%
crypto/keyobject-serialization.js n=10000 type='private' format='raw-private' operation='export' keyType='p-256'                             1.38 %       ±4.56%  ±6.01%  ±7.71%
crypto/keyobject-serialization.js n=10000 type='private' format='raw-private' operation='export' keyType='slh-dsa-sha2-128s'                 4.41 %       ±7.75% ±10.21% ±13.10%
crypto/keyobject-serialization.js n=10000 type='private' format='raw-private' operation='export' keyType='x25519'                            4.66 %       ±7.47%  ±9.84% ±12.63%
crypto/keyobject-serialization.js n=10000 type='private' format='raw-private' operation='import' keyType='ed25519'                           1.73 %       ±6.17%  ±8.14% ±10.44%
crypto/keyobject-serialization.js n=10000 type='private' format='raw-private' operation='import' keyType='p-256'                             3.75 %       ±6.75%  ±8.90% ±11.42%
crypto/keyobject-serialization.js n=10000 type='private' format='raw-private' operation='import' keyType='slh-dsa-sha2-128s'                 5.63 %       ±7.92% ±10.44% ±13.39%
crypto/keyobject-serialization.js n=10000 type='private' format='raw-private' operation='import' keyType='x25519'                            1.73 %       ±6.10%  ±8.05% ±10.32%
crypto/keyobject-serialization.js n=10000 type='private' format='raw-seed' operation='export' keyType='ml-dsa-44'                            6.29 %       ±8.74% ±11.52% ±14.78%
crypto/keyobject-serialization.js n=10000 type='private' format='raw-seed' operation='export' keyType='ml-kem-768'                           6.28 %       ±8.86% ±11.68% ±14.99%
crypto/keyobject-serialization.js n=10000 type='private' format='raw-seed' operation='import' keyType='ml-dsa-44'                            1.41 %       ±5.40%  ±7.12%  ±9.13%
crypto/keyobject-serialization.js n=10000 type='private' format='raw-seed' operation='import' keyType='ml-kem-768'                           1.82 %       ±5.64%  ±7.43%  ±9.54%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='export' keyType='ed25519'                                    0.79 %       ±7.63% ±10.05% ±12.90%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='export' keyType='ml-dsa-44'                                  1.83 %       ±7.34%  ±9.68% ±12.42%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='export' keyType='ml-kem-768'                                 0.68 %       ±7.17%  ±9.45% ±12.13%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='export' keyType='p-256'                                      0.39 %       ±5.94%  ±7.83% ±10.05%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='export' keyType='rsa-pss'                                   -1.06 %       ±7.20%  ±9.48% ±12.17%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='export' keyType='rsa'                                        0.24 %       ±7.39%  ±9.74% ±12.50%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='export' keyType='slh-dsa-sha2-128s'                          1.18 %       ±7.20%  ±9.49% ±12.18%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='export' keyType='x25519'                                     1.57 %       ±7.54%  ±9.94% ±12.76%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='import' keyType='ed25519'                                    4.07 %       ±8.53% ±11.24% ±14.42%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='import' keyType='ml-dsa-44'                                  5.71 %       ±9.02% ±11.89% ±15.26%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='import' keyType='ml-kem-768'                                 3.76 %       ±7.61% ±10.03% ±12.87%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='import' keyType='p-256'                                      3.36 %       ±8.85% ±11.66% ±14.97%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='import' keyType='rsa-pss'                                    3.67 %       ±8.64% ±11.39% ±14.61%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='import' keyType='rsa'                                        3.87 %       ±8.59% ±11.32% ±14.53%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='import' keyType='slh-dsa-sha2-128s'                          5.68 %       ±8.91% ±11.74% ±15.07%
crypto/keyobject-serialization.js n=10000 type='public' format='der' operation='import' keyType='x25519'                                     4.08 %       ±8.67% ±11.43% ±14.67%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='export' keyType='ed25519'                                    4.00 %       ±7.36%  ±9.70% ±12.45%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='export' keyType='ml-dsa-44'                                  4.33 %       ±6.93%  ±9.13% ±11.71%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='export' keyType='ml-kem-768'                                 1.06 %       ±5.85%  ±7.71%  ±9.89%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='export' keyType='p-256'                                      2.64 %       ±4.69%  ±6.18%  ±7.93%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='export' keyType='rsa'                                       -0.14 %       ±3.89%  ±5.12%  ±6.57%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='export' keyType='slh-dsa-sha2-128s'                          2.87 %       ±7.12%  ±9.39% ±12.04%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='export' keyType='x25519'                                     4.72 %       ±7.27%  ±9.59% ±12.30%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='import' keyType='ed25519'                                    8.01 %       ±8.16% ±10.75% ±13.80%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='import' keyType='ml-dsa-44'                                  4.50 %       ±8.13% ±10.71% ±13.75%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='import' keyType='ml-kem-768'                                 3.16 %       ±7.07%  ±9.31% ±11.95%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='import' keyType='p-256'                                      4.62 %       ±7.62% ±10.05% ±12.89%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='import' keyType='rsa'                                        3.81 %       ±7.73% ±10.18% ±13.07%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='import' keyType='slh-dsa-sha2-128s'                          7.20 %       ±7.94% ±10.47% ±13.43%
crypto/keyobject-serialization.js n=10000 type='public' format='jwk' operation='import' keyType='x25519'                                     6.29 %       ±7.75% ±10.22% ±13.11%
crypto/keyobject-serialization.js n=10000 type='public' format='raw-public' operation='export' keyType='ed25519'                             3.27 %       ±7.51%  ±9.89% ±12.69%
crypto/keyobject-serialization.js n=10000 type='public' format='raw-public' operation='export' keyType='ml-dsa-44'                           3.80 %      ±10.61% ±13.98% ±17.94%
crypto/keyobject-serialization.js n=10000 type='public' format='raw-public' operation='export' keyType='ml-kem-768'                          2.95 %       ±6.86%  ±9.04% ±11.61%
crypto/keyobject-serialization.js n=10000 type='public' format='raw-public' operation='export' keyType='p-256'                               1.89 %       ±3.29%  ±4.34%  ±5.57%
crypto/keyobject-serialization.js n=10000 type='public' format='raw-public' operation='export' keyType='slh-dsa-sha2-128s'                   5.88 %       ±7.94% ±10.47% ±13.43%
crypto/keyobject-serialization.js n=10000 type='public' format='raw-public' operation='export' keyType='x25519'                              5.81 %       ±7.76% ±10.23% ±13.12%
crypto/keyobject-serialization.js n=10000 type='public' format='raw-public' operation='import' keyType='ed25519'                             8.10 %       ±8.17% ±10.77% ±13.81%
crypto/keyobject-serialization.js n=10000 type='public' format='raw-public' operation='import' keyType='ml-dsa-44'                           5.83 %       ±8.88% ±11.71% ±15.03%
crypto/keyobject-serialization.js n=10000 type='public' format='raw-public' operation='import' keyType='ml-kem-768'                          3.13 %       ±7.25%  ±9.56% ±12.27%
crypto/keyobject-serialization.js n=10000 type='public' format='raw-public' operation='import' keyType='p-256'                               4.68 %       ±7.50%  ±9.89% ±12.69%
crypto/keyobject-serialization.js n=10000 type='public' format='raw-public' operation='import' keyType='slh-dsa-sha2-128s'                   6.92 %       ±8.17% ±10.77% ±13.82%
crypto/keyobject-serialization.js n=10000 type='public' format='raw-public' operation='import' keyType='x25519'                       *      7.96 %       ±7.81% ±10.30% ±13.21%

Be aware that when doing many comparisons the risk of a false-positive
result increases. In this case, there are 84 comparisons, you can thus
expect the following amount of false-positive results:
  4.20 false positives, when considering a   5% risk acceptance (*, **, ***),
  0.84 false positives, when considering a   1% risk acceptance (**, ***),
  0.08 false positives, when considering a 0.1% risk acceptance (***)

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark GHA (crypto / class-construction.js): https://github.com/nodejs/node/actions/runs/36720379055

Results

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

Benchmark results:

                                                                confidence improvement accuracy (*)    (**)   (***)
crypto/class-construction.js n=10 type='DiffieHellman'                         -0.22 %       ±3.15%  ±4.16%  ±5.33%
crypto/class-construction.js n=100000 type='Cipheriv'                          -2.27 %       ±7.68% ±10.12% ±12.99%
crypto/class-construction.js n=100000 type='Decipheriv'                         0.89 %       ±7.79% ±10.27% ±13.17%
crypto/class-construction.js n=100000 type='Hash'                               0.47 %       ±6.89%  ±9.08% ±11.66%
crypto/class-construction.js n=100000 type='KeyObject'                  **     10.25 %       ±6.22%  ±8.20% ±10.53%
crypto/class-construction.js n=100000 type='Sign'                               0.74 %       ±7.19%  ±9.47% ±12.15%
crypto/class-construction.js n=100000 type='Verify'                            -0.02 %       ±6.90%  ±9.09% ±11.66%
crypto/class-construction.js n=10000000 type='Certificate'                     -0.61 %      ±10.49% ±13.83% ±17.74%
crypto/class-construction.js n=200000 type='DiffieHellmanGroup'                 2.36 %       ±7.47%  ±9.85% ±12.64%
crypto/class-construction.js n=200000 type='ECDH'                               1.27 %       ±7.60% ±10.02% ±12.86%
crypto/class-construction.js n=5000 type='X509Certificate'                      0.69 %       ±7.11%  ±9.38% ±12.03%
crypto/class-construction.js n=50000 type='CryptoKey'                           2.45 %       ±6.75%  ±8.89% ±11.41%
crypto/class-construction.js n=50000 type='Hmac'                               -0.30 %       ±8.11% ±10.69% ±13.72%

Be aware that when doing many comparisons the risk of a false-positive
result increases. In this case, there are 13 comparisons, you can thus
expect the following amount of false-positive results:
  0.65 false positives, when considering a   5% risk acceptance (*, **, ***),
  0.13 false positives, when considering a   1% risk acceptance (**, ***),
  0.01 false positives, when considering a 0.1% risk acceptance (***)

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

crypto/class-construction.js n=100000 type='KeyObject'                  **     10.25 %       ±6.22%  ±8.20% ±10.53%

@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark GHA (crypto / sign.js): https://github.com/nodejs/node/actions/runs/36720391744

Results

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

Benchmark results:

                                                                                                     confidence improvement accuracy (*)    (**)   (***)
crypto/oneshot-sign.js n=1000 keyFormat='der' mode='sync' keyType='ec'                                               0.24 %       ±9.06% ±11.94% ±15.33%
crypto/oneshot-sign.js n=1000 keyFormat='der' mode='sync' keyType='ed25519'                                          1.15 %       ±6.93%  ±9.13% ±11.71%
crypto/oneshot-sign.js n=1000 keyFormat='der' mode='sync' keyType='ml-dsa-44'                                        1.03 %       ±7.67% ±10.11% ±12.97%
crypto/oneshot-sign.js n=1000 keyFormat='der' mode='sync' keyType='rsa'                                             -0.52 %       ±4.06%  ±5.35%  ±6.87%
crypto/oneshot-sign.js n=1000 keyFormat='jwk' mode='sync' keyType='ec'                                               0.73 %       ±8.21% ±10.82% ±13.88%
crypto/oneshot-sign.js n=1000 keyFormat='jwk' mode='sync' keyType='ed25519'                                          1.04 %       ±6.61%  ±8.71% ±11.17%
crypto/oneshot-sign.js n=1000 keyFormat='jwk' mode='sync' keyType='ml-dsa-44'                                        0.58 %       ±7.65% ±10.08% ±12.94%
crypto/oneshot-sign.js n=1000 keyFormat='jwk' mode='sync' keyType='rsa'                                             -0.13 %       ±3.88%  ±5.11%  ±6.56%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject.unique' mode='async-parallel' keyType='ec'                        0.49 %       ±8.10% ±10.68% ±13.71%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject.unique' mode='async-parallel' keyType='ed25519'                   0.78 %       ±8.05% ±10.60% ±13.61%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject.unique' mode='async-parallel' keyType='ml-dsa-44'                -0.76 %       ±8.73% ±11.51% ±14.76%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject.unique' mode='async-parallel' keyType='rsa'                      -1.09 %       ±5.27%  ±6.95%  ±8.92%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject' mode='async-parallel' keyType='ec'                              -0.97 %       ±7.11%  ±9.37% ±12.02%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject' mode='async-parallel' keyType='ed25519'                          1.42 %       ±9.04% ±11.91% ±15.29%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject' mode='async-parallel' keyType='ml-dsa-44'                        0.16 %       ±8.34% ±10.99% ±14.10%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject' mode='async-parallel' keyType='rsa'                             -0.66 %       ±6.04%  ±7.96% ±10.21%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject' mode='async' keyType='ec'                                        0.11 %       ±8.18% ±10.78% ±13.84%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject' mode='async' keyType='ed25519'                                  -1.13 %       ±7.69% ±10.14% ±13.01%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject' mode='async' keyType='ml-dsa-44'                                 0.25 %       ±7.82% ±10.31% ±13.22%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject' mode='async' keyType='rsa'                                       0.17 %       ±3.80%  ±5.01%  ±6.43%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject' mode='sync' keyType='ec'                                        -0.60 %       ±6.91%  ±9.11% ±11.69%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject' mode='sync' keyType='ed25519'                                    0.35 %       ±6.72%  ±8.86% ±11.37%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject' mode='sync' keyType='ml-dsa-44'                                 -0.12 %       ±7.60% ±10.02% ±12.85%
crypto/oneshot-sign.js n=1000 keyFormat='keyObject' mode='sync' keyType='rsa'                                       -0.57 %       ±3.90%  ±5.14%  ±6.59%
crypto/oneshot-sign.js n=1000 keyFormat='pem' mode='sync' keyType='ec'                                               0.17 %       ±9.64% ±12.71% ±16.30%
crypto/oneshot-sign.js n=1000 keyFormat='pem' mode='sync' keyType='ed25519'                                          0.73 %       ±6.62%  ±8.72% ±11.19%
crypto/oneshot-sign.js n=1000 keyFormat='pem' mode='sync' keyType='ml-dsa-44'                                        0.30 %       ±7.69% ±10.14% ±13.01%
crypto/oneshot-sign.js n=1000 keyFormat='pem' mode='sync' keyType='rsa'                                             -0.29 %       ±3.82%  ±5.04%  ±6.46%
crypto/oneshot-sign.js n=1000 keyFormat='raw-private' mode='sync' keyType='ec'                                       0.96 %       ±7.96% ±10.49% ±13.47%
crypto/oneshot-sign.js n=1000 keyFormat='raw-private' mode='sync' keyType='ed25519'                                  0.57 %       ±6.62%  ±8.73% ±11.20%
crypto/oneshot-sign.js n=1000 keyFormat='raw-seed' mode='sync' keyType='ml-dsa-44'                                   0.30 %       ±7.69% ±10.13% ±13.00%
crypto/webcrypto-sign.js n=1000 keyReuse='shared' mode='parallel' keyType='ec'                                      -0.80 %       ±9.73% ±12.83% ±16.46%
crypto/webcrypto-sign.js n=1000 keyReuse='shared' mode='parallel' keyType='ed25519'                                 -0.27 %       ±9.31% ±12.28% ±15.75%
crypto/webcrypto-sign.js n=1000 keyReuse='shared' mode='parallel' keyType='ml-dsa-44'                                1.59 %       ±9.31% ±12.27% ±15.74%
crypto/webcrypto-sign.js n=1000 keyReuse='shared' mode='parallel' keyType='rsa-pss'                                 -1.34 %       ±5.76%  ±7.60%  ±9.75%
crypto/webcrypto-sign.js n=1000 keyReuse='shared' mode='parallel' keyType='rsassa-pkcs1-v1_5'                        1.11 %       ±5.58%  ±7.36%  ±9.44%
crypto/webcrypto-sign.js n=1000 keyReuse='shared' mode='serial' keyType='ec'                                         0.21 %       ±9.73% ±12.83% ±16.46%
crypto/webcrypto-sign.js n=1000 keyReuse='shared' mode='serial' keyType='ed25519'                                   -0.55 %       ±9.03% ±11.90% ±15.27%
crypto/webcrypto-sign.js n=1000 keyReuse='shared' mode='serial' keyType='ml-dsa-44'                                  0.09 %       ±9.38% ±12.37% ±15.87%
crypto/webcrypto-sign.js n=1000 keyReuse='shared' mode='serial' keyType='rsa-pss'                                    0.63 %       ±4.81%  ±6.33%  ±8.13%
crypto/webcrypto-sign.js n=1000 keyReuse='shared' mode='serial' keyType='rsassa-pkcs1-v1_5'                         -0.20 %       ±4.62%  ±6.08%  ±7.81%
crypto/webcrypto-sign.js n=1000 keyReuse='unique' mode='parallel' keyType='ec'                                       2.18 %       ±9.48% ±12.49% ±16.03%
crypto/webcrypto-sign.js n=1000 keyReuse='unique' mode='parallel' keyType='ed25519'                                  0.02 %       ±9.10% ±12.00% ±15.39%
crypto/webcrypto-sign.js n=1000 keyReuse='unique' mode='parallel' keyType='ml-dsa-44'                                1.92 %       ±9.39% ±12.38% ±15.89%
crypto/webcrypto-sign.js n=1000 keyReuse='unique' mode='parallel' keyType='rsa-pss'                                  0.32 %       ±5.78%  ±7.62%  ±9.78%
crypto/webcrypto-sign.js n=1000 keyReuse='unique' mode='parallel' keyType='rsassa-pkcs1-v1_5'                       -2.40 %       ±5.83%  ±7.68%  ±9.86%

Be aware that when doing many comparisons the risk of a false-positive
result increases. In this case, there are 46 comparisons, you can thus
expect the following amount of false-positive results:
  2.30 false positives, when considering a   5% risk acceptance (*, **, ***),
  0.46 false positives, when considering a   1% risk acceptance (**, ***),
  0.05 false positives, when considering a 0.1% risk acceptance (***)

[!WARNING]
Do not take GHA benchmark results as face value, always confirm them
using a dedicated machine, e.g. Jenkins CI.

@codecov

codecov Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.37%. Comparing base (8bf7793) to head (286570b).
⚠️ Report is 7 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #66413      +/-   ##
==========================================
- Coverage   90.39%   90.37%   -0.03%     
==========================================
  Files         792      792              
  Lines      275580   275658      +78     
  Branches    52840    52862      +22     
==========================================
+ Hits       249104   249119      +15     
- Misses      16897    16942      +45     
- Partials     9579     9597      +18     
Files with missing lines Coverage Δ
src/crypto/crypto_ec.cc 67.91% <ø> (-1.66%) ⬇️
src/crypto/crypto_kem.cc 74.66% <ø> (-0.50%) ⬇️
src/crypto/crypto_keys.cc 72.40% <100.00%> (-0.23%) ⬇️
src/crypto/crypto_keys.h 67.92% <100.00%> (ø)
src/crypto/crypto_rsa.cc 64.26% <ø> (-0.30%) ⬇️
src/crypto/crypto_sig.cc 68.81% <ø> (+0.12%) ⬆️

... and 36 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@panva
panva force-pushed the crypto-key-mutexes branch from 15b1e98 to 286570b Compare September 30, 2026 16:30

@addaleax addaleax left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be helpful to reference documentation that says these methods are threadsafe, including whether that's a guarantee across BoringSSL/OpenSSL. (If it's about allowing concurrency, an RwLock would allow that, but I get that if it's truly unnecessary then there's no point in adding that)

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++. commit-queue-rebase PRs the Commit Queue should land as multiple self-contained commits. crypto Issues and PRs related to the crypto subsystem. lib / src Issues and PRs involving general changes in the lib/ or src/ directories. needs-ci PRs that need a full CI run. webcrypto Issues and PRs related to the Web Crypto API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants