From 5c46782137733ea2e9712b8df170aa342a5c856c Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Sat, 29 Jun 2024 00:21:29 +0200 Subject: [PATCH] crypto: make deriveBits length parameter optional and nullable PR-URL: https://github.com/nodejs/node/pull/53601 Reviewed-By: Luigi Pinca Reviewed-By: Benjamin Gruenbaum --- doc/api/webcrypto.md | 20 +++++++++++-------- lib/internal/crypto/webcrypto.js | 4 ++-- .../test-webcrypto-derivebits-cfrg.js | 10 ++++++++++ .../test-webcrypto-derivebits-ecdh.js | 10 ++++++++++ .../test-webcrypto-derivebits-hkdf.js | 5 +++++ .../test-webcrypto-derivebits-pbkdf2.js | 5 +++++ 6 files changed, 44 insertions(+), 10 deletions(-) diff --git a/doc/api/webcrypto.md b/doc/api/webcrypto.md index 68f81570d70c11..bbe58031e481dc 100644 --- a/doc/api/webcrypto.md +++ b/doc/api/webcrypto.md @@ -552,11 +552,15 @@ The algorithms currently supported include: * `'AES-CBC'` * `'AES-GCM`' -### `subtle.deriveBits(algorithm, baseKey, length)` +### `subtle.deriveBits(algorithm, baseKey[, length])` @@ -575,12 +579,12 @@ Using the method and parameters specified in `algorithm` and the keying material provided by `baseKey`, `subtle.deriveBits()` attempts to generate `length` bits. -The Node.js implementation requires that when `length` is a -number it must be multiple of `8`. +The Node.js implementation requires that `length`, when a number, is a multiple +of `8`. -When `length` is `null` the maximum number of bits for a given algorithm is -generated. This is allowed for the `'ECDH'`, `'X25519'`, and `'X448'` -algorithms. +When `length` is not provided or `null` the maximum number of bits for a given +algorithm is generated. This is allowed for the `'ECDH'`, `'X25519'`, and `'X448'` +algorithms, for other algorithms `length` is required to be a number. If successful, the returned promise will be resolved with an {ArrayBuffer} containing the generated data. diff --git a/lib/internal/crypto/webcrypto.js b/lib/internal/crypto/webcrypto.js index d52f64bd4fa57c..ba9b077c7829a1 100644 --- a/lib/internal/crypto/webcrypto.js +++ b/lib/internal/crypto/webcrypto.js @@ -173,12 +173,12 @@ async function generateKey( return result; } -async function deriveBits(algorithm, baseKey, length) { +async function deriveBits(algorithm, baseKey, length = null) { if (this !== subtle) throw new ERR_INVALID_THIS('SubtleCrypto'); webidl ??= require('internal/crypto/webidl'); const prefix = "Failed to execute 'deriveBits' on 'SubtleCrypto'"; - webidl.requiredArguments(arguments.length, 3, { prefix }); + webidl.requiredArguments(arguments.length, 2, { prefix }); algorithm = webidl.converters.AlgorithmIdentifier(algorithm, { prefix, context: '1st argument', diff --git a/test/parallel/test-webcrypto-derivebits-cfrg.js b/test/parallel/test-webcrypto-derivebits-cfrg.js index a9b0d1c248f275..9996bf7b9466c3 100644 --- a/test/parallel/test-webcrypto-derivebits-cfrg.js +++ b/test/parallel/test-webcrypto-derivebits-cfrg.js @@ -102,6 +102,16 @@ async function prepareKeys() { assert.strictEqual(Buffer.from(bits).toString('hex'), result); } + { + // Default length + const bits = await subtle.deriveBits({ + name, + public: publicKey + }, privateKey); + + assert.strictEqual(Buffer.from(bits).toString('hex'), result); + } + { // Short Result const bits = await subtle.deriveBits({ diff --git a/test/parallel/test-webcrypto-derivebits-ecdh.js b/test/parallel/test-webcrypto-derivebits-ecdh.js index d14d2e96e2d444..eb732636f3e271 100644 --- a/test/parallel/test-webcrypto-derivebits-ecdh.js +++ b/test/parallel/test-webcrypto-derivebits-ecdh.js @@ -123,6 +123,16 @@ async function prepareKeys() { assert.strictEqual(Buffer.from(bits).toString('hex'), result); } + { + // Default length + const bits = await subtle.deriveBits({ + name: 'ECDH', + public: publicKey + }, privateKey); + + assert.strictEqual(Buffer.from(bits).toString('hex'), result); + } + { // Short Result const bits = await subtle.deriveBits({ diff --git a/test/parallel/test-webcrypto-derivebits-hkdf.js b/test/parallel/test-webcrypto-derivebits-hkdf.js index 90cb14fddfe3cd..799d7d49ee4b3c 100644 --- a/test/parallel/test-webcrypto-derivebits-hkdf.js +++ b/test/parallel/test-webcrypto-derivebits-hkdf.js @@ -271,6 +271,11 @@ async function testDeriveBitsBadLengths( message: 'length cannot be null', name: 'OperationError', }), + assert.rejects( + subtle.deriveBits(algorithm, baseKeys[size]), { + message: 'length cannot be null', + name: 'OperationError', + }), assert.rejects( subtle.deriveBits(algorithm, baseKeys[size], 15), { message: /length must be a multiple of 8/, diff --git a/test/pummel/test-webcrypto-derivebits-pbkdf2.js b/test/pummel/test-webcrypto-derivebits-pbkdf2.js index 74f2e88c58024c..e6c357ab3a47a1 100644 --- a/test/pummel/test-webcrypto-derivebits-pbkdf2.js +++ b/test/pummel/test-webcrypto-derivebits-pbkdf2.js @@ -459,6 +459,11 @@ async function testDeriveBitsBadLengths( message: 'length cannot be null', name: 'OperationError', }), + assert.rejects( + subtle.deriveBits(algorithm, baseKeys[size]), { + message: 'length cannot be null', + name: 'OperationError', + }), assert.rejects( subtle.deriveBits(algorithm, baseKeys[size], 15), { message: /length must be a multiple of 8/,