diff --git a/lib/internal/crypto/diffiehellman.js b/lib/internal/crypto/diffiehellman.js index 63a9451b3cc..46659419c8d 100644 --- a/lib/internal/crypto/diffiehellman.js +++ b/lib/internal/crypto/diffiehellman.js @@ -2,7 +2,6 @@ const { ArrayBufferPrototypeGetByteLength, - ArrayBufferPrototypeSlice, FunctionPrototypeCall, ObjectDefineProperty, TypedArrayPrototypeGetBuffer, @@ -381,11 +380,8 @@ function ecdhDeriveBits(algorithm, baseKey, length) { if (byteLength < sliceLength) throw lazyDOMException('derived bit length is too small', 'OperationError'); - if (length % 8 === 0) { - if (byteLength === sliceLength) - return bits; - return ArrayBufferPrototypeSlice(bits, 0, sliceLength); - } + if (length % 8 === 0 && byteLength === sliceLength) + return bits; return TypedArrayPrototypeGetBuffer(truncateToBitLength(length, bits)); }); diff --git a/test/parallel/test-webcrypto-derived-bits-species.js b/test/parallel/test-webcrypto-derived-bits-species.js new file mode 100644 index 00000000000..491dc0df877 --- /dev/null +++ b/test/parallel/test-webcrypto-derived-bits-species.js @@ -0,0 +1,26 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { subtle } = globalThis.crypto; + +(async () => { + const keys = await subtle.generateKey({ name: 'ECDH', namedCurve: 'P-256' }, false, ['deriveBits']); + const algorithm = { name: 'ECDH', public: keys.publicKey }; + const expected = await subtle.deriveBits(algorithm, keys.privateKey, 128); + const species = Object.getOwnPropertyDescriptor(ArrayBuffer, Symbol.species); + Object.defineProperty(ArrayBuffer, Symbol.species, { + configurable: true, + get: common.mustNotCall(), + }); + try { + const actual = await subtle.deriveBits(algorithm, keys.privateKey, 128); + assert.deepStrictEqual(actual, expected); + assert.strictEqual(Object.getPrototypeOf(actual), ArrayBuffer.prototype); + } finally { + Object.defineProperty(ArrayBuffer, Symbol.species, species); + } +})().then(common.mustCall());