unjwt 0.4.0 → 0.5.0

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.
Files changed (49) hide show
  1. package/README.md +360 -190
  2. package/dist/index.d.mts +6 -5
  3. package/dist/index.d.ts +6 -5
  4. package/dist/index.mjs +5 -5
  5. package/dist/jwe.d.mts +3 -3
  6. package/dist/jwe.d.ts +3 -3
  7. package/dist/jwe.mjs +4 -3
  8. package/dist/jwk.d.mts +2 -2
  9. package/dist/jwk.d.ts +2 -2
  10. package/dist/jwk.mjs +2 -2
  11. package/dist/jws.d.mts +3 -3
  12. package/dist/jws.d.ts +3 -3
  13. package/dist/jws.mjs +4 -4
  14. package/dist/shared/unjwt.B4e_rwol.mjs +453 -0
  15. package/dist/shared/unjwt.B9uGngq-.d.mts +154 -0
  16. package/dist/shared/unjwt.BKG_8Y9G.d.ts +189 -0
  17. package/dist/shared/unjwt.BOEZHxi_.d.ts +154 -0
  18. package/dist/shared/unjwt.Bzcov22m.mjs +167 -0
  19. package/dist/shared/unjwt.C0bBN0AC.d.mts +200 -0
  20. package/dist/shared/unjwt.C0bBN0AC.d.ts +200 -0
  21. package/dist/shared/unjwt.CJ_ohCFC.d.mts +46 -0
  22. package/dist/shared/unjwt.CjHZv3F3.mjs +57 -0
  23. package/dist/shared/unjwt.D90BbcE1.d.mts +52 -0
  24. package/dist/shared/unjwt.DKq5VF7t.mjs +1186 -0
  25. package/dist/shared/unjwt.DYFIh1YE.d.mts +100 -0
  26. package/dist/shared/unjwt.DoVzOnty.d.ts +52 -0
  27. package/dist/shared/unjwt.Dz5Oe9BG.d.mts +189 -0
  28. package/dist/shared/unjwt.mc4AEAT7.d.ts +46 -0
  29. package/dist/shared/unjwt.ppm5Y0k7.d.ts +100 -0
  30. package/dist/shared/unjwt.sux3_Z19.mjs +101 -0
  31. package/dist/utils.d.mts +2 -0
  32. package/dist/utils.d.ts +2 -0
  33. package/dist/utils.mjs +1 -0
  34. package/package.json +8 -4
  35. package/dist/shared/unjwt.4uzJv0cA.d.mts +0 -110
  36. package/dist/shared/unjwt.A7HKFx3n.d.mts +0 -52
  37. package/dist/shared/unjwt.BdjvpIUY.d.mts +0 -79
  38. package/dist/shared/unjwt.BmjmfFWo.d.ts +0 -79
  39. package/dist/shared/unjwt.C9ELsKeK.mjs +0 -120
  40. package/dist/shared/unjwt.CVUxLNoy.d.ts +0 -52
  41. package/dist/shared/unjwt.ChP7VhqI.d.ts +0 -110
  42. package/dist/shared/unjwt.DD0p18Gd.mjs +0 -81
  43. package/dist/shared/unjwt.DGsIvgyn.d.ts +0 -106
  44. package/dist/shared/unjwt.DPTwlVpK.mjs +0 -28
  45. package/dist/shared/unjwt.Dr-mxtq9.d.mts +0 -106
  46. package/dist/shared/unjwt.KOd0vXyx.mjs +0 -90
  47. package/dist/shared/unjwt._GivNhs2.mjs +0 -213
  48. package/dist/shared/unjwt.zb2wBNCJ.d.mts +0 -82
  49. package/dist/shared/unjwt.zb2wBNCJ.d.ts +0 -82
