Skip to content

Commit b10ac9a

Browse files
panvaaduh95
authored andcommittedMar 9, 2025
src: refactor SubtleCrypto algorithm and length validations
PR-URL: #57273 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jason Zhang <xzha4350@gmail.com> Reviewed-By: Mattias Buelens <mattias@buelens.com>
1 parent 90cd780 commit b10ac9a

17 files changed

+208
-180
lines changed
 

‎lib/internal/crypto/aes.js

+39-27
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ const {
5858
generateKey: _generateKey,
5959
} = require('internal/crypto/keygen');
6060

61-
const kMaxCounterLength = 128;
6261
const kTagLengths = [32, 64, 96, 104, 112, 120, 128];
6362
const generateKey = promisify(_generateKey);
6463

@@ -109,35 +108,43 @@ function getVariant(name, length) {
109108
}
110109
}
111110

112-
function asyncAesCtrCipher(mode, key, data, { counter, length }) {
113-
validateByteLength(counter, 'algorithm.counter', 16);
111+
function validateAesCtrAlgorithm(algorithm) {
112+
validateByteLength(algorithm.counter, 'algorithm.counter', 16);
114113
// The length must specify an integer between 1 and 128. While
115114
// there is no default, this should typically be 64.
116-
if (length === 0 || length > kMaxCounterLength) {
115+
if (algorithm.length === 0 || algorithm.length > 128) {
117116
throw lazyDOMException(
118117
'AES-CTR algorithm.length must be between 1 and 128',
119118
'OperationError');
120119
}
120+
}
121+
122+
function asyncAesCtrCipher(mode, key, data, algorithm) {
123+
validateAesCtrAlgorithm(algorithm);
121124

122125
return jobPromise(() => new AESCipherJob(
123126
kCryptoJobAsync,
124127
mode,
125128
key[kKeyObject][kHandle],
126129
data,
127130
getVariant('AES-CTR', key.algorithm.length),
128-
counter,
129-
length));
131+
algorithm.counter,
132+
algorithm.length));
133+
}
134+
135+
function validateAesCbcAlgorithm(algorithm) {
136+
validateByteLength(algorithm.iv, 'algorithm.iv', 16);
130137
}
131138

132-
function asyncAesCbcCipher(mode, key, data, { iv }) {
133-
validateByteLength(iv, 'algorithm.iv', 16);
139+
function asyncAesCbcCipher(mode, key, data, algorithm) {
140+
validateAesCbcAlgorithm(algorithm);
134141
return jobPromise(() => new AESCipherJob(
135142
kCryptoJobAsync,
136143
mode,
137144
key[kKeyObject][kHandle],
138145
data,
139146
getVariant('AES-CBC', key.algorithm.length),
140-
iv));
147+
algorithm.iv));
141148
}
142149

143150
function asyncAesKwCipher(mode, key, data) {
@@ -149,24 +156,25 @@ function asyncAesKwCipher(mode, key, data) {
149156
getVariant('AES-KW', key.algorithm.length)));
150157
}
151158

