Skip to content

Commit fe7ebcc

Browse files
authored
crypto: deduplicate and canonicalize CryptoKey usages
Fixes: #62899 Signed-off-by: Filip Skokan <panva.ip@gmail.com> PR-URL: #62902 Fixes: #62899 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Сковорода Никита Андреевич <chalkerx@gmail.com> Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
1 parent 4744070 commit fe7ebcc

12 files changed

Lines changed: 620 additions & 25 deletions

File tree

lib/internal/crypto/aes.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
const {
4-
ArrayFrom,
54
ArrayPrototypePush,
65
SafeSet,
76
} = primordials;
@@ -210,7 +209,7 @@ async function aesGenerateKey(algorithm, extractable, keyUsages) {
210209
return new InternalCryptoKey(
211210
key,
212211
{ name, length },
213-
ArrayFrom(usagesSet),
212+
usagesSet,
214213
extractable);
215214
}
216215

@@ -285,7 +284,7 @@ function aesImportKey(
285284
return new InternalCryptoKey(
286285
keyObject,
287286
{ name, length },
288-
keyUsages,
287+
usagesSet,
289288
extractable);
290289
}
291290

lib/internal/crypto/cfrg.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ async function cfrgGenerateKey(algorithm, extractable, keyUsages) {
134134
case 'X25519':
135135
// Fall through
136136
case 'X448':
137-
publicUsages = [];
137+
publicUsages = new SafeSet();
138138
privateUsages = getUsagesUnion(usageSet, 'deriveKey', 'deriveBits');
139139
break;
140140
}
@@ -245,7 +245,7 @@ function cfrgImportKey(
245245
return new InternalCryptoKey(
246246
keyObject,
247247
{ name },
248-
keyUsages,
248+
usagesSet,
249249
extractable);
250250
}
251251

lib/internal/crypto/chacha20_poly1305.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
const {
4-
ArrayFrom,
54
SafeSet,
65
} = primordials;
76

@@ -81,7 +80,7 @@ async function c20pGenerateKey(algorithm, extractable, keyUsages) {
8180
return new InternalCryptoKey(
8281
createSecretKey(keyData),
8382
{ name },
84-
ArrayFrom(usagesSet),
83+
usagesSet,
8584
extractable);
8685
}
8786

@@ -140,7 +139,7 @@ function c20pImportKey(
140139
return new InternalCryptoKey(
141140
keyObject,
142141
{ name },
143-
keyUsages,
142+
usagesSet,
144143
extractable);
145144
}
146145

lib/internal/crypto/ec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ async function ecGenerateKey(algorithm, extractable, keyUsages) {
119119
privateUsages = getUsagesUnion(usageSet, 'sign');
120120
break;
121121
case 'ECDH':
122-
publicUsages = [];
122+
publicUsages = new SafeSet();
123123
privateUsages = getUsagesUnion(usageSet, 'deriveKey', 'deriveBits');
124124
break;
125125
}
@@ -271,7 +271,7 @@ function ecImportKey(
271271
return new InternalCryptoKey(
272272
keyObject,
273273
{ name, namedCurve },
274-
keyUsages,
274+
usagesSet,
275275
extractable);
276276
}
277277

lib/internal/crypto/keys.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const {
6161
bigIntArrayToUnsignedBigInt,
6262
normalizeAlgorithm,
6363
hasAnyNotIn,
64+
getSortedUsages,
6465
} = require('internal/crypto/util');
6566

6667
const {
@@ -901,7 +902,7 @@ class InternalCryptoKey {
901902
keyObject,
902903
algorithm,
903904
extractable,
904-
keyUsages,
905+
getSortedUsages(new SafeSet(keyUsages)),
905906
);
906907
}
907908
}
@@ -967,7 +968,7 @@ function importGenericSecretKey(
967968
return undefined;
968969
}
969970

970-
return new InternalCryptoKey(keyObject, { name }, keyUsages, false);
971+
return new InternalCryptoKey(keyObject, { name }, usagesSet, false);
971972
}
972973

