react-native-quick-crypto 1.1.3 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/QuickCrypto.podspec +2 -2
- package/android/build.gradle +2 -2
- package/lib/commonjs/index.js +4 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/subtle.js +692 -12
- package/lib/commonjs/subtle.js.map +1 -1
- package/lib/commonjs/utils/types.js.map +1 -1
- package/lib/module/index.js +4 -4
- package/lib/module/index.js.map +1 -1
- package/lib/module/subtle.js +693 -13
- package/lib/module/subtle.js.map +1 -1
- package/lib/module/utils/types.js.map +1 -1
- package/lib/typescript/index.d.ts +6 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/subtle.d.ts.map +1 -1
- package/lib/typescript/utils/types.d.ts +3 -1
- package/lib/typescript/utils/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +16 -3
- package/src/subtle.ts +736 -26
- package/src/utils/types.ts +5 -0
package/lib/commonjs/subtle.js
CHANGED
|
@@ -29,7 +29,6 @@ var _mldsa = require("./mldsa");
|
|
|
29
29
|
var _slhdsa = require("./slhdsa");
|
|
30
30
|
var _mlkem = require("./mlkem");
|
|
31
31
|
var _hkdf = require("./hkdf");
|
|
32
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
33
32
|
// Temporary enums that need to be defined
|
|
34
33
|
var KWebCryptoKeyFormat = /*#__PURE__*/function (KWebCryptoKeyFormat) {
|
|
35
34
|
KWebCryptoKeyFormat[KWebCryptoKeyFormat["kWebCryptoKeyFormatRaw"] = 0] = "kWebCryptoKeyFormatRaw";
|
|
@@ -81,21 +80,682 @@ function getCanonicalAlgorithmNames() {
|
|
|
81
80
|
}
|
|
82
81
|
return _canonicalAlgorithmNames;
|
|
83
82
|
}
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
|
|
84
|
+
// Per-algorithm WebIDL converter table. Mirrors Node's kAlgorithmDefinitions
|
|
85
|
+
// (lib/internal/crypto/util.js): each (algorithm, operation) pair maps to a
|
|
86
|
+
// dictionary converter name, or null when only the `name` member is required.
|
|
87
|
+
// Operation keys are missing when an algorithm cannot perform that operation,
|
|
88
|
+
// causing `normalizeAlgorithm` to reject the call.
|
|
89
|
+
const kAlgorithmDefinitions = {
|
|
90
|
+
'AES-CBC': {
|
|
91
|
+
generateKey: 'AesKeyGenParams',
|
|
92
|
+
exportKey: null,
|
|
93
|
+
importKey: null,
|
|
94
|
+
encrypt: 'AesCbcParams',
|
|
95
|
+
decrypt: 'AesCbcParams',
|
|
96
|
+
'get key length': 'AesDerivedKeyParams'
|
|
97
|
+
},
|
|
98
|
+
'AES-CTR': {
|
|
99
|
+
generateKey: 'AesKeyGenParams',
|
|
100
|
+
exportKey: null,
|
|
101
|
+
importKey: null,
|
|
102
|
+
encrypt: 'AesCtrParams',
|
|
103
|
+
decrypt: 'AesCtrParams',
|
|
104
|
+
'get key length': 'AesDerivedKeyParams'
|
|
105
|
+
},
|
|
106
|
+
'AES-GCM': {
|
|
107
|
+
generateKey: 'AesKeyGenParams',
|
|
108
|
+
exportKey: null,
|
|
109
|
+
importKey: null,
|
|
110
|
+
encrypt: 'AeadParams',
|
|
111
|
+
decrypt: 'AeadParams',
|
|
112
|
+
'get key length': 'AesDerivedKeyParams'
|
|
113
|
+
},
|
|
114
|
+
'AES-KW': {
|
|
115
|
+
generateKey: 'AesKeyGenParams',
|
|
116
|
+
exportKey: null,
|
|
117
|
+
importKey: null,
|
|
118
|
+
'get key length': 'AesDerivedKeyParams',
|
|
119
|
+
wrapKey: null,
|
|
120
|
+
unwrapKey: null
|
|
121
|
+
},
|
|
122
|
+
'AES-OCB': {
|
|
123
|
+
generateKey: 'AesKeyGenParams',
|
|
124
|
+
exportKey: null,
|
|
125
|
+
importKey: null,
|
|
126
|
+
encrypt: 'AeadParams',
|
|
127
|
+
decrypt: 'AeadParams',
|
|
128
|
+
'get key length': 'AesDerivedKeyParams'
|
|
129
|
+
},
|
|
130
|
+
Argon2d: {
|
|
131
|
+
deriveBits: 'Argon2Params',
|
|
132
|
+
'get key length': null,
|
|
133
|
+
importKey: null
|
|
134
|
+
},
|
|
135
|
+
Argon2i: {
|
|
136
|
+
deriveBits: 'Argon2Params',
|
|
137
|
+
'get key length': null,
|
|
138
|
+
importKey: null
|
|
139
|
+
},
|
|
140
|
+
Argon2id: {
|
|
141
|
+
deriveBits: 'Argon2Params',
|
|
142
|
+
'get key length': null,
|
|
143
|
+
importKey: null
|
|
144
|
+
},
|
|
145
|
+
'ChaCha20-Poly1305': {
|
|
146
|
+
generateKey: null,
|
|
147
|
+
exportKey: null,
|
|
148
|
+
importKey: null,
|
|
149
|
+
encrypt: 'AeadParams',
|
|
150
|
+
decrypt: 'AeadParams',
|
|
151
|
+
'get key length': null
|
|
152
|
+
},
|
|
153
|
+
ECDH: {
|
|
154
|
+
generateKey: 'EcKeyGenParams',
|
|
155
|
+
exportKey: null,
|
|
156
|
+
importKey: 'EcKeyImportParams',
|
|
157
|
+
deriveBits: 'EcdhKeyDeriveParams'
|
|
158
|
+
},
|
|
159
|
+
ECDSA: {
|
|
160
|
+
generateKey: 'EcKeyGenParams',
|
|
161
|
+
exportKey: null,
|
|
162
|
+
importKey: 'EcKeyImportParams',
|
|
163
|
+
sign: 'EcdsaParams',
|
|
164
|
+
verify: 'EcdsaParams'
|
|
165
|
+
},
|
|
166
|
+
Ed25519: {
|
|
167
|
+
generateKey: null,
|
|
168
|
+
exportKey: null,
|
|
169
|
+
importKey: null,
|
|
170
|
+
sign: null,
|
|
171
|
+
verify: null
|
|
172
|
+
},
|
|
173
|
+
Ed448: {
|
|
174
|
+
generateKey: null,
|
|
175
|
+
exportKey: null,
|
|
176
|
+
importKey: null,
|
|
177
|
+
sign: 'ContextParams',
|
|
178
|
+
verify: 'ContextParams'
|
|
179
|
+
},
|
|
180
|
+
HKDF: {
|
|
181
|
+
importKey: null,
|
|
182
|
+
deriveBits: 'HkdfParams',
|
|
183
|
+
'get key length': null
|
|
184
|
+
},
|
|
185
|
+
HMAC: {
|
|
186
|
+
generateKey: 'HmacKeyGenParams',
|
|
187
|
+
exportKey: null,
|
|
188
|
+
importKey: 'HmacImportParams',
|
|
189
|
+
sign: null,
|
|
190
|
+
verify: null,
|
|
191
|
+
'get key length': 'HmacImportParams'
|
|
192
|
+
},
|
|
193
|
+
KMAC128: {
|
|
194
|
+
generateKey: 'KmacKeyGenParams',
|
|
195
|
+
exportKey: null,
|
|
196
|
+
importKey: 'KmacImportParams',
|
|
197
|
+
sign: 'KmacParams',
|
|
198
|
+
verify: 'KmacParams',
|
|
199
|
+
'get key length': 'KmacImportParams'
|
|
200
|
+
},
|
|
201
|
+
KMAC256: {
|
|
202
|
+
generateKey: 'KmacKeyGenParams',
|
|
203
|
+
exportKey: null,
|
|
204
|
+
importKey: 'KmacImportParams',
|
|
205
|
+
sign: 'KmacParams',
|
|
206
|
+
verify: 'KmacParams',
|
|
207
|
+
'get key length': 'KmacImportParams'
|
|
208
|
+
},
|
|
209
|
+
'ML-DSA-44': {
|
|
210
|
+
generateKey: null,
|
|
211
|
+
exportKey: null,
|
|
212
|
+
importKey: null,
|
|
213
|
+
sign: 'ContextParams',
|
|
214
|
+
verify: 'ContextParams'
|
|
215
|
+
},
|
|
216
|
+
'ML-DSA-65': {
|
|
217
|
+
generateKey: null,
|
|
218
|
+
exportKey: null,
|
|
219
|
+
importKey: null,
|
|
220
|
+
sign: 'ContextParams',
|
|
221
|
+
verify: 'ContextParams'
|
|
222
|
+
},
|
|
223
|
+
'ML-DSA-87': {
|
|
224
|
+
generateKey: null,
|
|
225
|
+
exportKey: null,
|
|
226
|
+
importKey: null,
|
|
227
|
+
sign: 'ContextParams',
|
|
228
|
+
verify: 'ContextParams'
|
|
229
|
+
},
|
|
230
|
+
'ML-KEM-512': {
|
|
231
|
+
generateKey: null,
|
|
232
|
+
exportKey: null,
|
|
233
|
+
importKey: null,
|
|
234
|
+
encapsulateBits: null,
|
|
235
|
+
decapsulateBits: null,
|
|
236
|
+
encapsulateKey: null,
|
|
237
|
+
decapsulateKey: null
|
|
238
|
+
},
|
|
239
|
+
'ML-KEM-768': {
|
|
240
|
+
generateKey: null,
|
|
241
|
+
exportKey: null,
|
|
242
|
+
importKey: null,
|
|
243
|
+
encapsulateBits: null,
|
|
244
|
+
decapsulateBits: null,
|
|
245
|
+
encapsulateKey: null,
|
|
246
|
+
decapsulateKey: null
|
|
247
|
+
},
|
|
248
|
+
'ML-KEM-1024': {
|
|
249
|
+
generateKey: null,
|
|
250
|
+
exportKey: null,
|
|
251
|
+
importKey: null,
|
|
252
|
+
encapsulateBits: null,
|
|
253
|
+
decapsulateBits: null,
|
|
254
|
+
encapsulateKey: null,
|
|
255
|
+
decapsulateKey: null
|
|
256
|
+
},
|
|
257
|
+
PBKDF2: {
|
|
258
|
+
importKey: null,
|
|
259
|
+
deriveBits: 'Pbkdf2Params',
|
|
260
|
+
'get key length': null
|
|
261
|
+
},
|
|
262
|
+
'RSA-OAEP': {
|
|
263
|
+
generateKey: 'RsaHashedKeyGenParams',
|
|
264
|
+
exportKey: null,
|
|
265
|
+
importKey: 'RsaHashedImportParams',
|
|
266
|
+
encrypt: 'RsaOaepParams',
|
|
267
|
+
decrypt: 'RsaOaepParams'
|
|
268
|
+
},
|
|
269
|
+
'RSA-PSS': {
|
|
270
|
+
generateKey: 'RsaHashedKeyGenParams',
|
|
271
|
+
exportKey: null,
|
|
272
|
+
importKey: 'RsaHashedImportParams',
|
|
273
|
+
sign: 'RsaPssParams',
|
|
274
|
+
verify: 'RsaPssParams'
|
|
275
|
+
},
|
|
276
|
+
'RSASSA-PKCS1-v1_5': {
|
|
277
|
+
generateKey: 'RsaHashedKeyGenParams',
|
|
278
|
+
exportKey: null,
|
|
279
|
+
importKey: 'RsaHashedImportParams',
|
|
280
|
+
sign: null,
|
|
281
|
+
verify: null
|
|
282
|
+
},
|
|
283
|
+
'SHA-1': {
|
|
284
|
+
digest: null
|
|
285
|
+
},
|
|
286
|
+
'SHA-256': {
|
|
287
|
+
digest: null
|
|
288
|
+
},
|
|
289
|
+
'SHA-384': {
|
|
290
|
+
digest: null
|
|
291
|
+
},
|
|
292
|
+
'SHA-512': {
|
|
293
|
+
digest: null
|
|
294
|
+
},
|
|
295
|
+
'SHA3-256': {
|
|
296
|
+
digest: null
|
|
297
|
+
},
|
|
298
|
+
'SHA3-384': {
|
|
299
|
+
digest: null
|
|
300
|
+
},
|
|
301
|
+
'SHA3-512': {
|
|
302
|
+
digest: null
|
|
303
|
+
},
|
|
304
|
+
cSHAKE128: {
|
|
305
|
+
digest: 'CShakeParams'
|
|
306
|
+
},
|
|
307
|
+
cSHAKE256: {
|
|
308
|
+
digest: 'CShakeParams'
|
|
309
|
+
},
|
|
310
|
+
KT128: {
|
|
311
|
+
digest: 'KangarooTwelveParams'
|
|
312
|
+
},
|
|
313
|
+
KT256: {
|
|
314
|
+
digest: 'KangarooTwelveParams'
|
|
315
|
+
},
|
|
316
|
+
TurboSHAKE128: {
|
|
317
|
+
digest: 'TurboShakeParams'
|
|
318
|
+
},
|
|
319
|
+
TurboSHAKE256: {
|
|
320
|
+
digest: 'TurboShakeParams'
|
|
321
|
+
},
|
|
322
|
+
X25519: {
|
|
323
|
+
generateKey: null,
|
|
324
|
+
exportKey: null,
|
|
325
|
+
importKey: null,
|
|
326
|
+
deriveBits: 'EcdhKeyDeriveParams'
|
|
327
|
+
},
|
|
328
|
+
X448: {
|
|
329
|
+
generateKey: null,
|
|
330
|
+
exportKey: null,
|
|
331
|
+
importKey: null,
|
|
332
|
+
deriveBits: 'EcdhKeyDeriveParams'
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
for (const v of _slhdsa.SLH_DSA_VARIANTS) {
|
|
336
|
+
kAlgorithmDefinitions[v] = {
|
|
337
|
+
generateKey: null,
|
|
338
|
+
exportKey: null,
|
|
339
|
+
importKey: null,
|
|
340
|
+
sign: null,
|
|
341
|
+
verify: null
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// WebIDL dictionary member specs. Mirrors Node's per-converter
|
|
346
|
+
// `createDictionaryConverter` definitions in lib/internal/crypto/webidl.js.
|
|
347
|
+
// `required: true` causes `normalizeAlgorithm` to throw a TypeError when the
|
|
348
|
+
// member is missing — matching the spec'd WebCrypto behavior that
|
|
349
|
+
// `SubtleCrypto.supports` relies on via try/catch.
|
|
350
|
+
|
|
351
|
+
const kRequiredFields = {
|
|
352
|
+
AesKeyGenParams: [{
|
|
353
|
+
key: 'length',
|
|
354
|
+
required: true
|
|
355
|
+
}],
|
|
356
|
+
AesDerivedKeyParams: [{
|
|
357
|
+
key: 'length',
|
|
358
|
+
required: true
|
|
359
|
+
}],
|
|
360
|
+
AesCbcParams: [{
|
|
361
|
+
key: 'iv',
|
|
362
|
+
required: true
|
|
363
|
+
}],
|
|
364
|
+
AesCtrParams: [{
|
|
365
|
+
key: 'counter',
|
|
366
|
+
required: true
|
|
367
|
+
}, {
|
|
368
|
+
key: 'length',
|
|
369
|
+
required: true
|
|
370
|
+
}],
|
|
371
|
+
AeadParams: [{
|
|
372
|
+
key: 'iv',
|
|
373
|
+
required: true
|
|
374
|
+
}, {
|
|
375
|
+
key: 'tagLength'
|
|
376
|
+
}, {
|
|
377
|
+
key: 'additionalData'
|
|
378
|
+
}],
|
|
379
|
+
EcKeyGenParams: [{
|
|
380
|
+
key: 'namedCurve',
|
|
381
|
+
required: true
|
|
382
|
+
}],
|
|
383
|
+
EcKeyImportParams: [{
|
|
384
|
+
key: 'namedCurve',
|
|
385
|
+
required: true
|
|
386
|
+
}],
|
|
387
|
+
EcdsaParams: [{
|
|
388
|
+
key: 'hash',
|
|
389
|
+
required: true
|
|
390
|
+
}],
|
|
391
|
+
EcdhKeyDeriveParams: [{
|
|
392
|
+
key: 'public',
|
|
393
|
+
required: true
|
|
394
|
+
}],
|
|
395
|
+
HmacKeyGenParams: [{
|
|
396
|
+
key: 'hash',
|
|
397
|
+
required: true
|
|
398
|
+
}, {
|
|
399
|
+
key: 'length'
|
|
400
|
+
}],
|
|
401
|
+
HmacImportParams: [{
|
|
402
|
+
key: 'hash',
|
|
403
|
+
required: true
|
|
404
|
+
}, {
|
|
405
|
+
key: 'length'
|
|
406
|
+
}],
|
|
407
|
+
HkdfParams: [{
|
|
408
|
+
key: 'hash',
|
|
409
|
+
required: true
|
|
410
|
+
}, {
|
|
411
|
+
key: 'salt',
|
|
412
|
+
required: true
|
|
413
|
+
}, {
|
|
414
|
+
key: 'info',
|
|
415
|
+
required: true
|
|
416
|
+
}],
|
|
417
|
+
Pbkdf2Params: [{
|
|
418
|
+
key: 'hash',
|
|
419
|
+
required: true
|
|
420
|
+
}, {
|
|
421
|
+
key: 'iterations',
|
|
422
|
+
required: true
|
|
423
|
+
}, {
|
|
424
|
+
key: 'salt',
|
|
425
|
+
required: true
|
|
426
|
+
}],
|
|
427
|
+
RsaHashedKeyGenParams: [{
|
|
428
|
+
key: 'modulusLength',
|
|
429
|
+
required: true
|
|
430
|
+
}, {
|
|
431
|
+
key: 'publicExponent',
|
|
432
|
+
required: true
|
|
433
|
+
}, {
|
|
434
|
+
key: 'hash',
|
|
435
|
+
required: true
|
|
436
|
+
}],
|
|
437
|
+
RsaHashedImportParams: [{
|
|
438
|
+
key: 'hash',
|
|
439
|
+
required: true
|
|
440
|
+
}],
|
|
441
|
+
RsaOaepParams: [{
|
|
442
|
+
key: 'label'
|
|
443
|
+
}],
|
|
444
|
+
RsaPssParams: [{
|
|
445
|
+
key: 'saltLength',
|
|
446
|
+
required: true
|
|
447
|
+
}],
|
|
448
|
+
ContextParams: [{
|
|
449
|
+
key: 'context'
|
|
450
|
+
}],
|
|
451
|
+
Argon2Params: [{
|
|
452
|
+
key: 'nonce',
|
|
453
|
+
required: true
|
|
454
|
+
}, {
|
|
455
|
+
key: 'parallelism',
|
|
456
|
+
required: true
|
|
457
|
+
}, {
|
|
458
|
+
key: 'memory',
|
|
459
|
+
required: true
|
|
460
|
+
}, {
|
|
461
|
+
key: 'passes',
|
|
462
|
+
required: true
|
|
463
|
+
}, {
|
|
464
|
+
key: 'version'
|
|
465
|
+
}, {
|
|
466
|
+
key: 'secretValue'
|
|
467
|
+
}, {
|
|
468
|
+
key: 'associatedData'
|
|
469
|
+
}],
|
|
470
|
+
KmacKeyGenParams: [{
|
|
471
|
+
key: 'length'
|
|
472
|
+
}],
|
|
473
|
+
KmacImportParams: [{
|
|
474
|
+
key: 'length'
|
|
475
|
+
}],
|
|
476
|
+
KmacParams: [{
|
|
477
|
+
key: 'outputLength',
|
|
478
|
+
required: true
|
|
479
|
+
}, {
|
|
480
|
+
key: 'customization'
|
|
481
|
+
}],
|
|
482
|
+
CShakeParams: [{
|
|
483
|
+
key: 'outputLength',
|
|
484
|
+
required: true
|
|
485
|
+
}, {
|
|
486
|
+
key: 'functionName'
|
|
487
|
+
}, {
|
|
488
|
+
key: 'customization'
|
|
489
|
+
}],
|
|
490
|
+
KangarooTwelveParams: [{
|
|
491
|
+
key: 'outputLength',
|
|
492
|
+
required: true
|
|
493
|
+
}, {
|
|
494
|
+
key: 'customization'
|
|
495
|
+
}],
|
|
496
|
+
TurboShakeParams: [{
|
|
497
|
+
key: 'outputLength',
|
|
498
|
+
required: true
|
|
499
|
+
}, {
|
|
500
|
+
key: 'domainSeparation'
|
|
501
|
+
}]
|
|
502
|
+
};
|
|
503
|
+
function isBufferSource(value) {
|
|
504
|
+
return value instanceof ArrayBuffer || ArrayBuffer.isView(value);
|
|
505
|
+
}
|
|
506
|
+
function validateBufferSource(algorithm, key) {
|
|
507
|
+
const value = algorithm[key];
|
|
508
|
+
if (value === undefined) return undefined;
|
|
509
|
+
if (!isBufferSource(value)) {
|
|
510
|
+
throw new TypeError(`Failed to normalize algorithm: '${key}' must be a BufferSource`);
|
|
511
|
+
}
|
|
512
|
+
return (0, _conversion.bufferLikeToArrayBuffer)(value);
|
|
513
|
+
}
|
|
514
|
+
function validateBinaryLike(algorithm, key) {
|
|
515
|
+
const value = algorithm[key];
|
|
516
|
+
if (value === undefined) return undefined;
|
|
517
|
+
try {
|
|
518
|
+
return (0, _conversion.binaryLikeToArrayBuffer)(value);
|
|
519
|
+
} catch {
|
|
520
|
+
throw new TypeError(`Failed to normalize algorithm: '${key}' must be a BufferSource`);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
function validateByteLength(buffer, key, length, message) {
|
|
524
|
+
if (buffer !== undefined && buffer.byteLength !== length) {
|
|
525
|
+
throw (0, _errors.lazyDOMException)(message ?? `${key} must be ${length} bytes`, 'OperationError');
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
function validateUnsignedInteger(algorithm, key) {
|
|
529
|
+
const value = algorithm[key];
|
|
530
|
+
if (value === undefined) return undefined;
|
|
531
|
+
const numberValue = Number(value);
|
|
532
|
+
if (!Number.isFinite(numberValue) || !Number.isInteger(numberValue) || numberValue < 0) {
|
|
533
|
+
throw new TypeError(`Failed to normalize algorithm: '${key}' must be an unsigned integer`);
|
|
534
|
+
}
|
|
535
|
+
algorithm[key] = numberValue;
|
|
536
|
+
return numberValue;
|
|
537
|
+
}
|
|
538
|
+
function validateHashAlgorithm(algorithm, converterName) {
|
|
539
|
+
const hash = algorithm.hash;
|
|
540
|
+
if (hash === undefined) return;
|
|
541
|
+
const normalizedHash = (0, _hashnames.normalizeHashName)(hash, _hashnames.HashContext.WebCrypto);
|
|
542
|
+
if (!['SHA-1', 'SHA-256', 'SHA-384', 'SHA-512', 'SHA3-256', 'SHA3-384', 'SHA3-512'].includes(normalizedHash)) {
|
|
543
|
+
throw (0, _errors.lazyDOMException)(`Unsupported ${converterName}.hash`, 'NotSupportedError');
|
|
544
|
+
}
|
|
545
|
+
algorithm.hash = {
|
|
546
|
+
name: normalizedHash
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
function validateAesLength(length) {
|
|
550
|
+
if (length !== undefined && length !== 128 && length !== 192 && length !== 256) {
|
|
551
|
+
throw (0, _errors.lazyDOMException)('Invalid key length', 'OperationError');
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
function validateMacLength(algorithm, key, zeroError) {
|
|
555
|
+
const length = validateUnsignedInteger(algorithm, key);
|
|
556
|
+
if (length === undefined) return;
|
|
557
|
+
if (length === 0) {
|
|
558
|
+
throw (0, _errors.lazyDOMException)(`${key} cannot be 0`, zeroError);
|
|
559
|
+
}
|
|
560
|
+
if (length % 8) {
|
|
561
|
+
throw (0, _errors.lazyDOMException)(`Unsupported ${key}`, 'NotSupportedError');
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
function validateAeadParams(algorithm) {
|
|
565
|
+
const iv = validateBufferSource(algorithm, 'iv');
|
|
566
|
+
const tagLength = validateUnsignedInteger(algorithm, 'tagLength');
|
|
567
|
+
validateBufferSource(algorithm, 'additionalData');
|
|
568
|
+
switch (algorithm.name) {
|
|
569
|
+
case 'AES-GCM':
|
|
570
|
+
if (tagLength !== undefined && ![32, 64, 96, 104, 112, 120, 128].includes(tagLength)) {
|
|
571
|
+
throw (0, _errors.lazyDOMException)(`${tagLength} is not a valid AES-GCM tag length`, 'OperationError');
|
|
572
|
+
}
|
|
573
|
+
break;
|
|
574
|
+
case 'AES-OCB':
|
|
575
|
+
if (iv !== undefined && (iv.byteLength < 1 || iv.byteLength > 15)) {
|
|
576
|
+
throw (0, _errors.lazyDOMException)('AES-OCB algorithm.iv must be between 1 and 15 bytes', 'OperationError');
|
|
577
|
+
}
|
|
578
|
+
if (tagLength !== undefined && ![64, 96, 128].includes(tagLength)) {
|
|
579
|
+
throw (0, _errors.lazyDOMException)(`${tagLength} is not a valid AES-OCB tag length`, 'OperationError');
|
|
580
|
+
}
|
|
581
|
+
break;
|
|
582
|
+
case 'ChaCha20-Poly1305':
|
|
583
|
+
validateByteLength(iv, 'algorithm.iv', 12, 'ChaCha20-Poly1305 IV must be exactly 12 bytes');
|
|
584
|
+
if (tagLength !== undefined && tagLength !== 128) {
|
|
585
|
+
throw (0, _errors.lazyDOMException)(`${tagLength} is not a valid ChaCha20-Poly1305 tag length`, 'OperationError');
|
|
586
|
+
}
|
|
587
|
+
break;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
function validateNormalizedAlgorithm(converterName, algorithm) {
|
|
591
|
+
switch (converterName) {
|
|
592
|
+
case 'AesKeyGenParams':
|
|
593
|
+
case 'AesDerivedKeyParams':
|
|
594
|
+
validateAesLength(validateUnsignedInteger(algorithm, 'length'));
|
|
595
|
+
break;
|
|
596
|
+
case 'AesCbcParams':
|
|
597
|
+
validateByteLength(validateBufferSource(algorithm, 'iv'), 'algorithm.iv', 16, 'algorithm.iv must contain exactly 16 bytes');
|
|
598
|
+
break;
|
|
599
|
+
case 'AesCtrParams':
|
|
600
|
+
{
|
|
601
|
+
validateByteLength(validateBufferSource(algorithm, 'counter'), 'algorithm.counter', 16);
|
|
602
|
+
const length = validateUnsignedInteger(algorithm, 'length');
|
|
603
|
+
if (length !== undefined && (length === 0 || length > 128)) {
|
|
604
|
+
throw (0, _errors.lazyDOMException)('AES-CTR algorithm.length must be between 1 and 128', 'OperationError');
|
|
605
|
+
}
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
case 'AeadParams':
|
|
609
|
+
validateAeadParams(algorithm);
|
|
610
|
+
break;
|
|
611
|
+
case 'EcdsaParams':
|
|
612
|
+
case 'HmacKeyGenParams':
|
|
613
|
+
case 'HmacImportParams':
|
|
614
|
+
case 'HkdfParams':
|
|
615
|
+
case 'Pbkdf2Params':
|
|
616
|
+
case 'RsaHashedKeyGenParams':
|
|
617
|
+
case 'RsaHashedImportParams':
|
|
618
|
+
validateHashAlgorithm(algorithm, converterName);
|
|
619
|
+
if (converterName === 'HmacKeyGenParams') {
|
|
620
|
+
validateMacLength(algorithm, 'length', 'OperationError');
|
|
621
|
+
}
|
|
622
|
+
if (converterName === 'HkdfParams') {
|
|
623
|
+
validateBinaryLike(algorithm, 'salt');
|
|
624
|
+
validateBinaryLike(algorithm, 'info');
|
|
625
|
+
} else if (converterName === 'Pbkdf2Params') {
|
|
626
|
+
const iterations = validateUnsignedInteger(algorithm, 'iterations');
|
|
627
|
+
if (iterations === 0) {
|
|
628
|
+
throw (0, _errors.lazyDOMException)('iterations cannot be zero', 'OperationError');
|
|
629
|
+
}
|
|
630
|
+
validateBinaryLike(algorithm, 'salt');
|
|
631
|
+
} else if (converterName === 'RsaHashedKeyGenParams') {
|
|
632
|
+
validateUnsignedInteger(algorithm, 'modulusLength');
|
|
633
|
+
validateBufferSource(algorithm, 'publicExponent');
|
|
634
|
+
}
|
|
635
|
+
break;
|
|
636
|
+
case 'RsaPssParams':
|
|
637
|
+
validateUnsignedInteger(algorithm, 'saltLength');
|
|
638
|
+
break;
|
|
639
|
+
case 'RsaOaepParams':
|
|
640
|
+
validateBufferSource(algorithm, 'label');
|
|
641
|
+
break;
|
|
642
|
+
case 'ContextParams':
|
|
643
|
+
validateBufferSource(algorithm, 'context');
|
|
644
|
+
break;
|
|
645
|
+
case 'EcdhKeyDeriveParams':
|
|
646
|
+
if (!(algorithm.public instanceof _keys.CryptoKey)) {
|
|
647
|
+
throw (0, _errors.lazyDOMException)('algorithm.public must be a public key', 'InvalidAccessError');
|
|
648
|
+
}
|
|
649
|
+
break;
|
|
650
|
+
case 'Argon2Params':
|
|
651
|
+
{
|
|
652
|
+
validateBufferSource(algorithm, 'nonce');
|
|
653
|
+
const parallelism = validateUnsignedInteger(algorithm, 'parallelism');
|
|
654
|
+
const memory = validateUnsignedInteger(algorithm, 'memory');
|
|
655
|
+
validateUnsignedInteger(algorithm, 'passes');
|
|
656
|
+
const version = validateUnsignedInteger(algorithm, 'version');
|
|
657
|
+
validateBufferSource(algorithm, 'secretValue');
|
|
658
|
+
validateBufferSource(algorithm, 'associatedData');
|
|
659
|
+
if (parallelism !== undefined && (parallelism === 0 || parallelism > 2 ** 24 - 1)) {
|
|
660
|
+
throw (0, _errors.lazyDOMException)('parallelism must be > 0 and < 16777215', 'OperationError');
|
|
661
|
+
}
|
|
662
|
+
if (memory !== undefined && parallelism !== undefined && memory < 8 * parallelism) {
|
|
663
|
+
throw (0, _errors.lazyDOMException)('memory must be at least 8 times the degree of parallelism', 'OperationError');
|
|
664
|
+
}
|
|
665
|
+
if (version !== undefined && version !== 0x13) {
|
|
666
|
+
throw (0, _errors.lazyDOMException)(`${version} is not a valid Argon2 version`, 'OperationError');
|
|
667
|
+
}
|
|
668
|
+
break;
|
|
669
|
+
}
|
|
670
|
+
case 'KmacKeyGenParams':
|
|
671
|
+
validateMacLength(algorithm, 'length', 'OperationError');
|
|
672
|
+
break;
|
|
673
|
+
case 'KmacImportParams':
|
|
674
|
+
validateMacLength(algorithm, 'length', 'DataError');
|
|
675
|
+
break;
|
|
676
|
+
case 'KmacParams':
|
|
677
|
+
validateMacLength(algorithm, 'outputLength', 'OperationError');
|
|
678
|
+
validateBufferSource(algorithm, 'customization');
|
|
679
|
+
break;
|
|
680
|
+
case 'CShakeParams':
|
|
681
|
+
case 'KangarooTwelveParams':
|
|
682
|
+
{
|
|
683
|
+
const outputLength = validateUnsignedInteger(algorithm, 'outputLength');
|
|
684
|
+
if (outputLength !== undefined && (outputLength === 0 || outputLength % 8)) {
|
|
685
|
+
throw (0, _errors.lazyDOMException)(`Invalid ${converterName} outputLength`, 'OperationError');
|
|
686
|
+
}
|
|
687
|
+
validateBufferSource(algorithm, 'functionName');
|
|
688
|
+
validateBufferSource(algorithm, 'customization');
|
|
689
|
+
break;
|
|
690
|
+
}
|
|
691
|
+
case 'TurboShakeParams':
|
|
692
|
+
{
|
|
693
|
+
const outputLength = validateUnsignedInteger(algorithm, 'outputLength');
|
|
694
|
+
const domainSeparation = validateUnsignedInteger(algorithm, 'domainSeparation');
|
|
695
|
+
if (outputLength !== undefined && (outputLength === 0 || outputLength % 8)) {
|
|
696
|
+
throw (0, _errors.lazyDOMException)('Invalid TurboShakeParams outputLength', 'OperationError');
|
|
697
|
+
}
|
|
698
|
+
if (domainSeparation !== undefined && (domainSeparation < 0x01 || domainSeparation > 0x7f)) {
|
|
699
|
+
throw (0, _errors.lazyDOMException)('TurboShakeParams.domainSeparation must be in range 0x01-0x7f', 'OperationError');
|
|
700
|
+
}
|
|
701
|
+
break;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
// WebCrypto §18.4.4 algorithm normalization. Mirrors Node's normalizeAlgorithm
|
|
707
|
+
// in lib/internal/crypto/util.js: canonicalizes `name`, looks up the
|
|
708
|
+
// (name, op) → converter mapping, and rejects inputs that omit required
|
|
709
|
+
// dictionary members. Callers in Subtle.supports rely on this throwing for
|
|
710
|
+
// invalid params — without it, supports() over-reports capability (#1025).
|
|
711
|
+
function normalizeAlgorithm(algorithm, operation) {
|
|
86
712
|
if (typeof algorithm === 'string') {
|
|
713
|
+
return normalizeAlgorithm({
|
|
714
|
+
name: algorithm
|
|
715
|
+
}, operation);
|
|
716
|
+
}
|
|
717
|
+
const name = algorithm.name;
|
|
718
|
+
if (typeof name !== 'string') {
|
|
719
|
+
throw new TypeError("Algorithm: 'name' is required");
|
|
720
|
+
}
|
|
721
|
+
const map = getCanonicalAlgorithmNames();
|
|
722
|
+
const canonical = map.get(name.toLowerCase());
|
|
723
|
+
if (canonical === undefined) {
|
|
724
|
+
throw (0, _errors.lazyDOMException)('Unrecognized algorithm name', 'NotSupportedError');
|
|
725
|
+
}
|
|
726
|
+
const opMap = kAlgorithmDefinitions[canonical];
|
|
727
|
+
if (!opMap || !(operation in opMap)) {
|
|
728
|
+
throw (0, _errors.lazyDOMException)('Unrecognized algorithm name', 'NotSupportedError');
|
|
729
|
+
}
|
|
730
|
+
const converterName = opMap[operation];
|
|
731
|
+
if (converterName == null) {
|
|
87
732
|
return {
|
|
88
|
-
name:
|
|
733
|
+
name: canonical
|
|
89
734
|
};
|
|
90
735
|
}
|
|
91
|
-
|
|
92
|
-
|
|
736
|
+
const fields = kRequiredFields[converterName];
|
|
737
|
+
if (!fields) {
|
|
93
738
|
return {
|
|
94
739
|
...algorithm,
|
|
95
740
|
name: canonical
|
|
96
741
|
};
|
|
97
742
|
}
|
|
98
|
-
|
|
743
|
+
const out = {
|
|
744
|
+
name: canonical
|
|
745
|
+
};
|
|
746
|
+
const src = algorithm;
|
|
747
|
+
for (const field of fields) {
|
|
748
|
+
const value = src[field.key];
|
|
749
|
+
if (value === undefined) {
|
|
750
|
+
if (field.required) {
|
|
751
|
+
throw new TypeError(`Failed to normalize algorithm: '${field.key}' is required in '${converterName}'`);
|
|
752
|
+
}
|
|
753
|
+
continue;
|
|
754
|
+
}
|
|
755
|
+
out[field.key] = value;
|
|
756
|
+
}
|
|
757
|
+
validateNormalizedAlgorithm(converterName, out);
|
|
758
|
+
return out;
|
|
99
759
|
}
|
|
100
760
|
function getAlgorithmName(name, length) {
|
|
101
761
|
switch (name) {
|
|
@@ -1972,7 +2632,6 @@ class Subtle {
|
|
|
1972
2632
|
}
|
|
1973
2633
|
async deriveBits(algorithm, baseKey, length = null) {
|
|
1974
2634
|
requireArgs(arguments.length, 2, 'deriveBits');
|
|
1975
|
-
const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'deriveBits');
|
|
1976
2635
|
// WebCrypto §SubtleCrypto.deriveBits step 11: throw InvalidAccessError
|
|
1977
2636
|
// unless `baseKey.[[usages]]` contains "deriveBits" specifically. The
|
|
1978
2637
|
// previous `deriveBits || deriveKey` accept-either branch silently
|
|
@@ -1981,6 +2640,7 @@ class Subtle {
|
|
|
1981
2640
|
if (!baseKey.usages.includes('deriveBits')) {
|
|
1982
2641
|
throw (0, _errors.lazyDOMException)('baseKey does not have deriveBits usage', 'InvalidAccessError');
|
|
1983
2642
|
}
|
|
2643
|
+
const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'deriveBits');
|
|
1984
2644
|
if (baseKey.algorithm.name !== normalizedAlgorithm.name) {
|
|
1985
2645
|
throw (0, _errors.lazyDOMException)('Key algorithm mismatch', 'InvalidAccessError');
|
|
1986
2646
|
}
|
|
@@ -2014,7 +2674,9 @@ class Subtle {
|
|
|
2014
2674
|
async deriveKey(algorithm, baseKey, derivedKeyAlgorithm, extractable, keyUsages) {
|
|
2015
2675
|
requireArgs(arguments.length, 5, 'deriveKey');
|
|
2016
2676
|
const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'deriveBits');
|
|
2017
|
-
|
|
2677
|
+
// Validate the derived-key algorithm up front (mirrors Node webcrypto.js:341).
|
|
2678
|
+
// The normalized form is unused — `this.importKey` re-normalizes below.
|
|
2679
|
+
normalizeAlgorithm(derivedKeyAlgorithm, 'importKey');
|
|
2018
2680
|
|
|
2019
2681
|
// Validate baseKey usage
|
|
2020
2682
|
if (!baseKey.usages.includes('deriveKey')) {
|
|
@@ -2025,7 +2687,10 @@ class Subtle {
|
|
|
2025
2687
|
}
|
|
2026
2688
|
|
|
2027
2689
|
// Calculate required key length (may be null for KDF-derived material).
|
|
2028
|
-
|
|
2690
|
+
// Mirrors Node webcrypto.js:350 — uses the raw derivedKeyAlgorithm with
|
|
2691
|
+
// op='get key length' so AES `length` survives normalization (the
|
|
2692
|
+
// 'importKey' converter for AES is null and strips dictionary members).
|
|
2693
|
+
const length = getKeyLength(normalizeAlgorithm(derivedKeyAlgorithm, 'get key length'));
|
|
2029
2694
|
|
|
2030
2695
|
// Step 1: Derive bits
|
|
2031
2696
|
let derivedBits;
|
|
@@ -2105,7 +2770,15 @@ class Subtle {
|
|
|
2105
2770
|
}
|
|
2106
2771
|
async wrapKey(format, key, wrappingKey, wrapAlgorithm) {
|
|
2107
2772
|
requireArgs(arguments.length, 4, 'wrapKey');
|
|
2108
|
-
|
|
2773
|
+
// Mirrors Node webcrypto.js:923-927: prefer the 'wrapKey' op (only
|
|
2774
|
+
// AES-KW defines it) and fall back to 'encrypt' for cipher-based wrap
|
|
2775
|
+
// algorithms like AES-GCM and RSA-OAEP.
|
|
2776
|
+
let normalizedWrapAlgorithm;
|
|
2777
|
+
try {
|
|
2778
|
+
normalizedWrapAlgorithm = normalizeAlgorithm(wrapAlgorithm, 'wrapKey');
|
|
2779
|
+
} catch {
|
|
2780
|
+
normalizedWrapAlgorithm = normalizeAlgorithm(wrapAlgorithm, 'encrypt');
|
|
2781
|
+
}
|
|
2109
2782
|
if (normalizedWrapAlgorithm.name !== wrappingKey.algorithm.name) {
|
|
2110
2783
|
throw (0, _errors.lazyDOMException)('Key algorithm mismatch', 'InvalidAccessError');
|
|
2111
2784
|
}
|
|
@@ -2144,7 +2817,14 @@ class Subtle {
|
|
|
2144
2817
|
}
|
|
2145
2818
|
async unwrapKey(format, wrappedKey, unwrappingKey, unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages) {
|
|
2146
2819
|
requireArgs(arguments.length, 7, 'unwrapKey');
|
|
2147
|
-
|
|
2820
|
+
// Mirrors Node webcrypto.js:1006-1010: prefer 'unwrapKey', fall back to
|
|
2821
|
+
// 'decrypt' for cipher-based unwrap algorithms.
|
|
2822
|
+
let normalizedUnwrapAlgorithm;
|
|
2823
|
+
try {
|
|
2824
|
+
normalizedUnwrapAlgorithm = normalizeAlgorithm(unwrapAlgorithm, 'unwrapKey');
|
|
2825
|
+
} catch {
|
|
2826
|
+
normalizedUnwrapAlgorithm = normalizeAlgorithm(unwrapAlgorithm, 'decrypt');
|
|
2827
|
+
}
|
|
2148
2828
|
if (normalizedUnwrapAlgorithm.name !== unwrappingKey.algorithm.name) {
|
|
2149
2829
|
throw (0, _errors.lazyDOMException)('Key algorithm mismatch', 'InvalidAccessError');
|
|
2150
2830
|
}
|