crypto: support loading private keys through STORE loaders - #63949
Conversation
|
Review requested:
|
43f0d74 to
96c5081
Compare
ddd7eaf to
35bb771
Compare
I changed the feature shape quite a bit. Dismissing a stale review.
This comment was marked as resolved.
This comment was marked as resolved.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #63949 +/- ##
==========================================
- Coverage 90.14% 90.14% -0.01%
==========================================
Files 743 746 +3
Lines 242408 242774 +366
Branches 45656 45749 +93
==========================================
+ Hits 218520 218838 +318
- Misses 15387 15395 +8
- Partials 8501 8541 +40
🚀 New features to boost your workflow:
|
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as resolved.
This comment was marked as resolved.
40b7a66 to
0ec7b5c
Compare
|
With db7cc5b and cecfdce...0938489 in place I have to cleanup workarounds on the wrong layer which are now absorbed by ncrypto |
Accept WHATWG URL objects in private-key inputs and load referenced keys through OpenSSL STORE loaders. Pass optional property queries and passphrases while preserving provider-owned EVP_PKEY objects for ordinary KeyObject and CryptoKey operations. Signed-off-by: Filip Skokan <panva.ip@gmail.com>
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
| # shared OpenSSL >= 3, and a platform nixpkgs ships pkcs11-provider for. The | ||
| # token is copied into the shell's temporary directory, so the test has to run | ||
| # from the shell that set it up. | ||
| withPkcs11 ? false, |
There was a problem hiding this comment.
It might get confusing when the user provides --arg pkcs11 '<some value>' --arg withPkcs11 false. We could rename it to withDefaultPkcs11, or merge the two arguments
| withOpenSSL = | ||
| pkg: | ||
| (pkg.override { inherit openssl; }).overrideAttrs (_: { | ||
| doCheck = false; |
There was a problem hiding this comment.
I’m not sure we want to do that, it forces to rebuild the derivation even if it’s cached by the Nix project – for softhms there’s no upside given that upstream doesn’t define a doCheck. Maybe we should override only if openssl != pkgs.openssl?
| '' | ||
| mkdir -p "$out/tokens" | ||
|
|
||
| export SOFTHSM2_CONF="$NIX_BUILD_TOP/softhsm2.conf" |
There was a problem hiding this comment.
Why do we use a variable here that we only use once?
| # cannot, so the token is unusable straight out of the read-only Nix store. | ||
| # Give the test a writable copy instead, in the shell's own temporary | ||
| # directory so that it is discarded along with the shell. | ||
| shellHook = '' |
There was a problem hiding this comment.
Do we need a hook and temp files, or could we have a derivation that outputs a fixed conf file?
Allow
crypto.createPrivateKey()and APIs that consume private keys, such ascrypto.sign(),crypto.privateDecrypt(),crypto.diffieHellman(), andcrypto.decapsulate(), to load private keys through configured OpenSSL STORE loaders using WHATWGURLobjects.This supports direct URL input:
It also supports object input with an optional passphrase or PIN and OpenSSL property query:
The provider implementing the STORE loader must already be loaded in Node.js' default OpenSSL library context, for example through OpenSSL configuration. This API does not load providers.
passphraseis forwarded to the loader as its passphrase or PIN.propertiesis an OpenSSL property query used to select the STORE loader; it is not appended to the URL and is distinct from provider-specific URI parameters.Why URL?
A
URLdistinguishes an external key reference from existing key material. Strings, buffers, typed arrays, and formatted objects retain their existing PEM, DER, JWK, and raw-key semantics. This avoids adding STORE loading to the key import/exportformatnamespace.URL input is accepted only in private-key contexts. A public key can be derived by first loading the private key and passing the resulting
KeyObjecttocrypto.createPublicKey().The resulting provider-backed key is an ordinary
KeyObjectand interoperates with existing private-key operations, key metadata, public-key derivation, andtoCryptoKey()where supported by the key algorithm and provider. Provider policy continues to control permitted operations and private-key exportability.The native STORE-loading path is available with OpenSSL >= 3.
Permission model
STORE loading adds the global
openssl.storepermission, enabled with--allow-openssl-storeand exposed through the runtime permission APIs:This permission grants broad authority to configured STORE loaders. Loaders may access files, devices, tokens, or the network, and that access is not constrained by the
fs.read,fs.write, ornetpermission scopes.This broad capability matches OpenSSL's behavior: STORE loaders perform their own I/O, and OpenSSL may try its file loader before another loader for opaque URIs.
When STORE access is denied, Node.js redacts the URI from the permission error resource and permission diagnostics.
Passphrases and errors
Credentials should be supplied through
passphraserather than embedded in the URI.If OpenSSL requests a passphrase and none was provided, Node.js throws
ERR_MISSING_PASSPHRASE, matching existing encrypted private-key import behavior. Incorrect passphrases and provider failures continue to surface as OpenSSL errors.Node.js redacts URIs from its own permission-denial errors. Errors reported by OpenSSL or a provider after loading begins may still include the URI.