152-
function asyncAesGcmCipher(
153-
mode,
154-
key,
155-
data,
156-
{ iv, additionalData, tagLength = 128 }) {
157-
if (!ArrayPrototypeIncludes(kTagLengths, tagLength)) {
158-
return PromiseReject(lazyDOMException(
159-
`${tagLength} is not a valid AES-GCM tag length`,
160-
'OperationError'));
159+
function validateAesGcmAlgorithm(algorithm) {
160+
if (!ArrayPrototypeIncludes(kTagLengths, algorithm.tagLength)) {
161+
throw lazyDOMException(
162+
`${algorithm.tagLength} is not a valid AES-GCM tag length`,
163+
'OperationError');
161164
}
162165

163-
validateMaxBufferLength(iv, 'algorithm.iv');
166+
validateMaxBufferLength(algorithm.iv, 'algorithm.iv');
164167

165-
if (additionalData !== undefined) {
166-
validateMaxBufferLength(additionalData, 'algorithm.additionalData');
168+
if (algorithm.additionalData !== undefined) {
169+
validateMaxBufferLength(algorithm.additionalData, 'algorithm.additionalData');
167170
}
171+
}
168172

169-
const tagByteLength = MathFloor(tagLength / 8);
173+
function asyncAesGcmCipher(mode, key, data, algorithm) {
174+
algorithm.tagLength ??= 128;
175+
validateAesGcmAlgorithm(algorithm);
176+
177+
const tagByteLength = MathFloor(algorithm.tagLength / 8);
170178
let tag;
171179
switch (mode) {
172180
case kWebCryptoCipherDecrypt: {
@@ -198,9 +206,9 @@ function asyncAesGcmCipher(
198206
key[kKeyObject][kHandle],
199207
data,
200208
getVariant('AES-GCM', key.algorithm.length),
201-
iv,
209+
algorithm.iv,
202210
tag,
203-
additionalData));
211+
algorithm.additionalData));
204212
}
205213

206214
function aesCipher(mode, key, data, algorithm) {
@@ -212,13 +220,17 @@ function aesCipher(mode, key, data, algorithm) {
212220
}
213221
}
214222

215-
async function aesGenerateKey(algorithm, extractable, keyUsages) {
216-
const { name, length } = algorithm;
217-
if (!ArrayPrototypeIncludes(kAesKeyLengths, length)) {
223+
function validateAesGenerateKeyAlgorithm(algorithm) {
224+
if (!ArrayPrototypeIncludes(kAesKeyLengths, algorithm.length)) {
218225
throw lazyDOMException(
219226
'AES key length must be 128, 192, or 256 bits',
220227
'OperationError');
221228
}
229+
}
230+
231+
async function aesGenerateKey(algorithm, extractable, keyUsages) {
232+
validateAesGenerateKeyAlgorithm(algorithm);
233+
const { name, length } = algorithm;
222234

223235
const checkUsages = ['wrapKey', 'unwrapKey'];
224236
if (name !== 'AES-KW')

‎lib/internal/crypto/cfrg.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -329,18 +329,21 @@ function cfrgImportKey(
329329
extractable);
330330
}
331331

332-
function eddsaSignVerify(key, data, { name, context }, signature) {
332+
function validateEdDSASignVerifyAlgorithm(algorithm) {
333+
if (algorithm.name === 'Ed448' && algorithm.context?.byteLength) {
334+
throw lazyDOMException(
335+
'Non zero-length context is not yet supported.', 'NotSupportedError');
336+
}
337+
}
338+
339+
function eddsaSignVerify(key, data, algorithm, signature) {
340+
validateEdDSASignVerifyAlgorithm(algorithm);
333341
const mode = signature === undefined ? kSignJobModeSign : kSignJobModeVerify;
334342
const type = mode === kSignJobModeSign ? 'private' : 'public';
335343

336344
if (key.type !== type)
337345
throw lazyDOMException(`Key must be a ${type} key`, 'InvalidAccessError');
338346

339-
if (name === 'Ed448' && context?.byteLength) {
340-
throw lazyDOMException(
341-
'Non zero-length context is not yet supported.', 'NotSupportedError');
342-
}
343-
344347
return jobPromise(() => new SignJob(
345348
kCryptoJobAsync,
346349
mode,

‎lib/internal/crypto/diffiehellman.js

+12-12
Original file line numberDiff line numberDiff line change
@@ -298,28 +298,28 @@ function diffieHellman(options) {
298298

299299
let masks;
300300

301+
function validateEcdhDeriveBitsAlgorithmAndLength(algorithm, length) {
302+
if (algorithm.public.type !== 'public') {
303+
throw lazyDOMException(
304+
'algorithm.public must be a public key', 'InvalidAccessError');
305+
}
306+
307+
if (algorithm.name !== algorithm.public.algorithm.name) {
308+
throw lazyDOMException(`algorithm.public must be an ${algorithm.name} key`, 'InvalidAccessError');
309+
}
310+
}
311+
301312
// The ecdhDeriveBits function is part of the Web Crypto API and serves both
302313
// deriveKeys and deriveBits functions.
303314
async function ecdhDeriveBits(algorithm, baseKey, length) {
315+
validateEcdhDeriveBitsAlgorithmAndLength(algorithm, length);
304316
const { 'public': key } = algorithm;
305317

306-
if (key.type !== 'public') {
307-
throw lazyDOMException(
308-
'algorithm.public must be a public key', 'InvalidAccessError');
309-
}
310318
if (baseKey.type !== 'private') {
311319
throw lazyDOMException(
312320
'baseKey must be a private key', 'InvalidAccessError');
313321
}
314322

315-
if (
316-
key.algorithm.name !== 'ECDH' &&
317-
key.algorithm.name !== 'X25519' &&
318-
key.algorithm.name !== 'X448'
319-
) {
320-
throw lazyDOMException('Keys must be ECDH, X25519, or X448 keys', 'InvalidAccessError');
321-
}
322-
323323
if (key.algorithm.name !== baseKey.algorithm.name) {
324324
throw lazyDOMException(
325325
'The public and private keys must be of the same type',

‎lib/internal/crypto/ec.js

+11-14
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
'use strict';
22

33
const {
4-
ArrayPrototypeIncludes,
5-
ObjectKeys,
4+
ObjectPrototypeHasOwnProperty,
65
SafeSet,
76
} = primordials;
87

@@ -77,14 +76,17 @@ function createECPublicKeyRaw(namedCurve, keyData) {
7776
return new PublicKeyObject(handle);
7877
}
7978

80-
async function ecGenerateKey(algorithm, extractable, keyUsages) {
81-
const { name, namedCurve } = algorithm;
82-
83-
if (!ArrayPrototypeIncludes(ObjectKeys(kNamedCurveAliases), namedCurve)) {
79+
function validateEcKeyAlgorithm(algorithm) {
80+
if (!ObjectPrototypeHasOwnProperty(kNamedCurveAliases, algorithm.namedCurve)) {
8481
throw lazyDOMException(
8582
'Unrecognized namedCurve',
8683
'NotSupportedError');
8784
}
85+
}
86+
87+
async function ecGenerateKey(algorithm, extractable, keyUsages) {
88+
validateEcKeyAlgorithm(algorithm);
89+
const { name, namedCurve } = algorithm;
8890

8991
const usageSet = new SafeSet(keyUsages);
9092
switch (name) {
@@ -154,16 +156,11 @@ function ecImportKey(
154156
keyData,
155157
algorithm,
156158
extractable,
157-
keyUsages) {
158-
159+
keyUsages,
160+
) {
161+
validateEcKeyAlgorithm(algorithm);
159162
const { name, namedCurve } = algorithm;
160163

161-
if (!ArrayPrototypeIncludes(ObjectKeys(kNamedCurveAliases), namedCurve)) {
162-
throw lazyDOMException(
163-
'Unrecognized namedCurve',
164-
'NotSupportedError');
165-
}
166-
167164
let keyObject;
168165
const usagesSet = new SafeSet(keyUsages);
169166
switch (format) {

‎lib/internal/crypto/hkdf.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -138,18 +138,22 @@ function hkdfSync(hash, key, salt, info, length) {
138138
}
139139

140140
const hkdfPromise = promisify(hkdf);
141-
async function hkdfDeriveBits(algorithm, baseKey, length) {
142-
const { hash, salt, info } = algorithm;
143-
144-
if (length === 0)
145-
return new ArrayBuffer(0);
141+
function validateHkdfDeriveBitsAlgorithmAndLength(algorithm, length) {
146142
if (length === null)
147143
throw lazyDOMException('length cannot be null', 'OperationError');
148144
if (length % 8) {
149145
throw lazyDOMException(
150146
'length must be a multiple of 8',
151147
'OperationError');
152148
}
149+
}
150+
151+
async function hkdfDeriveBits(algorithm, baseKey, length) {
152+
validateHkdfDeriveBitsAlgorithmAndLength(algorithm, length);
153+
const { hash, salt, info } = algorithm;
154+
155+
if (length === 0)
156+
return new ArrayBuffer(0);
153157

154158
try {
155159
return await hkdfPromise(

‎lib/internal/crypto/keys.js

+13-36
Original file line numberDiff line numberDiff line change
@@ -895,12 +895,14 @@ function isCryptoKey(obj) {
895895
}
896896

897897
function importGenericSecretKey(
898-
{ name, length },
898+
algorithm,
899899
format,
900900
keyData,
901901
extractable,
902-
keyUsages) {
902+
keyUsages,
903+
) {
903904
const usagesSet = new SafeSet(keyUsages);
905+
const { name } = algorithm;
904906
if (extractable)
905907
throw lazyDOMException(`${name} keys are not extractable`, 'SyntaxError');
906908

@@ -910,47 +912,22 @@ function importGenericSecretKey(
910912
'SyntaxError');
911913
}
912914

915+
let keyObject;
913916
switch (format) {
914917
case 'KeyObject': {
915-
if (hasAnyNotIn(usagesSet, ['deriveKey', 'deriveBits'])) {
916-
throw lazyDOMException(
917-
`Unsupported key usage for a ${name} key`,
918-
'SyntaxError');
919-
}
920-
921-
const checkLength = keyData.symmetricKeySize * 8;
922-
923-
// The Web Crypto spec allows for key lengths that are not multiples of
924-
// 8. We don't. Our check here is stricter than that defined by the spec
925-
// in that we require that algorithm.length match keyData.length * 8 if
926-
// algorithm.length is specified.
927-
if (length !== undefined && length !== checkLength) {
928-
throw lazyDOMException('Invalid key length', 'DataError');
929-
}
930-
return new InternalCryptoKey(keyData, { name }, keyUsages, false);
918+
keyObject = keyData;
919+
break;
931920
}
932921
case 'raw': {
933-
if (hasAnyNotIn(usagesSet, ['deriveKey', 'deriveBits'])) {
934-
throw lazyDOMException(
935-
`Unsupported key usage for a ${name} key`,
936-
'SyntaxError');
937-
}
938-
939-
const checkLength = keyData.byteLength * 8;
940-
941-
// The Web Crypto spec allows for key lengths that are not multiples of
942-
// 8. We don't. Our check here is stricter than that defined by the spec
943-
// in that we require that algorithm.length match keyData.length * 8 if
944-
// algorithm.length is specified.
945-
if (length !== undefined && length !== checkLength) {
946-
throw lazyDOMException('Invalid key length', 'DataError');
947-
}
948-
949-
const keyObject = createSecretKey(keyData);
950-
return new InternalCryptoKey(keyObject, { name }, keyUsages, false);
922+
keyObject = createSecretKey(keyData);
923+
break;
951924
}
952925
}
953926

927+
if (keyObject) {
928+
return new InternalCryptoKey(keyObject, { name }, keyUsages, false);
929+
}
930+
954931
throw lazyDOMException(
955932
`Unable to import ${name} key with format ${format}`,
956933
'NotSupportedError');

‎lib/internal/crypto/mac.js

+41-32
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ const {
1818
hasAnyNotIn,
1919
jobPromise,
2020
normalizeHashName,
21-
validateBitLength,
2221
validateKeyOps,
2322
kHandle,
2423
kKeyObject,
@@ -41,15 +40,30 @@ const {
4140

4241
const generateKey = promisify(_generateKey);
4342

43+
function validateHmacGenerateKeyAlgorithm(algorithm) {
44+
if (algorithm.length !== undefined) {
45+
if (algorithm.length === 0)
46+
throw lazyDOMException(
47+
'Zero-length key is not supported',
48+
'OperationError');
49+
50+
// The Web Crypto spec allows for key lengths that are not multiples of 8. We don't.
51+
if (algorithm.length % 8) {
52+
throw lazyDOMException(
53+
'Unsupported algorithm.length',
54+
'NotSupportedError');
55+
}
56+
}
57+
}
58+
4459
async function hmacGenerateKey(algorithm, extractable, keyUsages) {
60+
validateHmacGenerateKeyAlgorithm(algorithm);
4561
const { hash, name } = algorithm;
4662
let { length } = algorithm;
4763

4864
if (length === undefined)
4965
length = getBlockSize(hash.name);
5066

51-
validateBitLength(length, 'algorithm.length', true);
52-
5367
const usageSet = new SafeSet(keyUsages);
5468
if (hasAnyNotIn(usageSet, ['sign', 'verify'])) {
5569
throw lazyDOMException(
@@ -82,12 +96,27 @@ function getAlgorithmName(hash) {
8296
}
8397
}
8498

99+
function validateHmacImportKeyAlgorithm(algorithm) {
100+
if (algorithm.length !== undefined) {
101+
if (algorithm.length === 0) {
102+
throw lazyDOMException('Zero-length key is not supported', 'DataError');
103+
}
104+
105+
// The Web Crypto spec allows for key lengths that are not multiples of 8. We don't.
106+
if (algorithm.length % 8) {
107+
throw lazyDOMException('Unsupported algorithm.length', 'NotSupportedError');
108+
}
109+
}
110+
}
111+
85112
function hmacImportKey(
86113
format,
87114
keyData,
88115
algorithm,
89116
extractable,
90-
keyUsages) {
117+
keyUsages,
118+
) {
119+
validateHmacImportKeyAlgorithm(algorithm);
91120
const usagesSet = new SafeSet(keyUsages);
92121
if (hasAnyNotIn(usagesSet, ['sign', 'verify'])) {
93122
throw lazyDOMException(
@@ -97,38 +126,10 @@ function hmacImportKey(
97126
let keyObject;
98127
switch (format) {
99128
case 'KeyObject': {
100-
const checkLength = keyData.symmetricKeySize * 8;
101-
102-
if (checkLength === 0 || algorithm.length === 0)
103-
throw lazyDOMException('Zero-length key is not supported', 'DataError');
104-
105-
// The Web Crypto spec allows for key lengths that are not multiples of
106-
// 8. We don't. Our check here is stricter than that defined by the spec
107-
// in that we require that algorithm.length match keyData.length * 8 if
108-
// algorithm.length is specified.
109-
if (algorithm.length !== undefined &&
110-
algorithm.length !== checkLength) {
111-
throw lazyDOMException('Invalid key length', 'DataError');
112-
}
113-
114129
keyObject = keyData;
115130
break;
116131
}
117132
case 'raw': {
118-
const checkLength = keyData.byteLength * 8;
119-
120-
if (checkLength === 0 || algorithm.length === 0)
121-
throw lazyDOMException('Zero-length key is not supported', 'DataError');
122-
123-
// The Web Crypto spec allows for key lengths that are not multiples of
124-
// 8. We don't. Our check here is stricter than that defined by the spec
125-
// in that we require that algorithm.length match keyData.length * 8 if
126-
// algorithm.length is specified.
127-
if (algorithm.length !== undefined &&
128-
algorithm.length !== checkLength) {
129-
throw lazyDOMException('Invalid key length', 'DataError');
130-
}
131-
132133
keyObject = createSecretKey(keyData);
133134
break;
134135
}
@@ -178,6 +179,14 @@ function hmacImportKey(
178179

179180
const { length } = keyObject[kHandle].keyDetail({});
180181

182+
if (length === 0)
183+
throw lazyDOMException('Zero-length key is not supported', 'DataError');
184+
185+
if (algorithm.length !== undefined &&
186+
algorithm.length !== length) {
187+
throw lazyDOMException('Invalid key length', 'DataError');
188+
}
189+
181190
return new InternalCryptoKey(
182191
keyObject, {
183192
name: 'HMAC',

‎lib/internal/crypto/pbkdf2.js

+11-5
Original file line numberDiff line numberDiff line change
@@ -92,22 +92,28 @@ function check(password, salt, iterations, keylen, digest) {
9292
}
9393

9494
const pbkdf2Promise = promisify(pbkdf2);
95-
async function pbkdf2DeriveBits(algorithm, baseKey, length) {
96-
const { iterations, hash, salt } = algorithm;
97-
if (iterations === 0)
95+
function validatePbkdf2DeriveBitsAlgorithmAndLength(algorithm, length) {
96+
if (algorithm.iterations === 0)
9897
throw lazyDOMException(
9998
'iterations cannot be zero',
10099
'OperationError');
101100

102-
if (length === 0)
103-
return new ArrayBuffer(0);
104101
if (length === null)
105102
throw lazyDOMException('length cannot be null', 'OperationError');
103+
106104
if (length % 8) {
107105
throw lazyDOMException(
108106
'length must be a multiple of 8',
109107
'OperationError');
110108
}
109+
}
110+
111+
async function pbkdf2DeriveBits(algorithm, baseKey, length) {
112+
validatePbkdf2DeriveBitsAlgorithmAndLength(algorithm, length);
113+
const { iterations, hash, salt } = algorithm;
114+
115+
if (length === 0)
116+
return new ArrayBuffer(0);
111117

112118
let result;
113119
try {

‎lib/internal/crypto/rsa.js

+25-15
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,21 @@ function verifyAcceptableRsaKeyUse(name, isPublic, usages) {
8585
}
8686
}
8787

88-
function rsaOaepCipher(mode, key, data, { label }) {
88+
function validateRsaOaepAlgorithm(algorithm) {
89+
if (algorithm.label !== undefined) {
90+
validateMaxBufferLength(algorithm.label, 'algorithm.label');
91+
}
92+
}
93+
94+
function rsaOaepCipher(mode, key, data, algorithm) {
95+
validateRsaOaepAlgorithm(algorithm);
96+
8997
const type = mode === kWebCryptoCipherEncrypt ? 'public' : 'private';
9098
if (key.type !== type) {
9199
throw lazyDOMException(
92100
'The requested operation is not valid for the provided key',
93101
'InvalidAccessError');
94102
}
95-
if (label !== undefined) {
96-
validateMaxBufferLength(label, 'algorithm.label');
97-
}
98103

99104
return jobPromise(() => new RSACipherJob(
100105
kCryptoJobAsync,
@@ -103,14 +108,26 @@ function rsaOaepCipher(mode, key, data, { label }) {
103108
data,
104109
kKeyVariantRSA_OAEP,
105110
normalizeHashName(key.algorithm.hash.name),
106-
label));
111+
algorithm.label));
112+
}
113+
114+
function validateRsaKeyGenerateAlgorithm(algorithm) {
115+
const publicExponentConverted = bigIntArrayToUnsignedInt(algorithm.publicExponent);
116+
if (publicExponentConverted === undefined) {
117+
throw lazyDOMException(
118+
'The publicExponent must be equivalent to an unsigned 32-bit value',
119+
'OperationError');
120+
}
121+
122+
return publicExponentConverted;
107123
}
108124

109125
async function rsaKeyGenerate(
110126
algorithm,
111127
extractable,
112-
keyUsages) {
113-
128+
keyUsages,
129+
) {
130+
const publicExponentConverted = validateRsaKeyGenerateAlgorithm(algorithm);
114131
const {
115132
name,
116133
modulusLength,
@@ -120,13 +137,6 @@ async function rsaKeyGenerate(
120137

121138
const usageSet = new SafeSet(keyUsages);
122139

123-
const publicExponentConverted = bigIntArrayToUnsignedInt(publicExponent);
124-
if (publicExponentConverted === undefined) {
125-
throw lazyDOMException(
126-
'The publicExponent must be equivalent to an unsigned 32-bit value',
127-
'OperationError');
128-
}
129-
130140
switch (name) {
131141
case 'RSA-OAEP':
132142
if (hasAnyNotIn(usageSet,
@@ -319,7 +329,7 @@ function rsaImportKey(
319329
}, keyUsages, extractable);
320330
}
321331

322-
async function rsaSignVerify(key, data, { saltLength }, signature) {
332+
function rsaSignVerify(key, data, { saltLength }, signature) {
323333
const mode = signature === undefined ? kSignJobModeSign : kSignJobModeVerify;
324334
const type = mode === kSignJobModeSign ? 'private' : 'public';
325335

‎lib/internal/crypto/util.js

-17
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ const {
5050
ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED,
5151
ERR_CRYPTO_ENGINE_UNKNOWN,
5252
ERR_INVALID_ARG_TYPE,
53-
ERR_INVALID_ARG_VALUE,
54-
ERR_OUT_OF_RANGE,
5553
},
5654
hideStackFrames,
5755
} = require('internal/errors');
@@ -418,20 +416,6 @@ function hasAnyNotIn(set, checks) {
418416
return false;
419417
}
420418

421-
function validateBitLength(length, name, required = false) {
422-
if (length !== undefined || required) {
423-
validateNumber(length, name);
424-
if (length < 0)
425-
throw new ERR_OUT_OF_RANGE(name, '> 0');
426-
if (length % 8) {
427-
throw new ERR_INVALID_ARG_VALUE(
428-
name,
429-
length,
430-
'must be a multiple of 8');
431-
}
432-
}
433-
}
434-
435419
function validateByteLength(buf, name, target) {
436420
if (buf.byteLength !== target) {
437421
throw lazyDOMException(
@@ -617,7 +601,6 @@ module.exports = {
617601
normalizeAlgorithm,
618602
normalizeHashName,
619603
hasAnyNotIn,
620-
validateBitLength,
621604
validateByteLength,
622605
validateByteSource,
623606
validateKeyOps,

‎test/parallel/test-webcrypto-derivebits-cfrg.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ async function prepareKeys() {
182182
},
183183
keys.X448.privateKey,
184184
8 * keys.X448.size),
185-
{ message: 'The public and private keys must be of the same type' });
185+
{ message: 'algorithm.public must be an X448 key' });
186186
}
187187

188188
{

‎test/parallel/test-webcrypto-derivebits-ecdh.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ async function prepareKeys() {
202202
public: keys['P-384'].publicKey
203203
},
204204
keys['P-521'].privateKey,
205-
8 * keys['P-521'].size),
205+
8 * keys['P-384'].size),
206206
{ message: /Named curve mismatch/ });
207207
}
208208

@@ -218,7 +218,7 @@ async function prepareKeys() {
218218
name: 'ECDH',
219219
public: publicKey
220220
}, keys['P-521'].privateKey, null), {
221-
message: /Keys must be ECDH, X25519, or X448 keys/
221+
message: 'algorithm.public must be an ECDH key'
222222
});
223223
}
224224

‎test/parallel/test-webcrypto-derivekey-cfrg.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ async function prepareKeys() {
136136
},
137137
keys.X448.privateKey,
138138
...otherArgs),
139-
{ message: 'The public and private keys must be of the same type' });
139+
{ message: 'algorithm.public must be an X448 key' });
140140
}
141141

142142
{

‎test/parallel/test-webcrypto-derivekey-ecdh.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ async function prepareKeys() {
174174
},
175175
keys['P-521'].privateKey,
176176
...otherArgs),
177-
{ message: /Keys must be ECDH, X25519, or X448 keys/ });
177+
{ message: 'algorithm.public must be an ECDH key' });
178178
}
179179

180180
{

‎test/parallel/test-webcrypto-encrypt-decrypt.js

+14
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,20 @@ const { subtle } = globalThis.crypto;
3737
assert.strictEqual(
3838
Buffer.from(plaintext).toString('hex'),
3939
Buffer.from(buf).toString('hex'));
40+
41+
await assert.rejects(() => subtle.encrypt({
42+
name: 'RSA-OAEP',
43+
}, privateKey, buf), {
44+
name: 'InvalidAccessError',
45+
message: 'The requested operation is not valid for the provided key'
46+
});
47+
48+
await assert.rejects(() => subtle.decrypt({
49+
name: 'RSA-OAEP',
50+
}, publicKey, ciphertext), {
51+
name: 'InvalidAccessError',
52+
message: 'The requested operation is not valid for the provided key'
53+
});
4054
}
4155

4256
test().then(common.mustCall());

‎test/parallel/test-webcrypto-export-import.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ const { subtle } = globalThis.crypto;
3636
}, false, ['sign', 'verify']), {
3737
code: 'ERR_MISSING_OPTION'
3838
});
39+
await assert.rejects(
40+
subtle.importKey('raw', keyData, {
41+
name: 'HMAC',
42+
hash: 'SHA-256',
43+
length: 384,
44+
}, false, ['sign', 'verify']), {
45+
name: 'DataError',
46+
message: 'Invalid key length'
47+
});
3948
await assert.rejects(
4049
subtle.importKey('raw', keyData, {
4150
name: 'HMAC',
@@ -59,8 +68,8 @@ const { subtle } = globalThis.crypto;
5968
hash: 'SHA-256',
6069
length: 1
6170
}, false, ['sign', 'verify']), {
62-
name: 'DataError',
63-
message: 'Invalid key length'
71+
name: 'NotSupportedError',
72+
message: 'Unsupported algorithm.length'
6473
});
6574
await assert.rejects(
6675
subtle.importKey('jwk', null, {

‎test/parallel/test-webcrypto-keygen.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,14 @@ const vectors = {
345345
{ code: 'ERR_INVALID_ARG_TYPE' });
346346
}));
347347

348+
await assert.rejects(
349+
subtle.generateKey(
350+
{ name, modulusLength, publicExponent: new Uint8Array([1, 1, 1, 1, 1]), hash }, true, usages),
351+
{
352+
message: /The publicExponent must be equivalent to an unsigned 32-bit value/,
353+
name: 'OperationError',
354+
});
355+
348356
await Promise.all([true, 1].map((hash) => {
349357
return assert.rejects(subtle.generateKey({
350358
name,
@@ -494,8 +502,6 @@ const vectors = {
494502

495503
const tests = kTests.map((args) => test(...args));
496504

497-
// Test bad parameters
498-
499505
Promise.all(tests).then(common.mustCall());
500506
}
501507

@@ -675,7 +681,5 @@ assert.throws(() => new CryptoKey(), { code: 'ERR_ILLEGAL_CONSTRUCTOR' });
675681

676682
const tests = kTests.map((args) => test(...args));
677683

678-
// Test bad parameters
679-
680684
Promise.all(tests).then(common.mustCall());
681685
}

0 commit comments

Comments
 (0)
Please sign in to comment.