diff --git a/lib/internal/crypto/kem_hybrids.js b/lib/internal/crypto/kem_hybrids.js index 58fcb6e8fd1..d95a651b61b 100644 --- a/lib/internal/crypto/kem_hybrids.js +++ b/lib/internal/crypto/kem_hybrids.js @@ -1,7 +1,6 @@ 'use strict'; const { - ArrayPrototypeSlice, BigInt, PromiseWithResolvers, SafeSet, @@ -24,7 +23,7 @@ const { getCryptoKeySeedData, getCryptoKeySecondaryHandle, getCryptoKeyType, - getCryptoKeyUsages, + getCryptoKeyUsagesMask, InternalCryptoKey, } = require('internal/crypto/keys'); @@ -51,6 +50,7 @@ const { const { getBufferSourceBytes, getUsagesMask, + getUsagesFromMask, jobPromise, jobPromiseThen, resolveWebCryptoResult, @@ -860,7 +860,7 @@ function exportJwkKey(key, rawEncapsulationKey, config) { kty: 'AKP', alg: config.name, pub: base64urlEncode(rawEncapsulationKey), - key_ops: ArrayPrototypeSlice(getCryptoKeyUsages(key), 0), + key_ops: getUsagesFromMask(getCryptoKeyUsagesMask(key)), ext: getCryptoKeyExtractable(key), }; if (getCryptoKeyType(key) === 'private') diff --git a/lib/internal/crypto/keys.js b/lib/internal/crypto/keys.js index f54ba68f670..cdbf163ec08 100644 --- a/lib/internal/crypto/keys.js +++ b/lib/internal/crypto/keys.js @@ -2,7 +2,6 @@ const { ArrayPrototypeMap, - ArrayPrototypeSlice, ObjectDefineProperties, ObjectPrototypeHasOwnProperty, ObjectSetPrototypeOf, @@ -1224,7 +1223,7 @@ const { type: getCryptoKeyType(this), extractable: getCryptoKeyExtractable(this), algorithm: cloneAlgorithm(getCryptoKeyAlgorithm(this)), - usages: ArrayPrototypeSlice(getCryptoKeyUsages(this), 0), + usages: getUsagesFromMask(getCryptoKeyUsagesMask(this)), }, opts)}`; } @@ -1258,7 +1257,7 @@ const { const slots = getSlots(this); let cached = slots[kSlotClonedUsages]; if (cached === undefined) { - cached = ArrayPrototypeSlice(getCryptoKeyUsagesFromSlots(slots), 0); + cached = getUsagesFromMask(slots[kSlotUsagesMask]); slots[kSlotClonedUsages] = cached; } return cached; diff --git a/lib/internal/crypto/webcrypto.js b/lib/internal/crypto/webcrypto.js index 7777774a217..2f44d726026 100644 --- a/lib/internal/crypto/webcrypto.js +++ b/lib/internal/crypto/webcrypto.js @@ -3,7 +3,6 @@ const { ArrayBufferIsView, ArrayIsArray, - ArrayPrototypeSlice, FunctionPrototypeCall, JSONParse, JSONStringify, @@ -52,7 +51,6 @@ const { getCryptoKeyExtractable, getCryptoKeyHandle, getCryptoKeyType, - getCryptoKeyUsages, getCryptoKeyUsagesMask, hasCryptoKeyUsage, importGenericSecretKey, @@ -66,6 +64,7 @@ const { const { cleanupWebCryptoResult, getBlockSize, + getUsagesFromMask, jobPromiseThen, normalizeAlgorithm, normalizeHashName, @@ -801,7 +800,7 @@ function exportKeyJWK(key) { // `parameters` before native export populates key material. Delete it for // algorithms without a JWK alg value to keep the expected shape. const parameters = { - key_ops: ArrayPrototypeSlice(getCryptoKeyUsages(key), 0), + key_ops: getUsagesFromMask(getCryptoKeyUsagesMask(key)), ext: getCryptoKeyExtractable(key), alg, }; diff --git a/test/parallel/test-webcrypto-usages-species.js b/test/parallel/test-webcrypto-usages-species.js new file mode 100644 index 00000000000..2e1aed7ec42 --- /dev/null +++ b/test/parallel/test-webcrypto-usages-species.js @@ -0,0 +1,30 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { subtle } = globalThis.crypto; + +(async () => { + const key = await subtle.importKey('raw', new Uint8Array(16), 'AES-GCM', true, + ['encrypt', 'decrypt']); + const descriptor = Object.getOwnPropertyDescriptor(Array.prototype, 'constructor'); + let usages; + let jwk; + try { + Object.defineProperty(Array.prototype, 'constructor', { get: common.mustNotCall() }); + usages = key.usages; + jwk = await subtle.exportKey('jwk', key); + } finally { + Object.defineProperty(Array.prototype, 'constructor', descriptor); + } + assert.strictEqual(Object.getPrototypeOf(usages), Array.prototype); + assert.strictEqual(key.usages, usages); + assert.deepStrictEqual(usages, ['encrypt', 'decrypt']); + assert.deepStrictEqual(jwk.key_ops, usages); + usages.push('sign'); + assert.deepStrictEqual((await subtle.exportKey('jwk', key)).key_ops, + ['encrypt', 'decrypt']); +})().then(common.mustCall());