Skip to content

crypto: support OpenSSL STORE private keys#63949

Open
panva wants to merge 5 commits into
nodejs:mainfrom
panva:keyobject-stores
Open

crypto: support OpenSSL STORE private keys#63949
panva wants to merge 5 commits into
nodejs:mainfrom
panva:keyobject-stores

Conversation

@panva

@panva panva commented Jun 16, 2026

Copy link
Copy Markdown
Member

Note

Looking for reviews from folk knowledgeable of OpenSSL STORE providers.

Allow crypto.createPrivateKey() and private-key consumers such as crypto.sign() to load private keys from WHATWG URL objects via OpenSSL STORE.

This supports both direct URL input:

import { createPrivateKey } from 'node:crypto';

const key = createPrivateKey(new URL('file:///path/to/private-key.pem'));

and object input with optional STORE credentials and OpenSSL property query
metadata:

import { createPrivateKey, sign } from 'node:crypto';

const key = createPrivateKey({
  key: new URL('pkcs11:token=node;object=signing-key;type=private'),
  passphrase: process.env.PKCS11_PIN,
  properties: 'provider=pkcs11',
});

const signature = sign('sha256', Buffer.from('payload'), key);

The properties option is passed to OpenSSL as the property query used when fetching the STORE loader. It is not appended to the URL and is distinct from provider-specific URI parameters such as PKCS#11 token or object attributes.

Permission model

STORE loading is gated by a new crypto.store permission capability. When the Permission Model is enabled, attempts to load private keys from STORE URLs require --allow-crypto-store; otherwise ERR_ACCESS_DENIED is thrown.

$ node --permission --allow-crypto-store app.mjs

The permission is exposed through the runtime permission APIs:

process.permission.has('crypto.store'); // true
process.permission.drop('crypto.store');
process.permission.has('crypto.store'); // false

For file: STORE URLs, the existing file-system permission still applies as well: Node checks fs.read for the resolved file path before calling OpenSSL.

Passphrases and errors

The passphrase option is forwarded to OpenSSL's STORE UI callback and serves as the passphrase or PIN for encrypted or token-protected private keys.

If OpenSSL requests a passphrase and none was provided, Node throws ERR_MISSING_PASSPHRASE, matching the existing encrypted private-key import behavior. Incorrect passphrases continue to surface as OpenSSL errors.

@panva panva added the wip Issues and PRs that are still a work in progress. label Jun 16, 2026
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/actions
  • @nodejs/config
  • @nodejs/crypto
  • @nodejs/gyp
  • @nodejs/security-wg

@nodejs-github-bot nodejs-github-bot added lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. labels Jun 16, 2026
@panva panva requested a review from tniessen June 17, 2026 09:04
@panva panva force-pushed the keyobject-stores branch 2 times, most recently from 43f0d74 to 96c5081 Compare June 18, 2026 08:52
@panva panva removed the wip Issues and PRs that are still a work in progress. label Jun 18, 2026
@panva panva force-pushed the keyobject-stores branch 2 times, most recently from ddd7eaf to 35bb771 Compare June 18, 2026 09:03
jasnell
jasnell previously approved these changes Jun 19, 2026
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
@panva panva force-pushed the keyobject-stores branch from 35bb771 to 9d23b6b Compare June 29, 2026 13:01
@panva panva dismissed jasnell’s stale review June 29, 2026 13:02

I changed the feature shape quite a bit. Dismissing a stale review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants