Skip to content

Commit

Permalink
crypto: make deriveBits length parameter optional and nullable
Browse files Browse the repository at this point in the history
PR-URL: #53601
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
  • Loading branch information
panva authored Jun 28, 2024
1 parent 0062d5a commit d65b170
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 9 deletions.
18 changes: 11 additions & 7 deletions doc/api/webcrypto.md
Original file line number Diff line number Diff line change
Expand Up @@ -569,11 +569,15 @@ The algorithms currently supported include:
* `'AES-CBC'`
* `'AES-GCM`'

### `subtle.deriveBits(algorithm, baseKey, length)`
### `subtle.deriveBits(algorithm, baseKey[, length])`

<!-- YAML
added: v15.0.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/53601
description: The length parameter is now optional for `'ECDH'`, `'X25519'`,
and `'X448'`.
- version:
- v18.4.0
- v16.17.0
Expand All @@ -585,7 +589,7 @@ changes:

* `algorithm`: {AlgorithmIdentifier|EcdhKeyDeriveParams|HkdfParams|Pbkdf2Params}
* `baseKey`: {CryptoKey}
* `length`: {number|null}
* `length`: {number|null} **Default:** `null`
* Returns: {Promise} Fulfills with an {ArrayBuffer}

<!--lint enable maximum-line-length remark-lint-->
Expand All @@ -594,12 +598,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.
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/crypto/webcrypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
10 changes: 10 additions & 0 deletions test/parallel/test-webcrypto-derivebits-cfrg.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,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({
Expand Down
10 changes: 10 additions & 0 deletions test/parallel/test-webcrypto-derivebits-ecdh.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,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({
Expand Down
5 changes: 5 additions & 0 deletions test/parallel/test-webcrypto-derivebits-hkdf.js
Original file line number Diff line number Diff line change
Expand Up @@ -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/,
Expand Down
5 changes: 5 additions & 0 deletions test/pummel/test-webcrypto-derivebits-pbkdf2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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/,
Expand Down
8 changes: 8 additions & 0 deletions test/wpt/status/WebCryptoAPI.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,13 @@
},
"historical.any.js": {
"skip": "Not relevant in Node.js context"
},
"idlharness.https.any.js": {
"fail": {
"note": "WPT not updated for https://github.com/w3c/webcrypto/pull/345 yet",
"expected": [
"SubtleCrypto interface: operation deriveBits(AlgorithmIdentifier, CryptoKey, unsigned long)"
]
}
}
}

0 comments on commit d65b170

Please sign in to comment.