@@ -0,0 +1,1186 @@
1
+ import { g as isCryptoKey, e as concatUint8Arrays, b as base64UrlEncode, t as textEncoder, r as randomBytes, a as isJWK, d as base64UrlDecode } from './unjwt.CjHZv3F3.mjs';
2
+
3
+ /**
4
+ * This is a fork of Jose library's utility functions.
5
+ * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/buffer_utils.ts
6
+ * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
7
+ */
8
+ const MAX_INT32 = 2 ** 32;
9
+ function writeUInt32BE(buf, value, offset) {
10
+ if (value < 0 || value >= MAX_INT32) {
11
+ throw new RangeError(
12
+ `value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`
13
+ );
14
+ }
15
+ buf.set([value >>> 24, value >>> 16, value >>> 8, value & 255], offset);
16
+ }
17
+ function uint64be(value) {
18
+ const high = Math.floor(value / MAX_INT32);
19
+ const low = value % MAX_INT32;
20
+ const buf = new Uint8Array(8);
21
+ writeUInt32BE(buf, high, 0);
22
+ writeUInt32BE(buf, low, 4);
23
+ return buf;
24
+ }
25
+ function uint32be(value) {
26
+ const buf = new Uint8Array(4);
27
+ writeUInt32BE(buf, value);
28
+ return buf;
29
+ }
30
+
31
+ /**
32
+ * This is a fork of Jose library's utility functions.
33
+ * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/cek.ts
34
+ * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/iv.ts
35
+ * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
36
+ */
37
+ function bitLengthIV(alg) {
38
+ switch (alg) {
39
+ case "A128GCM":
40
+ case "A128GCMKW":
41
+ case "A192GCM":
42
+ case "A192GCMKW":
43
+ case "A256GCM":
44
+ case "A256GCMKW": {
45
+ return 96;
46
+ }
47
+ case "A128CBC-HS256":
48
+ case "A192CBC-HS384":
49
+ case "A256CBC-HS512": {
50
+ return 128;
51
+ }
52
+ default: {
53
+ throw new Error(`Unsupported JWE Algorithm: ${alg}`);
54
+ }
55
+ }
56
+ }
57
+ function generateIV(alg) {
58
+ return crypto.getRandomValues(new Uint8Array(bitLengthIV(alg) >> 3));
59
+ }
60
+ function checkIvLength(enc, iv) {
61
+ if (iv.length << 3 !== bitLengthIV(enc)) {
62
+ throw new Error("Invalid Initialization Vector length");
63
+ }
64
+ }
65
+ function bitLengthCEK(alg) {
66
+ switch (alg) {
67
+ case "A128GCM": {
68
+ return 128;
69
+ }
70
+ case "A192GCM": {
71
+ return 192;
72
+ }
73
+ case "A256GCM":
74
+ case "A128CBC-HS256": {
75
+ return 256;
76
+ }
77
+ case "A192CBC-HS384": {
78
+ return 384;
79
+ }
80
+ case "A256CBC-HS512": {
81
+ return 512;
82
+ }
83
+ default: {
84
+ throw new Error(`Unsupported JWE Algorithm: ${alg}`);
85
+ }
86
+ }
87
+ }
88
+ function generateCEK(alg) {
89
+ return crypto.getRandomValues(new Uint8Array(bitLengthCEK(alg) >> 3));
90
+ }
91
+ function checkCEKLength(cek, expected) {
92
+ const actual = cek.byteLength << 3;
93
+ if (actual !== expected) {
94
+ throw new Error(
95
+ `Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`
96
+ );
97
+ }
98
+ }
99
+
100
+ /**
101
+ * This is a fork of Jose library's utility functions.
102
+ * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/crypto_key.ts
103
+ * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
104
+ */
105
+ function unusable(name, prop = "algorithm.name") {
106
+ return new TypeError(
107
+ `CryptoKey does not support this operation, its ${prop} must be ${name}`
108
+ );
109
+ }
110
+ function isAlgorithm(algorithm, name) {
111
+ return algorithm.name === name;
112
+ }
113
+ function getHashLength(hash) {
114
+ return Number.parseInt(hash.name.slice(4), 10);
115
+ }
116
+ function getNamedCurve(alg) {
117
+ switch (alg) {
118
+ case "ES256": {
119
+ return "P-256";
120
+ }
121
+ case "ES384": {
122
+ return "P-384";
123
+ }
124
+ case "ES512": {
125
+ return "P-521";
126
+ }
127
+ default: {
128
+ throw new Error("unreachable");
129
+ }
130
+ }
131
+ }
132
+ function checkUsage(key, usage) {
133
+ if (usage && !key.usages.includes(usage)) {
134
+ throw new TypeError(
135
+ `CryptoKey does not support this operation, its usages must include ${usage}.`
136
+ );
137
+ }
138
+ }
139
+ function checkSigCryptoKey(key, alg, usage) {
140
+ switch (alg) {
141
+ case "HS256":
142
+ case "HS384":
143
+ case "HS512": {
144
+ if (!isAlgorithm(key.algorithm, "HMAC"))
145
+ throw unusable("HMAC");
146
+ const expected = Number.parseInt(alg.slice(2), 10);
147
+ const actual = getHashLength(key.algorithm.hash);
148
+ if (actual !== expected)
149
+ throw unusable(`SHA-${expected}`, "algorithm.hash");
150
+ break;
151
+ }
152
+ case "RS256":
153
+ case "RS384":
154
+ case "RS512": {
155
+ if (!isAlgorithm(key.algorithm, "RSASSA-PKCS1-v1_5"))
156
+ throw unusable("RSASSA-PKCS1-v1_5");
157
+ const expected = Number.parseInt(alg.slice(2), 10);
158
+ const actual = getHashLength(key.algorithm.hash);
159
+ if (actual !== expected)
160
+ throw unusable(`SHA-${expected}`, "algorithm.hash");
161
+ break;
162
+ }
163
+ case "PS256":
164
+ case "PS384":
165
+ case "PS512": {
166
+ if (!isAlgorithm(key.algorithm, "RSA-PSS"))
167
+ throw unusable("RSA-PSS");
168
+ const expected = Number.parseInt(alg.slice(2), 10);
169
+ const actual = getHashLength(key.algorithm.hash);
170
+ if (actual !== expected)
171
+ throw unusable(`SHA-${expected}`, "algorithm.hash");
172
+ break;
173
+ }
174
+ case "Ed25519":
175
+ // Fall through
176
+ case "EdDSA": {
177
+ if (!isAlgorithm(key.algorithm, "Ed25519")) throw unusable("Ed25519");
178
+ break;
179
+ }
180
+ case "ES256":
181
+ case "ES384":
182
+ case "ES512": {
183
+ if (!isAlgorithm(key.algorithm, "ECDSA"))
184
+ throw unusable("ECDSA");
185
+ const expected = getNamedCurve(alg);
186
+ const actual = key.algorithm.namedCurve;
187
+ if (actual !== expected) throw unusable(expected, "algorithm.namedCurve");
188
+ break;
189
+ }
190
+ default: {
191
+ throw new TypeError("CryptoKey does not support this operation");
192
+ }
193
+ }
194
+ checkUsage(key, usage);
195
+ }
196
+ function checkEncCryptoKey(key, alg, usage) {
197
+ switch (alg) {
198
+ case "A128GCM":
199
+ case "A192GCM":
200
+ case "A256GCM": {
201
+ if (!isAlgorithm(key.algorithm, "AES-GCM"))
202
+ throw unusable("AES-GCM");
203
+ const expected = Number.parseInt(alg.slice(1, 4), 10);
204
+ const actual = key.algorithm.length;
205
+ if (actual !== expected) throw unusable(expected, "algorithm.length");
206
+ break;
207
+ }
208
+ case "A128KW":
209
+ case "A192KW":
210
+ case "A256KW": {
211
+ if (!isAlgorithm(key.algorithm, "AES-KW"))
212
+ throw unusable("AES-KW");
213
+ const expected = Number.parseInt(alg.slice(1, 4), 10);
214
+ const actual = key.algorithm.length;
215
+ if (actual !== expected) throw unusable(expected, "algorithm.length");
216
+ break;
217
+ }
218
+ case "ECDH": {
219
+ switch (key.algorithm.name) {
220
+ case "ECDH":
221
+ case "X25519": {
222
+ break;
223
+ }
224
+ default: {
225
+ throw unusable("ECDH or X25519");
226
+ }
227
+ }
228
+ break;
229
+ }
230
+ case "PBES2-HS256+A128KW":
231
+ case "PBES2-HS384+A192KW":
232
+ case "PBES2-HS512+A256KW": {
233
+ if (!isAlgorithm(key.algorithm, "PBKDF2")) throw unusable("PBKDF2");
234
+ break;
235
+ }
236
+ case "RSA-OAEP":
237
+ case "RSA-OAEP-256":
238
+ case "RSA-OAEP-384":
239
+ case "RSA-OAEP-512": {
240
+ if (!isAlgorithm(key.algorithm, "RSA-OAEP"))
241
+ throw unusable("RSA-OAEP");
242
+ const expected = Number.parseInt(alg.slice(9), 10) || 1;
243
+ const actual = getHashLength(key.algorithm.hash);
244
+ if (actual !== expected)
245
+ throw unusable(`SHA-${expected}`, "algorithm.hash");
246
+ break;
247
+ }
248
+ default: {
249
+ throw new TypeError("CryptoKey does not support this operation");
250
+ }
251
+ }
252
+ checkUsage(key, usage);
253
+ }
254
+
255
+ /**
256
+ * This is a fork of Jose library's utility functions.
257
+ * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/encrypt.ts
258
+ * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/decrypt.ts
259
+ * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
260
+ */
261
+ async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
262
+ if (!(cek instanceof Uint8Array)) {
263
+ throw new TypeError(`Key must be ${cek} of type: Uint8Array`);
264
+ }
265
+ const keySize = Number.parseInt(enc.slice(1, 4), 10);
266
+ const encKey = await crypto.subtle.importKey(
267
+ "raw",
268
+ cek.subarray(keySize >> 3),
269
+ "AES-CBC",
270
+ false,
271
+ ["encrypt"]
272
+ );
273
+ const macKey = await crypto.subtle.importKey(
274
+ "raw",
275
+ cek.subarray(0, keySize >> 3),
276
+ {
277
+ hash: `SHA-${keySize << 1}`,
278
+ name: "HMAC"
279
+ },
280
+ false,
281
+ ["sign"]
282
+ );
283
+ const ciphertext = new Uint8Array(
284
+ await crypto.subtle.encrypt(
285
+ {
286
+ iv,
287
+ name: "AES-CBC"
288
+ },
289
+ encKey,
290
+ plaintext
291
+ )
292
+ );
293
+ const macData = concatUint8Arrays(
294
+ aad,
295
+ iv,
296
+ ciphertext,
297
+ uint64be(aad.length << 3)
298
+ );
299
+ const tag = new Uint8Array(
300
+ (await crypto.subtle.sign("HMAC", macKey, macData)).slice(0, keySize >> 3)
301
+ );
302
+ return { ciphertext, tag, iv };
303
+ }
304
+ async function gcmEncrypt(enc, plaintext, cek, iv, aad) {
305
+ let encKey;
306
+ if (cek instanceof Uint8Array) {
307
+ encKey = await crypto.subtle.importKey("raw", cek, "AES-GCM", false, [
308
+ "encrypt"
309
+ ]);
310
+ } else {
311
+ checkEncCryptoKey(cek, enc, "encrypt");
312
+ encKey = cek;
313
+ }
314
+ const encrypted = new Uint8Array(
315
+ await crypto.subtle.encrypt(
316
+ {
317
+ additionalData: aad,
318
+ iv,
319
+ name: "AES-GCM",
320
+ tagLength: 128
321
+ },
322
+ encKey,
323
+ plaintext
324
+ )
325
+ );
326
+ const tag = encrypted.slice(-16);
327
+ const ciphertext = encrypted.slice(0, -16);
328
+ return { ciphertext, tag, iv };
329
+ }
330
+ async function encrypt(enc, plaintext, cek, iv, aad) {
331
+ if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {
332
+ throw new TypeError(
333
+ `Key must be ${cek} one of type: CryptoKey, Uint8Array, or JSON Web Key`
334
+ );
335
+ }
336
+ if (iv) {
337
+ checkIvLength(enc, iv);
338
+ } else {
339
+ iv = generateIV(enc);
340
+ }
341
+ switch (enc) {
342
+ case "A128CBC-HS256":
343
+ case "A192CBC-HS384":
344
+ case "A256CBC-HS512": {
345
+ if (cek instanceof Uint8Array) {
346
+ checkCEKLength(cek, Number.parseInt(enc.slice(-3), 10));
347
+ }
348
+ return cbcEncrypt(enc, plaintext, cek, iv, aad);
349
+ }
350
+ case "A128GCM":
351
+ case "A192GCM":
352
+ case "A256GCM": {
353
+ if (cek instanceof Uint8Array) {
354
+ checkCEKLength(cek, Number.parseInt(enc.slice(1, 4), 10));
355
+ }
356
+ return gcmEncrypt(enc, plaintext, cek, iv, aad);
357
+ }
358
+ default: {
359
+ throw new Error("Unsupported JWE Content Encryption Algorithm");
360
+ }
361
+ }
362
+ }
363
+ async function timingSafeEqual(a, b) {
364
+ if (!(a instanceof Uint8Array)) {
365
+ throw new TypeError("First argument must be a buffer");
366
+ }
367
+ if (!(b instanceof Uint8Array)) {
368
+ throw new TypeError("Second argument must be a buffer");
369
+ }
370
+ const algorithm = { name: "HMAC", hash: "SHA-256" };
371
+ const key = await crypto.subtle.generateKey(algorithm, false, [
372
+ "sign"
373
+ ]);
374
+ const aHmac = new Uint8Array(await crypto.subtle.sign(algorithm, key, a));
375
+ const bHmac = new Uint8Array(await crypto.subtle.sign(algorithm, key, b));
376
+ let out = 0;
377
+ let i = -1;
378
+ while (++i < 32) {
379
+ out |= aHmac[i] ^ bHmac[i];
380
+ }
381
+ return out === 0;
382
+ }
383
+ async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
384
+ if (!(cek instanceof Uint8Array)) {
385
+ throw new TypeError(`Key must be ${cek} of type: Uint8Array`);
386
+ }
387
+ const keySize = Number.parseInt(enc.slice(1, 4), 10);
388
+ const encKey = await crypto.subtle.importKey(
389
+ "raw",
390
+ cek.subarray(keySize >> 3),
391
+ "AES-CBC",
392
+ false,
393
+ ["decrypt"]
394
+ );
395
+ const macKey = await crypto.subtle.importKey(
396
+ "raw",
397
+ cek.subarray(0, keySize >> 3),
398
+ {
399
+ hash: `SHA-${keySize << 1}`,
400
+ name: "HMAC"
401
+ },
402
+ false,
403
+ ["sign"]
404
+ );
405
+ const macData = concatUint8Arrays(
406
+ aad,
407
+ iv,
408
+ ciphertext,
409
+ uint64be(aad.length << 3)
410
+ );
411
+ const expectedTag = new Uint8Array(
412
+ (await crypto.subtle.sign("HMAC", macKey, macData)).slice(0, keySize >> 3)
413
+ );
414
+ let macCheckPassed;
415
+ try {
416
+ macCheckPassed = await timingSafeEqual(tag, expectedTag);
417
+ } catch {
418
+ }
419
+ if (!macCheckPassed) {
420
+ throw new Error("JWE Decryption Failed");
421
+ }
422
+ let plaintext;
423
+ try {
424
+ plaintext = new Uint8Array(
425
+ await crypto.subtle.decrypt({ iv, name: "AES-CBC" }, encKey, ciphertext)
426
+ );
427
+ } catch {
428
+ }
429
+ if (!plaintext) {
430
+ throw new Error("JWE Decryption Failed");
431
+ }
432
+ return plaintext;
433
+ }
434
+ async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) {
435
+ let encKey;
436
+ if (cek instanceof Uint8Array) {
437
+ encKey = await crypto.subtle.importKey("raw", cek, "AES-GCM", false, [
438
+ "decrypt"
439
+ ]);
440
+ } else {
441
+ checkEncCryptoKey(cek, enc, "decrypt");
442
+ encKey = cek;
443
+ }
444
+ try {
445
+ return new Uint8Array(
446
+ await crypto.subtle.decrypt(
447
+ {
448
+ additionalData: aad,
449
+ iv,
450
+ name: "AES-GCM",
451
+ tagLength: 128
452
+ },
453
+ encKey,
454
+ concatUint8Arrays(ciphertext, tag)
455
+ )
456
+ );
457
+ } catch {
458
+ throw new Error("JWE Decryption Failed");
459
+ }
460
+ }
461
+ async function decrypt(enc, cek, ciphertext, iv, tag, aad) {
462
+ if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {
463
+ throw new TypeError(
464
+ `Key must be ${cek} one of type: CryptoKey, Uint8Array, or JSON Web Key`
465
+ );
466
+ }
467
+ if (!iv) {
468
+ throw new Error("JWE Initialization Vector missing");
469
+ }
470
+ if (!tag) {
471
+ throw new Error("JWE Authentication Tag missing");
472
+ }
473
+ checkIvLength(enc, iv);
474
+ switch (enc) {
475
+ case "A128CBC-HS256":
476
+ case "A192CBC-HS384":
477
+ case "A256CBC-HS512": {
478
+ if (cek instanceof Uint8Array)
479
+ checkCEKLength(cek, Number.parseInt(enc.slice(-3), 10));
480
+ return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad);
481
+ }
482
+ case "A128GCM":
483
+ case "A192GCM":
484
+ case "A256GCM": {
485
+ if (cek instanceof Uint8Array)
486
+ checkCEKLength(cek, Number.parseInt(enc.slice(1, 4), 10));
487
+ return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad);
488
+ }
489
+ default: {
490
+ throw new Error("Unsupported JWE Content Encryption Algorithm");
491
+ }
492
+ }
493
+ }
494
+
495
+ /**
496
+ * This is a fork of Jose library's utility functions.
497
+ * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/aesgcmkw.ts
498
+ * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
499
+ */
500
+ async function encryptIV(alg, key, cek, iv) {
501
+ const jweAlgorithm = alg.slice(0, 7);
502
+ const wrapped = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0));
503
+ return {
504
+ encryptedKey: wrapped.ciphertext,
505
+ iv: base64UrlEncode(wrapped.iv),
506
+ tag: base64UrlEncode(wrapped.tag)
507
+ };
508
+ }
509
+ async function decryptIV(alg, key, encryptedKey, iv, tag) {
510
+ const jweAlgorithm = alg.slice(0, 7);
511
+ return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0));
512
+ }
513
+
514
+ /**
515
+ * This is a fork of Jose library's utility functions.
516
+ * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/jwt_to_key.ts
517
+ * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
518
+ */
519
+ function subtleMapping(jwk) {
520
+ let algorithm;
521
+ let keyUsages;
522
+ switch (jwk.kty) {
523
+ case "RSA": {
524
+ switch (jwk.alg) {
525
+ case "PS256":
526
+ case "PS384":
527
+ case "PS512": {
528
+ algorithm = { name: "RSA-PSS", hash: `SHA-${jwk.alg.slice(-3)}` };
529
+ keyUsages = jwk.d ? ["sign"] : ["verify"];
530
+ break;
531
+ }
532
+ case "RS256":
533
+ case "RS384":
534
+ case "RS512": {
535
+ algorithm = {
536
+ name: "RSASSA-PKCS1-v1_5",
537
+ hash: `SHA-${jwk.alg.slice(-3)}`
538
+ };
539
+ keyUsages = jwk.d ? ["sign"] : ["verify"];
540
+ break;
541
+ }
542
+ case "RSA-OAEP":
543
+ case "RSA-OAEP-256":
544
+ case "RSA-OAEP-384":
545
+ case "RSA-OAEP-512": {
546
+ algorithm = {
547
+ name: "RSA-OAEP",
548
+ hash: `SHA-${Number.parseInt(jwk.alg.slice(-3), 10) || 1}`
549
+ };
550
+ keyUsages = jwk.d ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"];
551
+ break;
552
+ }
553
+ default: {
554
+ throw new Error(
555
+ 'Invalid or unsupported JWK "alg" (Algorithm) Parameter value'
556
+ );
557
+ }
558
+ }
559
+ break;
560
+ }
561
+ case "EC": {
562
+ switch (jwk.alg) {
563
+ case "ES256": {
564
+ algorithm = { name: "ECDSA", namedCurve: "P-256" };
565
+ keyUsages = jwk.d ? ["sign"] : ["verify"];
566
+ break;
567
+ }
568
+ case "ES384": {
569
+ algorithm = { name: "ECDSA", namedCurve: "P-384" };
570
+ keyUsages = jwk.d ? ["sign"] : ["verify"];
571
+ break;
572
+ }
573
+ case "ES512": {
574
+ algorithm = { name: "ECDSA", namedCurve: "P-521" };
575
+ keyUsages = jwk.d ? ["sign"] : ["verify"];
576
+ break;
577
+ }
578
+ case "ECDH-ES":
579
+ case "ECDH-ES+A128KW":
580
+ case "ECDH-ES+A192KW":
581
+ case "ECDH-ES+A256KW": {
582
+ algorithm = { name: "ECDH", namedCurve: jwk.crv };
583
+ keyUsages = jwk.d ? ["deriveBits"] : [];
584
+ break;
585
+ }
586
+ default: {
587
+ throw new Error(
588
+ 'Invalid or unsupported JWK "alg" (Algorithm) Parameter value'
589
+ );
590
+ }
591
+ }
592
+ break;
593
+ }
594
+ case "OKP": {
595
+ switch (jwk.alg) {
596
+ case "Ed25519":
597
+ // Fall through
598
+ case "EdDSA": {
599
+ algorithm = { name: "Ed25519" };
600
+ keyUsages = jwk.d ? ["sign"] : ["verify"];
601
+ break;
602
+ }
603
+ case "ECDH-ES":
604
+ case "ECDH-ES+A128KW":
605
+ case "ECDH-ES+A192KW":
606
+ case "ECDH-ES+A256KW": {
607
+ algorithm = { name: jwk.crv };
608
+ keyUsages = jwk.d ? ["deriveBits"] : [];
609
+ break;
610
+ }
611
+ default: {
612
+ throw new Error(
613
+ 'Invalid or unsupported JWK "alg" (Algorithm) Parameter value'
614
+ );
615
+ }
616
+ }
617
+ break;
618
+ }
619
+ default: {
620
+ throw new Error(
621
+ 'Invalid or unsupported JWK "kty" (Key Type) Parameter value'
622
+ );
623
+ }
624
+ }
625
+ return { algorithm, keyUsages };
626
+ }
627
+ async function jwkTokey(jwk) {
628
+ if (!jwk.alg) {
629
+ throw new TypeError(
630
+ '"alg" argument is required when "jwk.alg" is not present'
631
+ );
632
+ }
633
+ const { algorithm, keyUsages } = subtleMapping(jwk);
634
+ const keyData = { ...jwk };
635
+ delete keyData.alg;
636
+ delete keyData.use;
637
+ return crypto.subtle.importKey(
638
+ "jwk",
639
+ keyData,
640
+ algorithm,
641
+ jwk.ext ?? (jwk.d ? false : true),
642
+ jwk.key_ops ?? keyUsages
643
+ );
644
+ }
645
+
646
+ /**
647
+ * This is a fork of Jose library's utility functions.
648
+ * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/key_to_jwt.ts
649
+ * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
650
+ */
651
+ async function keyToJWK(key) {
652
+ if (key instanceof Uint8Array) {
653
+ return {
654
+ kty: "oct",
655
+ k: base64UrlEncode(key)
656
+ };
657
+ }
658
+ if (!isCryptoKey(key)) {
659
+ throw new TypeError(
660
+ `Key must be ${key} one of type: CryptoKey, or Uint8Array`
661
+ );
662
+ }
663
+ if (!key.extractable) {
664
+ throw new TypeError(
665
+ "non-extractable CryptoKey cannot be exported as a JWK"
666
+ );
667
+ }
668
+ const jwk = await crypto.subtle.exportKey("jwk", key);
669
+ return jwk;
670
+ }
671
+
672
+ /**
673
+ * This is a fork of Jose library's utility functions.
674
+ * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/pbes2kw.ts
675
+ * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
676
+ */
677
+ async function wrap(alg, key, cek, p2c, p2s) {
678
+ if (p2c && p2s) {
679
+ const derived = await deriveKey(p2s, alg, p2c, key);
680
+ const encryptedKey = await _wrap(alg.slice(-6), derived, cek);
681
+ return { encryptedKey, p2c, p2s: base64UrlEncode(p2s) };
682
+ } else {
683
+ const encryptedKey = await _wrap(alg, key, cek);
684
+ return { encryptedKey };
685
+ }
686
+ }
687
+ async function unwrap(alg, key, encryptedKey, p2c, p2s) {
688
+ if (p2c && p2s) {
689
+ const derived = await deriveKey(p2s, alg, p2c, key);
690
+ return _unwrap(alg.slice(-6), derived, encryptedKey);
691
+ } else {
692
+ return _unwrap(alg, key, encryptedKey);
693
+ }
694
+ }
695
+ function getCryptoKey(key, alg, options = {}) {
696
+ const {
697
+ importAlg = "PBKDF2",
698
+ extractable = false,
699
+ usage = "deriveBits"
700
+ } = options;
701
+ if (key instanceof Uint8Array) {
702
+ return crypto.subtle.importKey("raw", key, importAlg, extractable, [usage]);
703
+ }
704
+ checkEncCryptoKey(key, alg, usage);
705
+ return key;
706
+ }
707
+ async function deriveKey(p2s, alg, p2c, key) {
708
+ if (!(p2s instanceof Uint8Array) || p2s.length < 8) {
709
+ throw new Error("PBES2 Salt Input must be 8 or more octets");
710
+ }
711
+ if (p2c === void 0 || p2c < 1) {
712
+ throw new Error(
713
+ "PBES2 Iteration Count Parameter must be a positive integer"
714
+ );
715
+ }
716
+ const salt = concatUint8Arrays(
717
+ textEncoder.encode(alg),
718
+ new Uint8Array([0]),
719
+ p2s
720
+ );
721
+ const keylen = Number.parseInt(alg.slice(13, 16), 10);
722
+ const subtleAlg = {
723
+ hash: `SHA-${alg.slice(8, 11)}`,
724
+ iterations: p2c,
725
+ name: "PBKDF2",
726
+ salt
727
+ };
728
+ const cryptoKey = await getCryptoKey(key, alg);
729
+ return new Uint8Array(
730
+ await crypto.subtle.deriveBits(subtleAlg, cryptoKey, keylen)
731
+ );
732
+ }
733
+ function checkKeySize(key, alg) {
734
+ if (key.algorithm.length !== Number.parseInt(alg.slice(1, 4), 10)) {
735
+ throw new TypeError(`Invalid key size for alg: ${alg}`);
736
+ }
737
+ }
738
+ async function _wrap(alg, key, cek) {
739
+ const cryptoKey = await getCryptoKey(key, alg, {
740
+ importAlg: "AES-KW",
741
+ extractable: true,
742
+ usage: "wrapKey"
743
+ });
744
+ checkKeySize(cryptoKey, alg);
745
+ const cryptoKeyCek = await crypto.subtle.importKey(
746
+ "raw",
747
+ cek,
748
+ { hash: "SHA-256", name: "HMAC" },
749
+ true,
750
+ ["sign"]
751
+ );
752
+ return new Uint8Array(
753
+ await crypto.subtle.wrapKey("raw", cryptoKeyCek, cryptoKey, "AES-KW")
754
+ );
755
+ }
756
+ async function _unwrap(alg, key, encryptedKey) {
757
+ const cryptoKey = await getCryptoKey(key, alg, {
758
+ importAlg: "AES-KW",
759
+ extractable: true,
760
+ usage: "unwrapKey"
761
+ });
762
+ checkKeySize(cryptoKey, alg);
763
+ const cryptoKeyCek = await crypto.subtle.unwrapKey(
764
+ "raw",
765
+ encryptedKey,
766
+ cryptoKey,
767
+ "AES-KW",
768
+ { hash: "SHA-256", name: "HMAC" },
769
+ true,
770
+ ["sign"]
771
+ );
772
+ return new Uint8Array(await crypto.subtle.exportKey("raw", cryptoKeyCek));
773
+ }
774
+
775
+ async function generateKey(alg, options = {}) {
776
+ const exportToJWK = options.toJWK === true;
777
+ const defaultExtractable = options.extractable !== false;
778
+ if (alg === "A128CBC-HS256" || alg === "A192CBC-HS384" || alg === "A256CBC-HS512") {
779
+ const keyLength = bitLengthCEK(alg);
780
+ const keyBytes = randomBytes(keyLength >> 3);
781
+ if (exportToJWK) {
782
+ return keyToJWK(keyBytes);
783
+ }
784
+ return keyBytes;
785
+ }
786
+ const { algorithm, keyUsages } = getGenerateKeyParams(alg, options);
787
+ const key = await crypto.subtle.generateKey(
788
+ algorithm,
789
+ defaultExtractable,
790
+ keyUsages
791
+ );
792
+ if (exportToJWK) {
793
+ if (key instanceof CryptoKey) {
794
+ return exportKey(key, { alg });
795
+ } else {
796
+ const [publicKey, privateKey] = await Promise.all([
797
+ exportKey(key.publicKey, { alg }),
798
+ exportKey(key.privateKey, { alg })
799
+ ]);
800
+ return { privateKey, publicKey };
801
+ }
802
+ }
803
+ return key;
804
+ }
805
+ async function deriveKeyFromPassword(password, alg, options) {
806
+ const { salt, iterations, toJWK, extractable, keyUsage } = options;
807
+ if (!(salt instanceof Uint8Array) || salt.length < 8) {
808
+ throw new Error("PBES2 Salt Input (salt) must be 8 or more octets");
809
+ }
810
+ if (typeof iterations !== "number" || iterations < 1) {
811
+ throw new Error(
812
+ "PBES2 Iteration Count (iterations) must be a positive integer"
813
+ );
814
+ }
815
+ const passwordBytes = typeof password === "string" ? textEncoder.encode(password) : password;
816
+ const derivedBytes = await deriveKey(
817
+ salt,
818
+ alg,
819
+ iterations,
820
+ passwordBytes
821
+ );
822
+ const wrappingAlg = alg.slice(-6);
823
+ const defaultUsages = ["wrapKey", "unwrapKey"];
824
+ const finalUsages = keyUsage ?? defaultUsages;
825
+ const finalExtractable = toJWK === true ? true : extractable === true;
826
+ const derivedKey = await crypto.subtle.importKey(
827
+ "raw",
828
+ derivedBytes,
829
+ { name: "AES-KW" },
830
+ finalExtractable,
831
+ finalUsages
832
+ );
833
+ if (toJWK === true) {
834
+ const jwk = await keyToJWK(derivedKey);
835
+ return { ...jwk, alg: wrappingAlg, kty: "oct" };
836
+ }
837
+ return derivedKey;
838
+ }
839
+ async function importKey(key, alg) {
840
+ if (typeof key === "string") {
841
+ key = textEncoder.encode(key);
842
+ }
843
+ if (key instanceof Uint8Array) {
844
+ return key;
845
+ }
846
+ if (isCryptoKey(key)) {
847
+ return key;
848
+ }
849
+ if (isJWK(key)) {
850
+ if ("k" in key && typeof key.k === "string") {
851
+ return base64UrlDecode(key.k, false);
852
+ } else {
853
+ if (!alg) {
854
+ throw new TypeError(
855
+ "Algorithm must be provided when importing non-oct JWK"
856
+ );
857
+ }
858
+ return jwkTokey({ ...key, alg });
859
+ }
860
+ }
861
+ throw new Error("Invalid key type provided to importKey");
862
+ }
863
+ async function exportKey(key, jwk) {
864
+ const exportedJwk = await keyToJWK(key);
865
+ if (jwk) {
866
+ return { ...exportedJwk, ...jwk };
867
+ }
868
+ return exportedJwk;
869
+ }
870
+ async function wrapKey(alg, keyToWrap, wrappingKey, options = {}) {
871
+ const cekBytes = keyToWrap instanceof Uint8Array ? keyToWrap : new Uint8Array(await crypto.subtle.exportKey("raw", keyToWrap));
872
+ let importedWrappingKey;
873
+ const isPbes = alg.startsWith("PBES2");
874
+ const isAesKw = ["A128KW", "A192KW", "A256KW"].includes(alg);
875
+ if (isPbes && (typeof wrappingKey === "string" || wrappingKey instanceof Uint8Array)) {
876
+ importedWrappingKey = typeof wrappingKey === "string" ? textEncoder.encode(wrappingKey) : wrappingKey;
877
+ } else if (isPbes || isAesKw) {
878
+ if (typeof wrappingKey === "string") {
879
+ throw new TypeError(
880
+ "Wrapping key must be a CryptoKey, JWK, or Uint8Array for AES-KW or non-password PBES2"
881
+ );
882
+ }
883
+ importedWrappingKey = await importKey(wrappingKey, alg);
884
+ } else {
885
+ if (typeof wrappingKey === "string") {
886
+ throw new TypeError(
887
+ "Wrapping key must be a CryptoKey, JWK, or Uint8Array for non-PBES2 algorithms"
888
+ );
889
+ }
890
+ importedWrappingKey = await importKey(wrappingKey, alg);
891
+ }
892
+ switch (alg) {
893
+ // AES Key Wrap and PBES2 are handled by the same helper
894
+ case "A128KW":
895
+ case "A192KW":
896
+ case "A256KW":
897
+ case "PBES2-HS256+A128KW":
898
+ case "PBES2-HS384+A192KW":
899
+ case "PBES2-HS512+A256KW": {
900
+ const { p2s, p2c } = options;
901
+ if (isPbes && (!p2s || typeof p2c !== "number")) {
902
+ throw new Error(
903
+ "PBES2 requires 'p2s' (salt) and 'p2c' (count) options"
904
+ );
905
+ }
906
+ return wrap(alg, importedWrappingKey, cekBytes, p2c, p2s);
907
+ }
908
+ case "A128GCMKW":
909
+ case "A192GCMKW":
910
+ case "A256GCMKW": {
911
+ const { encryptedKey, iv, tag } = await encryptIV(
912
+ alg,
913
+ importedWrappingKey,
914
+ cekBytes,
915
+ options.iv
916
+ );
917
+ return { encryptedKey, iv, tag };
918
+ }
919
+ case "RSA-OAEP":
920
+ case "RSA-OAEP-256":
921
+ case "RSA-OAEP-384":
922
+ case "RSA-OAEP-512": {
923
+ const keyToWrapImported = await crypto.subtle.importKey(
924
+ "raw",
925
+ cekBytes,
926
+ { name: "AES-GCM", length: cekBytes.length * 8 },
927
+ true,
928
+ ["encrypt", "decrypt"]
929
+ );
930
+ const encryptedKey = new Uint8Array(
931
+ await crypto.subtle.wrapKey(
932
+ "raw",
933
+ keyToWrapImported,
934
+ importedWrappingKey,
935
+ { name: "RSA-OAEP" }
936
+ )
937
+ );
938
+ return { encryptedKey };
939
+ }
940
+ case "ECDH-ES":
941
+ case "ECDH-ES+A128KW":
942
+ case "ECDH-ES+A192KW":
943
+ case "ECDH-ES+A256KW": {
944
+ throw new Error(`Algorithm ${alg} not yet implemented in wrapKey`);
945
+ }
946
+ default: {
947
+ throw new Error(`Unsupported key wrapping algorithm: ${alg}`);
948
+ }
949
+ }
950
+ }
951
+ async function unwrapKey(alg, wrappedKey, unwrappingKey, options = {}) {
952
+ const { returnAs = true } = options;
953
+ const defaultExtractable = options.extractable !== false;
954
+ let importedUnwrappingKey;
955
+ const isPbes = alg.startsWith("PBES2");
956
+ const isAesKw = ["A128KW", "A192KW", "A256KW"].includes(alg);
957
+ if (isPbes && (typeof unwrappingKey === "string" || unwrappingKey instanceof Uint8Array)) {
958
+ importedUnwrappingKey = typeof unwrappingKey === "string" ? textEncoder.encode(unwrappingKey) : unwrappingKey;
959
+ } else if (isPbes || isAesKw) {
960
+ if (typeof unwrappingKey === "string") {
961
+ throw new TypeError(
962
+ "Unwrapping key must be a CryptoKey, JWK, or Uint8Array for AES-KW or non-password PBES2"
963
+ );
964
+ }
965
+ importedUnwrappingKey = await importKey(unwrappingKey, alg);
966
+ } else {
967
+ if (typeof unwrappingKey === "string") {
968
+ throw new TypeError(
969
+ "Unwrapping key must be a CryptoKey, JWK, or Uint8Array for non-PBES2 algorithms"
970
+ );
971
+ }
972
+ importedUnwrappingKey = await importKey(unwrappingKey, alg);
973
+ }
974
+ let unwrappedCekBytes;
975
+ switch (alg) {
976
+ // AES Key Wrap and PBES2 are handled by the same helper
977
+ case "A128KW":
978
+ case "A192KW":
979
+ case "A256KW":
980
+ case "PBES2-HS256+A128KW":
981
+ case "PBES2-HS384+A192KW":
982
+ case "PBES2-HS512+A256KW": {
983
+ const { p2s, p2c } = options;
984
+ let p2sBytes;
985
+ if (isPbes) {
986
+ if (!p2s || typeof p2c !== "number") {
987
+ throw new Error(
988
+ "PBES2 requires 'p2s' (salt) and 'p2c' (count) options"
989
+ );
990
+ }
991
+ p2sBytes = typeof p2s === "string" ? base64UrlDecode(p2s, false) : p2s;
992
+ }
993
+ unwrappedCekBytes = await unwrap(
994
+ alg,
995
+ importedUnwrappingKey,
996
+ wrappedKey,
997
+ p2c,
998
+ p2sBytes
999
+ );
1000
+ break;
1001
+ }
1002
+ case "A128GCMKW":
1003
+ case "A192GCMKW":
1004
+ case "A256GCMKW": {
1005
+ if (!options.iv || !options.tag) {
1006
+ throw new Error(
1007
+ "AES-GCMKW requires 'iv' and 'tag' options for unwrapping"
1008
+ );
1009
+ }
1010
+ const ivBytes = typeof options.iv === "string" ? base64UrlDecode(options.iv, false) : options.iv;
1011
+ const tagBytes = typeof options.tag === "string" ? base64UrlDecode(options.tag, false) : options.tag;
1012
+ unwrappedCekBytes = await decryptIV(
1013
+ alg,
1014
+ importedUnwrappingKey,
1015
+ wrappedKey,
1016
+ ivBytes,
1017
+ tagBytes
1018
+ );
1019
+ break;
1020
+ }
1021
+ case "RSA-OAEP":
1022
+ case "RSA-OAEP-256":
1023
+ case "RSA-OAEP-384":
1024
+ case "RSA-OAEP-512": {
1025
+ const unwrappedKey = await crypto.subtle.unwrapKey(
1026
+ "raw",
1027
+ wrappedKey,
1028
+ importedUnwrappingKey,
1029
+ { name: "RSA-OAEP" },
1030
+ options.unwrappedKeyAlgorithm || { name: "AES-GCM" },
1031
+ // Fallback
1032
+ defaultExtractable,
1033
+ options.keyUsage || ["encrypt", "decrypt"]
1034
+ // Default usages
1035
+ );
1036
+ if (returnAs) return unwrappedKey;
1037
+ unwrappedCekBytes = new Uint8Array(
1038
+ await crypto.subtle.exportKey("raw", unwrappedKey)
1039
+ );
1040
+ break;
1041
+ }
1042
+ case "ECDH-ES":
1043
+ case "ECDH-ES+A128KW":
1044
+ case "ECDH-ES+A192KW":
1045
+ case "ECDH-ES+A256KW": {
1046
+ if (!options.epk) {
1047
+ throw new Error("ECDH-ES requires 'epk' (Ephemeral Public Key) option");
1048
+ }
1049
+ throw new Error(`Algorithm ${alg} not yet implemented in unwrapKey`);
1050
+ }
1051
+ default: {
1052
+ throw new Error(`Unsupported key unwrapping algorithm: ${alg}`);
1053
+ }
1054
+ }
1055
+ if (!returnAs) {
1056
+ return unwrappedCekBytes;
1057
+ }
1058
+ const finalKey = await crypto.subtle.importKey(
1059
+ "raw",
1060
+ unwrappedCekBytes,
1061
+ options.unwrappedKeyAlgorithm || { name: "AES-GCM" },
1062
+ defaultExtractable,
1063
+ options.keyUsage || ["encrypt", "decrypt"]
1064
+ );
1065
+ return finalKey;
1066
+ }
1067
+ function getGenerateKeyParams(alg, options) {
1068
+ let algorithm;
1069
+ let keyUsages;
1070
+ const defaultKeyUsage = options?.keyUsage;
1071
+ switch (alg) {
1072
+ // HMAC Signatures
1073
+ case "HS256":
1074
+ case "HS384":
1075
+ case "HS512": {
1076
+ algorithm = {
1077
+ name: "HMAC",
1078
+ hash: `SHA-${alg.slice(2)}`
1079
+ };
1080
+ keyUsages = defaultKeyUsage ?? ["sign", "verify"];
1081
+ break;
1082
+ }
1083
+ // RSA Signatures
1084
+ case "RS256":
1085
+ case "RS384":
1086
+ case "RS512": {
1087
+ algorithm = {
1088
+ name: "RSASSA-PKCS1-v1_5",
1089
+ modulusLength: options?.modulusLength ?? 2048,
1090
+ publicExponent: options?.publicExponent ?? new Uint8Array([1, 0, 1]),
1091
+ hash: `SHA-${alg.slice(2)}`
1092
+ };
1093
+ keyUsages = defaultKeyUsage ?? ["sign", "verify"];
1094
+ break;
1095
+ }
1096
+ // RSA PSS Signatures
1097
+ case "PS256":
1098
+ case "PS384":
1099
+ case "PS512": {
1100
+ algorithm = {
1101
+ name: "RSA-PSS",
1102
+ modulusLength: options?.modulusLength ?? 2048,
1103
+ publicExponent: options?.publicExponent ?? new Uint8Array([1, 0, 1]),
1104
+ hash: `SHA-${alg.slice(2)}`
1105
+ };
1106
+ keyUsages = defaultKeyUsage ?? ["sign", "verify"];
1107
+ break;
1108
+ }
1109
+ // ECDSA Signatures
1110
+ case "ES256": {
1111
+ algorithm = { name: "ECDSA", namedCurve: "P-256" };
1112
+ keyUsages = defaultKeyUsage ?? ["sign", "verify"];
1113
+ break;
1114
+ }
1115
+ case "ES384": {
1116
+ algorithm = { name: "ECDSA", namedCurve: "P-384" };
1117
+ keyUsages = defaultKeyUsage ?? ["sign", "verify"];
1118
+ break;
1119
+ }
1120
+ case "ES512": {
1121
+ algorithm = { name: "ECDSA", namedCurve: "P-521" };
1122
+ keyUsages = defaultKeyUsage ?? ["sign", "verify"];
1123
+ break;
1124
+ }
1125
+ // EdDSA Signatures should be imported
1126
+ // RSA Encryption
1127
+ case "RSA-OAEP":
1128
+ case "RSA-OAEP-256":
1129
+ case "RSA-OAEP-384":
1130
+ case "RSA-OAEP-512": {
1131
+ algorithm = {
1132
+ name: "RSA-OAEP",
1133
+ modulusLength: options?.modulusLength ?? 2048,
1134
+ publicExponent: options?.publicExponent ?? new Uint8Array([1, 0, 1]),
1135
+ hash: `SHA-${Number.parseInt(alg.slice(9), 10) || 1}`
1136
+ };
1137
+ keyUsages = defaultKeyUsage ?? [
1138
+ "encrypt",
1139
+ "decrypt",
1140
+ "wrapKey",
1141
+ "unwrapKey"
1142
+ ];
1143
+ break;
1144
+ }
1145
+ // AES Key Wrap
1146
+ case "A128KW":
1147
+ case "A192KW":
1148
+ case "A256KW": {
1149
+ const length = Number.parseInt(alg.slice(1, 4), 10);
1150
+ algorithm = { name: "AES-KW", length };
1151
+ keyUsages = defaultKeyUsage ?? ["wrapKey", "unwrapKey"];
1152
+ break;
1153
+ }
1154
+ // AES GCM Encryption
1155
+ case "A128GCM":
1156
+ case "A192GCM":
1157
+ case "A256GCM": {
1158
+ const length = Number.parseInt(alg.slice(1, 4), 10);
1159
+ algorithm = { name: "AES-GCM", length };
1160
+ keyUsages = defaultKeyUsage ?? ["encrypt", "decrypt"];
1161
+ break;
1162
+ }
1163
+ // ECDH Key Agreement (requires specific curve in JWK for import, generation is simpler)
1164
+ // For generation, typically generate the EC key pair first (e.g., P-256, P-384, P-521, X25519)
1165
+ // then use deriveBits/deriveKey. Direct generation for "ECDH-ES*" alg isn't standard.
1166
+ // Handle EC key pair generation under ES256/ES384/ES512.
1167
+ default: {
1168
+ throw new Error(
1169
+ `Unsupported or invalid algorithm for key generation: ${alg}`
1170
+ );
1171
+ }
1172
+ }
1173
+ return { algorithm, keyUsages };
1174
+ }
1175
+
1176
+ const jwk = {
1177
+ __proto__: null,
1178
+ deriveKeyFromPassword: deriveKeyFromPassword,
1179
+ exportKey: exportKey,
1180
+ generateKey: generateKey,
1181
+ importKey: importKey,
1182
+ unwrapKey: unwrapKey,
1183
+ wrapKey: wrapKey
1184
+ };
1185
+
1186
+ export { checkEncCryptoKey as a, bitLengthCEK as b, checkSigCryptoKey as c, jwkTokey as d, encryptIV as e, generateIV as f, generateCEK as g, encrypt as h, importKey as i, jwk as j, keyToJWK as k, unwrapKey as l, decrypt as m, generateKey as n, deriveKeyFromPassword as o, exportKey as p, wrapKey as q, uint32be as u, wrap as w };