973974
module.exports = {

lib/internal/crypto/mac.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
const {
4-
ArrayFrom,
54
SafeSet,
65
StringPrototypeSubstring,
76
} = primordials;
@@ -81,7 +80,7 @@ async function hmacGenerateKey(algorithm, extractable, keyUsages) {
8180
return new InternalCryptoKey(
8281
key,
8382
{ name, length, hash },
84-
ArrayFrom(usageSet),
83+
usageSet,
8584
extractable);
8685
}
8786

@@ -115,7 +114,7 @@ async function kmacGenerateKey(algorithm, extractable, keyUsages) {
115114
return new InternalCryptoKey(
116115
createSecretKey(keyData),
117116
{ name, length },
118-
ArrayFrom(usageSet),
117+
usageSet,
119118
extractable);
120119
}
121120

@@ -196,7 +195,7 @@ function macImportKey(
196195
return new InternalCryptoKey(
197196
keyObject,
198197
algorithmObject,
199-
keyUsages,
198+
usagesSet,
200199
extractable);
201200
}
202201

lib/internal/crypto/ml_dsa.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ function mlDsaImportKey(
203203
return new InternalCryptoKey(
204204
keyObject,
205205
{ name },
206-
keyUsages,
206+
usagesSet,
207207
extractable);
208208
}
209209

lib/internal/crypto/ml_kem.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ async function mlKemGenerateKey(algorithm, extractable, keyUsages) {
6969
{ name: 'OperationError', cause: err });
7070
}
7171

72-
const publicUsages = getUsagesUnion(usageSet, 'encapsulateBits', 'encapsulateKey');
73-
const privateUsages = getUsagesUnion(usageSet, 'decapsulateBits', 'decapsulateKey');
72+
const publicUsages = getUsagesUnion(usageSet, 'encapsulateKey', 'encapsulateBits');
73+
const privateUsages = getUsagesUnion(usageSet, 'decapsulateKey', 'decapsulateBits');
7474

7575
const keyAlgorithm = { name };
7676

@@ -202,7 +202,7 @@ function mlKemImportKey(
202202
return new InternalCryptoKey(
203203
keyObject,
204204
{ name },
205-
keyUsages,
205+
usagesSet,
206206
extractable);
207207
}
208208

lib/internal/crypto/rsa.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ function rsaImportKey(
281281
modulusLength,
282282
publicExponent: new Uint8Array(publicExponent),
283283
hash: algorithm.hash,
284-
}, keyUsages, extractable);
284+
}, usagesSet, extractable);
285285
}
286286

287287
async function rsaSignVerify(key, data, { saltLength }, signature) {

lib/internal/crypto/util.js

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const {
44
ArrayBufferIsView,
55
ArrayBufferPrototypeGetByteLength,
6+
ArrayFrom,
67
ArrayPrototypeIncludes,
78
ArrayPrototypePush,
89
BigInt,
@@ -16,6 +17,7 @@ const {
1617
ObjectKeys,
1718
ObjectPrototypeHasOwnProperty,
1819
PromiseWithResolvers,
20+
SafeSet,
1921
StringPrototypeToUpperCase,
2022
Symbol,
2123
TypedArrayPrototypeGetBuffer,
@@ -718,14 +720,40 @@ function getStringOption(options, key) {
718720
}
719721

720722
function getUsagesUnion(usageSet, ...usages) {
721-
const newset = [];
723+
const newset = new SafeSet();
722724
for (let n = 0; n < usages.length; n++) {
723725
if (usageSet.has(usages[n]))
724-
ArrayPrototypePush(newset, usages[n]);
726+
newset.add(usages[n]);
725727
}
726728
return newset;
727729
}
728730

731+
const kCanonicalUsageOrder = new SafeSet([
732+
'encrypt', 'decrypt',
733+
'sign', 'verify',
734+
'deriveKey', 'deriveBits',
735+
'wrapKey', 'unwrapKey',
736+
'encapsulateKey', 'encapsulateBits',
737+
'decapsulateKey', 'decapsulateBits',
738+
]);
739+
740+
/**
741+
* Returns the usages from `usageSet` as an array in the canonical order
742+
* defined by {@link kCanonicalUsageOrder}.
743+
* @param {SafeSet<string>} usageSet
744+
* @returns {string[]}
745+
*/
746+
function getSortedUsages(usageSet) {
747+
if (usageSet.size <= 1) {
748+
return ArrayFrom(usageSet);
749+
}
750+
const result = [];
751+
for (const usage of kCanonicalUsageOrder) {
752+
if (usageSet.has(usage)) ArrayPrototypePush(result, usage);
753+
}
754+
return result;
755+
}
756+
729757
function getBlockSize(name) {
730758
switch (name) {
731759
case 'SHA-1':
@@ -842,6 +870,7 @@ module.exports = {
842870
getDigestSizeInBytes,
843871
getStringOption,
844872
getUsagesUnion,
873+
getSortedUsages,
845874
secureHeapUsed,
846875
getCachedHashId,
847876
getHashCache,

0 commit comments

Comments
 (0)