Accept null IV and wrapped KeyObject in node:crypto by npaun · Pull Request #7837 · cloudflare/workerd · GitHub
Skip to content

Accept null IV and wrapped KeyObject in node:crypto - #7837

Open
npaun wants to merge 1 commit into
mainfrom
npaun/node-crypto-null-iv-keyobject
Open

npaun wants to merge 1 commit into
mainfrom
npaun/node-crypto-null-iv-keyobject

Conversation

@npaun

@npaun npaun commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Fixes #7772.

  • createCipheriv(alg, key, null): a null IV is now treated as an empty IV, matching Node.js, which documents null for ciphers without an IV (e.g. AES-ECB). Ciphers that need an IV still throw Invalid initialization vector, and undefined still throws ERR_INVALID_ARG_TYPE, as in Node.js.
  • publicEncrypt({ key: keyObject, padding }, data) (and publicDecrypt / privateEncrypt / privateDecrypt): a KeyObject or CryptoKey passed as the key property of an options object is now accepted. The four functions each had a copy of the key-resolution logic, and now share prepareAsymmetricKey().

Compatibility: both inputs previously threw ERR_INVALID_ARG_TYPE, so accepting them can't break a working Worker. No compat flag is needed.

Out of scope: Node.js also accepts a private key for publicEncrypt / publicDecrypt, deriving the public key from it. workerd still rejects that with ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE.

Test plan

New tests in crypto_cipher-test.js:

  • cipherivNullIv: AES-128-ECB with a null IV gives the same ciphertext as Node.js and round-trips. CBC with null and ECB with undefined still throw.
  • keyObjectInOptions: { key: KeyObject, padding: RSA_NO_PADDING } works with all four functions. The output matches Node.js and the PEM-string path, and a wrong-type key still throws.

createCipheriv() and createDecipheriv() rejected a null IV, even
though Node.js documents null as the IV for ciphers that don't use
one, such as AES-ECB. A null IV is now treated as an empty IV, so it
behaves exactly like Buffer.alloc(0). Ciphers that require an IV
still reject it, and undefined is still rejected, as in Node.js.

publicEncrypt(), publicDecrypt(), privateEncrypt() and
privateDecrypt() rejected a KeyObject or CryptoKey passed as the
`key` property of an options object, e.g.
publicEncrypt({ key: createPublicKey(pem), padding }, data). Node.js
accepts this so callers can specify `padding` and similar options
alongside a KeyObject. The four functions each had a copy of the key
resolution logic; they now share prepareAsymmetricKey(), which also
unwraps such an options object.

Compatibility: both inputs previously threw ERR_INVALID_ARG_TYPE, so
accepting them cannot change the behavior of a working Worker, and
no compatibility flag is needed.

Tests were not run locally because of an outage affecting the
cfdata.org domains that edgeworker's bazel build depends on; CI is
the verification for this change.

Fixes #7772

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@npaun
npaun marked this pull request as ready for review October 20, 2026 04:54
@npaun
npaun requested review from a team as code owners October 20, 2026 04:54
@clanky-the-clanker

Copy link
Copy Markdown

@ask-bonk

ask-bonk Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Review: 2 findings (1 blocking, 1 warning).

Adds Node-compatible null-IV and wrapped asymmetric-key handling with targeted tests.


Reviewed commit: db3a6efb · github run

Comment thread src/node/internal/crypto_cipher.ts
};

export const keyObjectInOptions = {
test(_, env) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[WARNING] This covers wrapped KeyObject values only, although prepareAsymmetricKey() has a separate inner instanceof CryptoKey branch. A regression that stops unwrapping a WebCrypto CryptoKey would still pass this test.

Suggested change

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug Report (by AI) — Runtime APIs: node:crypto rejects null IV for AES-ECB and KeyObject for publicEncrypt

2 participants