unjwt 0.5.38 → 0.5.39

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 (41) hide show
  1. package/README.md +142 -666
  2. package/dist/_chunks/chunk.mjs +13 -0
  3. package/dist/_chunks/h3v1.mjs +598 -0
  4. package/dist/_chunks/index.d.mts +250 -0
  5. package/dist/_chunks/index2.d.mts +108 -0
  6. package/dist/_chunks/jwe.d.mts +43 -0
  7. package/dist/_chunks/jwe.mjs +132 -0
  8. package/dist/_chunks/jwk.d.mts +575 -0
  9. package/dist/_chunks/jwk.mjs +1592 -0
  10. package/dist/_chunks/jws.d.mts +46 -0
  11. package/dist/_chunks/jws.mjs +2069 -0
  12. package/dist/_chunks/utils.mjs +374 -0
  13. package/dist/adapters/h3.d.mts +3 -267
  14. package/dist/adapters/h3.mjs +3 -704
  15. package/dist/adapters/h3v1.d.mts +3 -8
  16. package/dist/adapters/h3v1.mjs +3 -7
  17. package/dist/adapters/h3v2.d.mts +145 -146
  18. package/dist/adapters/h3v2.mjs +505 -594
  19. package/dist/index.d.mts +6 -8
  20. package/dist/index.mjs +5 -4
  21. package/dist/jwe.d.mts +3 -4
  22. package/dist/jwe.mjs +4 -3
  23. package/dist/jwk.d.mts +3 -2
  24. package/dist/jwk.mjs +3 -2
  25. package/dist/jws.d.mts +3 -3
  26. package/dist/jws.mjs +4 -3
  27. package/dist/utils.d.mts +3 -3
  28. package/dist/utils.mjs +2 -1
  29. package/package.json +33 -31
  30. package/dist/shared/unjwt.4JQCoID_.d.mts +0 -161
  31. package/dist/shared/unjwt.B-v62plj.mjs +0 -249
  32. package/dist/shared/unjwt.BCi3FEWr.d.mts +0 -328
  33. package/dist/shared/unjwt.BYDTEWa-.d.mts +0 -269
  34. package/dist/shared/unjwt.Be8NxwFK.mjs +0 -438
  35. package/dist/shared/unjwt.BqdNUKDr.d.mts +0 -64
  36. package/dist/shared/unjwt.CMNtw8ek.d.mts +0 -155
  37. package/dist/shared/unjwt.Cy2MlkUe.d.mts +0 -174
  38. package/dist/shared/unjwt.D0_ccT7g.d.mts +0 -166
  39. package/dist/shared/unjwt.DdLN9vwI.mjs +0 -163
  40. package/dist/shared/unjwt.Dpl__ZAR.mjs +0 -2121
  41. package/dist/shared/unjwt.JdKqVANs.d.mts +0 -5
@@ -1,2121 +0,0 @@
1
- import { k as isCryptoKey, x as concatUint8Arrays, d as base64UrlEncode, y as base64Decode, z as base64Encode, t as textEncoder, s as sanitizeObject, A as assertCryptoKey, a as isJWK, e as base64UrlDecode, B as isAsymmetricJWK, r as randomBytes, m as isJWKSet } from './unjwt.Be8NxwFK.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$1(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$1(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 or Uint8Array`
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 or Uint8Array`
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, plaintext, iv) {
501
- const jweAlgorithm = alg.slice(0, 7);
502
- const wrapped = await encrypt(
503
- jweAlgorithm,
504
- plaintext,
505
- key,
506
- iv,
507
- new Uint8Array(0)
508
- );
509
- return {
510
- encryptedKey: wrapped.ciphertext,
511
- iv: base64UrlEncode(wrapped.iv),
512
- tag: base64UrlEncode(wrapped.tag)
513
- };
514
- }
515
- async function decryptIV(alg, key, ciphertext, iv, tag) {
516
- const jweAlgorithm = alg.slice(0, 7);
517
- return decrypt(jweAlgorithm, key, ciphertext, iv, tag, new Uint8Array(0));
518
- }
519
-
520
- /**
521
- * This is a fork of Jose library's utility functions.
522
- * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/asn1.ts
523
- * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
524
- */
525
- const formatPEM = (b64, descriptor) => {
526
- const newlined = (b64.match(/.{1,64}/g) || []).join("\n");
527
- return `-----BEGIN ${descriptor}-----
528
- ${newlined}
529
- -----END ${descriptor}-----`;
530
- };
531
- const genericExport = async (keyType, keyFormat, key) => {
532
- if (!isCryptoKey(key)) {
533
- throw new TypeError(`Key must be ${key} of type CryptoKey`);
534
- }
535
- if (!key.extractable) {
536
- throw new TypeError("CryptoKey is not extractable");
537
- }
538
- if (key.type !== keyType) {
539
- throw new TypeError(`key is not a ${keyType} key`);
540
- }
541
- return formatPEM(
542
- base64Encode(new Uint8Array(await crypto.subtle.exportKey(keyFormat, key))),
543
- `${keyType.toUpperCase()} KEY`
544
- );
545
- };
546
- const toSPKI = (key) => {
547
- return genericExport("public", "spki", key);
548
- };
549
- const toPKCS8 = (key) => {
550
- return genericExport("private", "pkcs8", key);
551
- };
552
- const findOid = (keyData, oid, from = 0) => {
553
- if (from === 0) {
554
- oid.unshift(oid.length);
555
- oid.unshift(6);
556
- }
557
- const i = keyData.indexOf(oid[0], from);
558
- if (i === -1) return false;
559
- const sub = keyData.subarray(i, i + oid.length);
560
- if (sub.length !== oid.length) return false;
561
- return sub.every((value, index) => value === oid[index]) || findOid(keyData, oid, i + 1);
562
- };
563
- const getNamedCurve = (keyData) => {
564
- switch (true) {
565
- case findOid(keyData, [42, 134, 72, 206, 61, 3, 1, 7]): {
566
- return "P-256";
567
- }
568
- case findOid(keyData, [43, 129, 4, 0, 34]): {
569
- return "P-384";
570
- }
571
- case findOid(keyData, [43, 129, 4, 0, 35]): {
572
- return "P-521";
573
- }
574
- default: {
575
- return void 0;
576
- }
577
- }
578
- };
579
- const genericImport = async (replace, keyFormat, pem, alg, options) => {
580
- let algorithm;
581
- let keyUsages;
582
- const cleanedPem = pem.replace(replace, "");
583
- const keyData = base64Decode(cleanedPem, false);
584
- const isPublic = keyFormat === "spki";
585
- switch (alg) {
586
- case "PS256":
587
- case "PS384":
588
- case "PS512": {
589
- algorithm = { name: "RSA-PSS", hash: `SHA-${alg.slice(-3)}` };
590
- keyUsages = isPublic ? ["verify"] : ["sign"];
591
- break;
592
- }
593
- case "RS256":
594
- case "RS384":
595
- case "RS512": {
596
- algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${alg.slice(-3)}` };
597
- keyUsages = isPublic ? ["verify"] : ["sign"];
598
- break;
599
- }
600
- case "RSA-OAEP":
601
- case "RSA-OAEP-256":
602
- case "RSA-OAEP-384":
603
- case "RSA-OAEP-512": {
604
- algorithm = {
605
- name: "RSA-OAEP",
606
- hash: `SHA-${Number.parseInt(alg.slice(-3), 10) || 1}`
607
- };
608
- keyUsages = isPublic ? ["encrypt", "wrapKey"] : ["decrypt", "unwrapKey"];
609
- break;
610
- }
611
- case "ES256": {
612
- algorithm = { name: "ECDSA", namedCurve: "P-256" };
613
- keyUsages = isPublic ? ["verify"] : ["sign"];
614
- break;
615
- }
616
- case "ES384": {
617
- algorithm = { name: "ECDSA", namedCurve: "P-384" };
618
- keyUsages = isPublic ? ["verify"] : ["sign"];
619
- break;
620
- }
621
- case "ES512": {
622
- algorithm = { name: "ECDSA", namedCurve: "P-521" };
623
- keyUsages = isPublic ? ["verify"] : ["sign"];
624
- break;
625
- }
626
- case "ECDH-ES":
627
- case "ECDH-ES+A128KW":
628
- case "ECDH-ES+A192KW":
629
- case "ECDH-ES+A256KW": {
630
- const namedCurve = getNamedCurve(keyData);
631
- algorithm = namedCurve?.startsWith("P-") ? { name: "ECDH", namedCurve } : { name: "X25519" };
632
- keyUsages = isPublic ? [] : ["deriveBits"];
633
- break;
634
- }
635
- case "Ed25519":
636
- case "EdDSA": {
637
- algorithm = { name: "Ed25519" };
638
- keyUsages = isPublic ? ["verify"] : ["sign"];
639
- break;
640
- }
641
- default: {
642
- throw new Error('Invalid or unsupported "alg" (Algorithm) value');
643
- }
644
- }
645
- return crypto.subtle.importKey(
646
- keyFormat,
647
- keyData,
648
- algorithm,
649
- options?.extractable ?? (isPublic ? true : false),
650
- keyUsages
651
- );
652
- };
653
- const fromPKCS8 = (pem, alg, options) => {
654
- return genericImport(
655
- /(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g,
656
- "pkcs8",
657
- pem,
658
- alg,
659
- options
660
- );
661
- };
662
- const fromSPKI = (pem, alg, options) => {
663
- return genericImport(
664
- /(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g,
665
- "spki",
666
- pem,
667
- alg,
668
- options
669
- );
670
- };
671
- function getElement(seq) {
672
- const result = [];
673
- let next = 0;
674
- while (next < seq.length) {
675
- const nextPart = parseElement(seq.subarray(next));
676
- result.push(nextPart);
677
- next += nextPart.byteLength;
678
- }
679
- return result;
680
- }
681
- function parseElement(bytes) {
682
- let position = 0;
683
- let tag = bytes[0] & 31;
684
- position++;
685
- if (tag === 31) {
686
- tag = 0;
687
- while (bytes[position] >= 128) {
688
- tag = tag * 128 + bytes[position] - 128;
689
- position++;
690
- }
691
- tag = tag * 128 + bytes[position] - 128;
692
- position++;
693
- }
694
- let length = 0;
695
- if (bytes[position] < 128) {
696
- length = bytes[position];
697
- position++;
698
- } else if (length === 128) {
699
- length = 0;
700
- while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) {
701
- if (length > bytes.byteLength) {
702
- throw new TypeError("invalid indefinite form length");
703
- }
704
- length++;
705
- }
706
- const byteLength2 = position + length + 2;
707
- return {
708
- byteLength: byteLength2,
709
- contents: bytes.subarray(position, position + length),
710
- raw: bytes.subarray(0, byteLength2)
711
- };
712
- } else {
713
- const numberOfDigits = bytes[position] & 127;
714
- position++;
715
- length = 0;
716
- for (let i = 0; i < numberOfDigits; i++) {
717
- length = length * 256 + bytes[position];
718
- position++;
719
- }
720
- }
721
- const byteLength = position + length;
722
- return {
723
- byteLength,
724
- contents: bytes.subarray(position, byteLength),
725
- raw: bytes.subarray(0, byteLength)
726
- };
727
- }
728
- function spkiFromX509(buf) {
729
- const tbsCertificate = getElement(
730
- getElement(parseElement(buf).contents)[0].contents
731
- );
732
- return base64Encode(
733
- tbsCertificate[tbsCertificate[0].raw[0] === 160 ? 6 : 5].raw
734
- );
735
- }
736
- let createPublicKey;
737
- function getSPKI(x509) {
738
- try {
739
- createPublicKey ??= globalThis.process?.getBuiltinModule?.("node:crypto")?.createPublicKey;
740
- } catch {
741
- createPublicKey = 0;
742
- }
743
- if (createPublicKey) {
744
- try {
745
- return new createPublicKey(x509).export({ format: "pem", type: "spki" });
746
- } catch {
747
- }
748
- }
749
- const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, "");
750
- const raw = base64Decode(pem, false);
751
- return formatPEM(spkiFromX509(raw), "PUBLIC KEY");
752
- }
753
- const fromX509 = (pem, alg, options) => {
754
- let spki;
755
- try {
756
- spki = getSPKI(pem);
757
- } catch (error_) {
758
- throw new TypeError("Failed to parse the X.509 certificate", {
759
- cause: error_
760
- });
761
- }
762
- return fromSPKI(spki, alg, options);
763
- };
764
-
765
- function lengthAndInput(input) {
766
- return concatUint8Arrays(uint32be(input.length), input);
767
- }
768
- async function concatKdf(secret, bits, value) {
769
- const iterations = Math.ceil((bits >> 3) / 32);
770
- const res = new Uint8Array(iterations * 32);
771
- for (let iter = 0; iter < iterations; iter++) {
772
- const buf = new Uint8Array(4 + secret.length + value.length);
773
- buf.set(uint32be(iter + 1));
774
- buf.set(secret, 4);
775
- buf.set(value, 4 + secret.length);
776
- res.set(await digest("sha256", buf), iter * 32);
777
- }
778
- return res.slice(0, bits >> 3);
779
- }
780
- async function deriveECDHESKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) {
781
- checkEncCryptoKey(publicKey, "ECDH");
782
- checkEncCryptoKey(privateKey, "ECDH", "deriveBits");
783
- const value = concatUint8Arrays(
784
- lengthAndInput(textEncoder.encode(algorithm)),
785
- lengthAndInput(apu),
786
- lengthAndInput(apv),
787
- uint32be(keyLength)
788
- );
789
- const length = publicKey.algorithm.name === "X25519" ? 256 : Math.ceil(
790
- Number.parseInt(
791
- publicKey.algorithm.namedCurve.slice(-3),
792
- 10
793
- ) / 8
794
- ) << 3;
795
- const sharedSecret = new Uint8Array(
796
- await crypto.subtle.deriveBits(
797
- {
798
- name: publicKey.algorithm.name,
799
- public: publicKey
800
- },
801
- privateKey,
802
- length
803
- )
804
- );
805
- return concatKdf(sharedSecret, keyLength, value);
806
- }
807
- function allowed(key) {
808
- switch (key.algorithm.namedCurve) {
809
- case "P-256":
810
- case "P-384":
811
- case "P-521": {
812
- return true;
813
- }
814
- default: {
815
- return key.algorithm.name === "X25519";
816
- }
817
- }
818
- }
819
- async function digest(algorithm, data) {
820
- const subtleDigest = `SHA-${algorithm.slice(-3)}`;
821
- return new Uint8Array(await crypto.subtle.digest(subtleDigest, data));
822
- }
823
-
824
- /**
825
- * This is a fork of Jose library's utility functions.
826
- * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/jwt_to_key.ts
827
- * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
828
- */
829
- function subtleMapping(jwk) {
830
- let algorithm;
831
- let keyUsages;
832
- switch (jwk.kty) {
833
- case "RSA": {
834
- switch (jwk.alg) {
835
- case "PS256":
836
- case "PS384":
837
- case "PS512": {
838
- algorithm = { name: "RSA-PSS", hash: `SHA-${jwk.alg.slice(-3)}` };
839
- keyUsages = jwk.d ? ["sign"] : ["verify"];
840
- break;
841
- }
842
- case "RS256":
843
- case "RS384":
844
- case "RS512": {
845
- algorithm = {
846
- name: "RSASSA-PKCS1-v1_5",
847
- hash: `SHA-${jwk.alg.slice(-3)}`
848
- };
849
- keyUsages = jwk.d ? ["sign"] : ["verify"];
850
- break;
851
- }
852
- case "RSA-OAEP":
853
- case "RSA-OAEP-256":
854
- case "RSA-OAEP-384":
855
- case "RSA-OAEP-512": {
856
- algorithm = {
857
- name: "RSA-OAEP",
858
- hash: `SHA-${Number.parseInt(jwk.alg.slice(-3), 10) || 1}`
859
- };
860
- keyUsages = jwk.d ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"];
861
- break;
862
- }
863
- default: {
864
- throw new Error(
865
- 'Invalid or unsupported JWK "alg" (Algorithm) Parameter value'
866
- );
867
- }
868
- }
869
- break;
870
- }
871
- case "EC": {
872
- switch (jwk.alg) {
873
- case "ES256": {
874
- algorithm = { name: "ECDSA", namedCurve: "P-256" };
875
- keyUsages = jwk.d ? ["sign"] : ["verify"];
876
- break;
877
- }
878
- case "ES384": {
879
- algorithm = { name: "ECDSA", namedCurve: "P-384" };
880
- keyUsages = jwk.d ? ["sign"] : ["verify"];
881
- break;
882
- }
883
- case "ES512": {
884
- algorithm = { name: "ECDSA", namedCurve: "P-521" };
885
- keyUsages = jwk.d ? ["sign"] : ["verify"];
886
- break;
887
- }
888
- case "ECDH-ES":
889
- case "ECDH-ES+A128KW":
890
- case "ECDH-ES+A192KW":
891
- case "ECDH-ES+A256KW": {
892
- algorithm = {
893
- name: "ECDH",
894
- namedCurve: jwk.crv
895
- };
896
- keyUsages = jwk.d ? ["deriveBits"] : [];
897
- break;
898
- }
899
- default: {
900
- throw new Error(
901
- 'Invalid or unsupported JWK "alg" (Algorithm) Parameter value'
902
- );
903
- }
904
- }
905
- break;
906
- }
907
- case "OKP": {
908
- switch (jwk.alg) {
909
- case "Ed25519":
910
- // Fall through
911
- case "EdDSA": {
912
- algorithm = { name: "Ed25519" };
913
- keyUsages = jwk.d ? ["sign"] : ["verify"];
914
- break;
915
- }
916
- case "ECDH-ES":
917
- case "ECDH-ES+A128KW":
918
- case "ECDH-ES+A192KW":
919
- case "ECDH-ES+A256KW": {
920
- algorithm = { name: jwk.crv };
921
- keyUsages = jwk.d ? ["deriveBits"] : [];
922
- break;
923
- }
924
- default: {
925
- throw new Error(
926
- 'Invalid or unsupported JWK "alg" (Algorithm) Parameter value'
927
- );
928
- }
929
- }
930
- break;
931
- }
932
- default: {
933
- throw new Error(
934
- 'Invalid or unsupported JWK "kty" (Key Type) Parameter value'
935
- );
936
- }
937
- }
938
- return { algorithm, keyUsages };
939
- }
940
- async function jwkTokey(jwk) {
941
- if (!jwk.alg) {
942
- throw new TypeError(
943
- '"alg" argument is required when "jwk.alg" is not present'
944
- );
945
- }
946
- const { algorithm, keyUsages } = subtleMapping(jwk);
947
- const keyData = { ...sanitizeObject(jwk) };
948
- delete keyData.alg;
949
- delete keyData.use;
950
- return crypto.subtle.importKey(
951
- "jwk",
952
- keyData,
953
- algorithm,
954
- jwk.ext ?? (jwk.d ? false : true),
955
- jwk.key_ops ?? keyUsages
956
- );
957
- }
958
-
959
- /**
960
- * This is a fork of Jose library's utility functions.
961
- * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/key_to_jwt.ts
962
- * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
963
- */
964
- async function keyToJWK(key) {
965
- if (key instanceof Uint8Array) {
966
- return {
967
- kty: "oct",
968
- k: base64UrlEncode(key)
969
- };
970
- }
971
- if (!isCryptoKey(key)) {
972
- throw new TypeError(
973
- `Key must be ${key} one of type: CryptoKey, or Uint8Array`
974
- );
975
- }
976
- if (!key.extractable) {
977
- throw new TypeError(
978
- "non-extractable CryptoKey cannot be exported as a JWK"
979
- );
980
- }
981
- const jwk = await crypto.subtle.exportKey("jwk", key);
982
- return jwk;
983
- }
984
-
985
- /**
986
- * This is a fork of Jose library's utility functions.
987
- * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/sign.ts
988
- * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/verify.ts
989
- * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
990
- */
991
- async function sign(alg, key, data) {
992
- const cryptoKey = await getSignVerifyKey(alg, key, "sign");
993
- checkKeyLength(alg, cryptoKey);
994
- const signature = await crypto.subtle.sign(
995
- subtleAlgorithm$1(alg, cryptoKey.algorithm),
996
- cryptoKey,
997
- data
998
- );
999
- return new Uint8Array(signature);
1000
- }
1001
- async function verify(alg, key, signature, data) {
1002
- const cryptoKey = await getSignVerifyKey(alg, key, "verify");
1003
- checkKeyLength(alg, cryptoKey);
1004
- const algorithm = subtleAlgorithm$1(alg, cryptoKey.algorithm);
1005
- try {
1006
- return await crypto.subtle.verify(algorithm, cryptoKey, signature, data);
1007
- } catch {
1008
- return false;
1009
- }
1010
- }
1011
- function checkKeyLength(alg, key) {
1012
- if (alg.startsWith("RS") || alg.startsWith("PS")) {
1013
- const { modulusLength } = key.algorithm;
1014
- if (typeof modulusLength !== "number" || modulusLength < 2048) {
1015
- throw new TypeError(
1016
- `${alg} requires key modulusLength to be 2048 bits or larger`
1017
- );
1018
- }
1019
- }
1020
- }
1021
- async function getSignVerifyKey(alg, key, usage) {
1022
- if (key instanceof Uint8Array) {
1023
- if (!alg.startsWith("HS")) {
1024
- throw new TypeError(
1025
- `Key must be ${key} of type: CryptoKey or JSON Web Key`
1026
- );
1027
- }
1028
- return crypto.subtle.importKey(
1029
- "raw",
1030
- key,
1031
- { hash: `SHA-${alg.slice(-3)}`, name: "HMAC" },
1032
- false,
1033
- [usage]
1034
- );
1035
- }
1036
- checkSigCryptoKey(key, alg, usage);
1037
- return key;
1038
- }
1039
- function subtleAlgorithm$1(alg, algorithm) {
1040
- const hash = `SHA-${alg.slice(-3)}`;
1041
- switch (alg) {
1042
- case "HS256":
1043
- case "HS384":
1044
- case "HS512": {
1045
- return { hash, name: "HMAC" };
1046
- }
1047
- case "PS256":
1048
- case "PS384":
1049
- case "PS512": {
1050
- return {
1051
- hash,
1052
- name: "RSA-PSS",
1053
- saltLength: Number.parseInt(alg.slice(-3), 10) >> 3
1054
- };
1055
- }
1056
- case "RS256":
1057
- case "RS384":
1058
- case "RS512": {
1059
- return { hash, name: "RSASSA-PKCS1-v1_5" };
1060
- }
1061
- case "ES256":
1062
- case "ES384":
1063
- case "ES512": {
1064
- return {
1065
- hash,
1066
- name: "ECDSA",
1067
- namedCurve: algorithm.namedCurve
1068
- };
1069
- }
1070
- case "Ed25519":
1071
- // Fall through
1072
- case "EdDSA": {
1073
- return { name: "Ed25519" };
1074
- }
1075
- default: {
1076
- throw new Error(
1077
- `alg ${alg} is not supported either by JOSE or your javascript runtime`
1078
- );
1079
- }
1080
- }
1081
- }
1082
-
1083
- const subtleAlgorithm = (alg) => {
1084
- switch (alg) {
1085
- case "RSA-OAEP":
1086
- case "RSA-OAEP-256":
1087
- case "RSA-OAEP-384":
1088
- case "RSA-OAEP-512": {
1089
- return "RSA-OAEP";
1090
- }
1091
- default: {
1092
- throw new Error(
1093
- `alg ${alg} is not supported either by JOSE or your javascript runtime`
1094
- );
1095
- }
1096
- }
1097
- };
1098
- async function encryptRSAES(alg, key, cek) {
1099
- checkEncCryptoKey(key, alg, "encrypt");
1100
- checkKeyLength(alg, key);
1101
- return new Uint8Array(
1102
- await crypto.subtle.encrypt(subtleAlgorithm(alg), key, cek)
1103
- );
1104
- }
1105
- async function decryptRSAES(alg, key, encryptedKey) {
1106
- checkEncCryptoKey(key, alg, "decrypt");
1107
- checkKeyLength(alg, key);
1108
- return new Uint8Array(
1109
- await crypto.subtle.decrypt(subtleAlgorithm(alg), key, encryptedKey)
1110
- );
1111
- }
1112
-
1113
- /**
1114
- * This is a fork of Jose library's utility functions.
1115
- * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/pbes2kw.ts
1116
- * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
1117
- */
1118
- async function wrap(alg, key, cek, p2c, p2s) {
1119
- if (p2c && p2s) {
1120
- const derived = await deriveKey(p2s, alg, p2c, key);
1121
- const encryptedKey = await _wrap(alg.slice(-6), derived, cek);
1122
- return { encryptedKey, p2c, p2s: base64UrlEncode(p2s) };
1123
- } else {
1124
- const encryptedKey = await _wrap(alg, key, cek);
1125
- return { encryptedKey };
1126
- }
1127
- }
1128
- async function unwrap(alg, key, encryptedKey, p2c, p2s) {
1129
- if (p2c && p2s) {
1130
- const derived = await deriveKey(p2s, alg, p2c, key);
1131
- return _unwrap(alg.slice(-6), derived, encryptedKey);
1132
- } else {
1133
- return _unwrap(alg, key, encryptedKey);
1134
- }
1135
- }
1136
- function getCryptoKey(key, alg, options = {}) {
1137
- const {
1138
- importAlg = "PBKDF2",
1139
- extractable = false,
1140
- usage = "deriveBits"
1141
- } = options;
1142
- if (key instanceof Uint8Array) {
1143
- return crypto.subtle.importKey("raw", key, importAlg, extractable, [usage]);
1144
- }
1145
- checkEncCryptoKey(key, alg, usage);
1146
- return key;
1147
- }
1148
- async function deriveKey(p2s, alg, p2c, key) {
1149
- if (!(p2s instanceof Uint8Array) || p2s.length < 8) {
1150
- throw new Error("PBES2 Salt Input must be 8 or more octets");
1151
- }
1152
- if (p2c === void 0 || p2c < 1) {
1153
- throw new Error(
1154
- "PBES2 Iteration Count Parameter must be a positive integer"
1155
- );
1156
- }
1157
- const salt = concatUint8Arrays(
1158
- textEncoder.encode(alg),
1159
- new Uint8Array([0]),
1160
- p2s
1161
- );
1162
- const keylen = Number.parseInt(alg.slice(13, 16), 10);
1163
- const subtleAlg = {
1164
- hash: `SHA-${alg.slice(8, 11)}`,
1165
- iterations: p2c,
1166
- name: "PBKDF2",
1167
- salt
1168
- };
1169
- const cryptoKey = await getCryptoKey(key, alg);
1170
- return new Uint8Array(
1171
- await crypto.subtle.deriveBits(subtleAlg, cryptoKey, keylen)
1172
- );
1173
- }
1174
- function checkKeySize(key, alg) {
1175
- if (key.algorithm.length !== Number.parseInt(alg.slice(1, 4), 10)) {
1176
- throw new TypeError(`Invalid key size for alg: ${alg}`);
1177
- }
1178
- }
1179
- async function _wrap(alg, key, cek) {
1180
- const cryptoKey = await getCryptoKey(key, alg, {
1181
- importAlg: "AES-KW",
1182
- extractable: true,
1183
- usage: "wrapKey"
1184
- });
1185
- checkKeySize(cryptoKey, alg);
1186
- const cryptoKeyCek = await crypto.subtle.importKey(
1187
- "raw",
1188
- cek,
1189
- { hash: "SHA-256", name: "HMAC" },
1190
- true,
1191
- ["sign"]
1192
- );
1193
- return new Uint8Array(
1194
- await crypto.subtle.wrapKey("raw", cryptoKeyCek, cryptoKey, "AES-KW")
1195
- );
1196
- }
1197
- async function _unwrap(alg, key, encryptedKey) {
1198
- const cryptoKey = await getCryptoKey(key, alg, {
1199
- importAlg: "AES-KW",
1200
- extractable: true,
1201
- usage: "unwrapKey"
1202
- });
1203
- checkKeySize(cryptoKey, alg);
1204
- const cryptoKeyCek = await crypto.subtle.unwrapKey(
1205
- "raw",
1206
- encryptedKey,
1207
- cryptoKey,
1208
- "AES-KW",
1209
- { hash: "SHA-256", name: "HMAC" },
1210
- true,
1211
- ["sign"]
1212
- );
1213
- return new Uint8Array(await crypto.subtle.exportKey("raw", cryptoKeyCek));
1214
- }
1215
-
1216
- /**
1217
- * This is a fork of Jose library's utility functions.
1218
- * @source https://github.com/panva/jose/tree/69b7960c67e05be55fa2ec31c74b987696c20c60/src/lib/encrypt_key_management.ts
1219
- * @license MIT https://github.com/panva/jose/blob/69b7960c67e05be55fa2ec31c74b987696c20c60/LICENSE.md
1220
- */
1221
- const PUBLIC_EPK_FIELDS = /* @__PURE__ */ new Set([
1222
- "kty",
1223
- "crv",
1224
- "x",
1225
- "y",
1226
- "kid",
1227
- "use",
1228
- "key_ops",
1229
- "alg",
1230
- "x5c",
1231
- "x5t",
1232
- "x5t#S256",
1233
- "x5u"
1234
- ]);
1235
- function toPublicEpkJwk(jwk) {
1236
- const filtered = {};
1237
- for (const [key, value] of Object.entries(jwk)) {
1238
- if (value !== void 0 && PUBLIC_EPK_FIELDS.has(key)) {
1239
- filtered[key] = value;
1240
- }
1241
- }
1242
- const { kty, crv, x, y } = filtered;
1243
- if (typeof kty !== "string") {
1244
- throw new TypeError(
1245
- 'ECDH-ES ephemeral key JWK must include the "kty" parameter.'
1246
- );
1247
- }
1248
- if (typeof crv !== "string") {
1249
- throw new TypeError(
1250
- 'ECDH-ES ephemeral key JWK must include the "crv" parameter.'
1251
- );
1252
- }
1253
- if (typeof x !== "string") {
1254
- throw new TypeError(
1255
- 'ECDH-ES ephemeral key JWK must include the "x" coordinate.'
1256
- );
1257
- }
1258
- if (kty === "EC" && typeof y !== "string") {
1259
- throw new TypeError(
1260
- 'ECDH-ES EC ephemeral key JWK must include both "x" and "y" coordinates.'
1261
- );
1262
- }
1263
- const publicJwk = {
1264
- ...filtered,
1265
- kty,
1266
- crv,
1267
- x
1268
- };
1269
- if (typeof y === "string") {
1270
- publicJwk.y = y;
1271
- } else {
1272
- delete publicJwk.y;
1273
- }
1274
- return sanitizeObject(publicJwk);
1275
- }
1276
- async function ensurePrivateKey(alg, value) {
1277
- const normalized = await normalizeKey(value, alg);
1278
- if (!(normalized instanceof CryptoKey)) {
1279
- throw new TypeError(
1280
- "ECDH-ES ephemeral private key must be a CryptoKey or convertible JWK."
1281
- );
1282
- }
1283
- if (normalized.type !== "private") {
1284
- throw new TypeError(
1285
- 'ECDH-ES ephemeral private key must have type "private".'
1286
- );
1287
- }
1288
- return normalized;
1289
- }
1290
- async function exportPublicJwkFrom(alg, value) {
1291
- if (isCryptoKey(value)) {
1292
- try {
1293
- return toPublicEpkJwk(await keyToJWK(value));
1294
- } catch (error_) {
1295
- throw new TypeError(
1296
- "ECDH-ES ephemeral CryptoKey must be extractable to export as JWK.",
1297
- { cause: error_ instanceof Error ? error_ : void 0 }
1298
- );
1299
- }
1300
- }
1301
- if (isJWK(value) && isAsymmetricJWK(value) && value.kty === "EC") {
1302
- return toPublicEpkJwk(value);
1303
- }
1304
- const normalized = await normalizeKey(value, alg);
1305
- if (!(normalized instanceof CryptoKey)) {
1306
- throw new TypeError(
1307
- "ECDH-ES ephemeral public key must be a CryptoKey or convertible JWK."
1308
- );
1309
- }
1310
- return exportPublicJwkFrom(alg, normalized);
1311
- }
1312
- async function encryptKey(alg, enc, key, providedCek, providedParameters = {}) {
1313
- let encryptedKey;
1314
- let parameters = {};
1315
- let cek;
1316
- switch (alg) {
1317
- case "dir": {
1318
- cek = key;
1319
- break;
1320
- }
1321
- case "ECDH-ES":
1322
- case "ECDH-ES+A128KW":
1323
- case "ECDH-ES+A192KW":
1324
- case "ECDH-ES+A256KW": {
1325
- assertCryptoKey(key);
1326
- if (!allowed(key)) {
1327
- throw new Error(
1328
- "ECDH with the provided key is not allowed or not supported by your javascript runtime"
1329
- );
1330
- }
1331
- const { apu, apv, epk: providedEpk, epkPrivateKey } = providedParameters;
1332
- if (providedEpk && !epkPrivateKey) {
1333
- throw new TypeError(
1334
- "ECDH-ES custom ephemeral key material must include the matching private key."
1335
- );
1336
- }
1337
- let ephemeralPrivateKey;
1338
- let epkHeader;
1339
- if (epkPrivateKey) {
1340
- ephemeralPrivateKey = await ensurePrivateKey(alg, epkPrivateKey);
1341
- const publicSource = providedEpk ?? epkPrivateKey;
1342
- epkHeader = await exportPublicJwkFrom(alg, publicSource);
1343
- } else {
1344
- if (providedEpk) {
1345
- throw new TypeError(
1346
- "ECDH-ES custom ephemeral public key requires a matching private key."
1347
- );
1348
- }
1349
- const generated = await crypto.subtle.generateKey(
1350
- key.algorithm,
1351
- true,
1352
- ["deriveBits"]
1353
- );
1354
- ephemeralPrivateKey = generated.privateKey;
1355
- epkHeader = await exportPublicJwkFrom(alg, generated.publicKey);
1356
- }
1357
- const sharedSecret = await deriveECDHESKey(
1358
- key,
1359
- ephemeralPrivateKey,
1360
- alg === "ECDH-ES" ? enc : alg,
1361
- alg === "ECDH-ES" ? bitLengthCEK(enc) : Number.parseInt(alg.slice(-5, -2), 10),
1362
- apu,
1363
- apv
1364
- );
1365
- parameters = { epk: epkHeader };
1366
- if (apu) parameters.apu = base64UrlEncode(apu);
1367
- if (apv) parameters.apv = base64UrlEncode(apv);
1368
- if (alg === "ECDH-ES") {
1369
- cek = sharedSecret;
1370
- break;
1371
- }
1372
- cek = providedCek || generateCEK(enc);
1373
- const kwAlg = alg.slice(-6);
1374
- encryptedKey = (await wrap(kwAlg, sharedSecret, cek)).encryptedKey;
1375
- break;
1376
- }
1377
- case "RSA-OAEP":
1378
- case "RSA-OAEP-256":
1379
- case "RSA-OAEP-384":
1380
- case "RSA-OAEP-512": {
1381
- cek = providedCek || generateCEK(enc);
1382
- assertCryptoKey(key);
1383
- encryptedKey = await encryptRSAES(alg, key, cek);
1384
- break;
1385
- }
1386
- case "PBES2-HS256+A128KW":
1387
- case "PBES2-HS384+A192KW":
1388
- case "PBES2-HS512+A256KW": {
1389
- cek = providedCek || generateCEK(enc);
1390
- const { p2c, p2s } = providedParameters;
1391
- ({ encryptedKey, ...parameters } = await wrap(alg, key, cek, p2c, p2s));
1392
- break;
1393
- }
1394
- case "A128KW":
1395
- case "A192KW":
1396
- case "A256KW": {
1397
- cek = providedCek || generateCEK(enc);
1398
- encryptedKey = (await wrap(alg, key, cek)).encryptedKey;
1399
- break;
1400
- }
1401
- case "A128GCMKW":
1402
- case "A192GCMKW":
1403
- case "A256GCMKW": {
1404
- cek = providedCek || generateCEK(enc);
1405
- const { iv } = providedParameters;
1406
- ({ encryptedKey, ...parameters } = await encryptIV(alg, key, cek, iv));
1407
- break;
1408
- }
1409
- default: {
1410
- throw new Error(
1411
- 'Invalid or unsupported "alg" (JWE Algorithm) header value'
1412
- );
1413
- }
1414
- }
1415
- return { cek, encryptedKey, parameters };
1416
- }
1417
- async function normalizeKey(key, alg) {
1418
- if (key instanceof Uint8Array) {
1419
- return key;
1420
- }
1421
- if (isCryptoKey(key)) {
1422
- return key;
1423
- }
1424
- if (isJWK(key)) {
1425
- const safeJwk = sanitizeObject(key);
1426
- if ("k" in safeJwk && safeJwk.k) {
1427
- return base64UrlDecode(safeJwk.k, false);
1428
- }
1429
- return jwkTokey({ ...safeJwk, alg });
1430
- }
1431
- throw new Error("unreachable");
1432
- }
1433
-
1434
- async function generateKey(alg, options = {}) {
1435
- const exportToJWK = options.toJWK !== void 0 && options.toJWK !== false;
1436
- const defaultExtractable = options.extractable !== false;
1437
- if (alg === "A128CBC-HS256" || alg === "A192CBC-HS384" || alg === "A256CBC-HS512") {
1438
- const keyLength = bitLengthCEK(alg);
1439
- const keyBytes = randomBytes(keyLength >> 3);
1440
- if (exportToJWK) {
1441
- return keyToJWK(keyBytes);
1442
- }
1443
- return keyBytes;
1444
- }
1445
- const { algorithm, keyUsages } = getGenerateKeyParams(alg, options);
1446
- const key = await crypto.subtle.generateKey(
1447
- algorithm,
1448
- defaultExtractable,
1449
- keyUsages
1450
- );
1451
- if (exportToJWK) {
1452
- const {
1453
- alg: _a,
1454
- kty: _k,
1455
- key_ops: _ko,
1456
- ext: _e,
1457
- ...additionalKeyParams
1458
- } = typeof options.toJWK === "object" ? options.toJWK : {};
1459
- if (key instanceof CryptoKey) {
1460
- return exportKey(key, {
1461
- ...additionalKeyParams,
1462
- alg
1463
- });
1464
- } else {
1465
- const [publicKey, privateKey] = await Promise.all([
1466
- exportKey(key.publicKey, { ...additionalKeyParams, alg }),
1467
- exportKey(key.privateKey, {
1468
- ...additionalKeyParams,
1469
- alg
1470
- })
1471
- ]);
1472
- return { privateKey, publicKey };
1473
- }
1474
- }
1475
- return key;
1476
- }
1477
- async function generateJWK(alg, jwkParams, options = {}) {
1478
- const {
1479
- // @ts-expect-error destructuring just to avoid passing it down
1480
- toJWK: _,
1481
- ...opts
1482
- } = options;
1483
- return generateKey(alg, {
1484
- ...opts,
1485
- toJWK: {
1486
- kid: typeof jwkParams?.kid === "string" ? jwkParams.kid : crypto.randomUUID(),
1487
- ...jwkParams
1488
- }
1489
- });
1490
- }
1491
- async function deriveKeyFromPassword(password, alg, options) {
1492
- const { salt, iterations, extractable, keyUsage } = options;
1493
- const exportToJWK = options.toJWK !== void 0 && options.toJWK !== false;
1494
- if (!(salt instanceof Uint8Array) || salt.length < 8) {
1495
- throw new Error("PBES2 Salt Input (salt) must be 8 or more octets");
1496
- }
1497
- if (typeof iterations !== "number" || iterations < 1) {
1498
- throw new Error(
1499
- "PBES2 Iteration Count (iterations) must be a positive integer"
1500
- );
1501
- }
1502
- const passwordBytes = typeof password === "string" ? textEncoder.encode(password) : password;
1503
- const derivedBytes = await deriveKey(
1504
- salt,
1505
- alg,
1506
- iterations,
1507
- passwordBytes
1508
- );
1509
- const wrappingAlg = alg.slice(-6);
1510
- const defaultUsages = ["wrapKey", "unwrapKey"];
1511
- const finalUsages = keyUsage ?? defaultUsages;
1512
- const finalExtractable = exportToJWK ? true : extractable === true;
1513
- const derivedKey = await crypto.subtle.importKey(
1514
- "raw",
1515
- derivedBytes,
1516
- { name: "AES-KW" },
1517
- finalExtractable,
1518
- finalUsages
1519
- );
1520
- if (exportToJWK) {
1521
- const jwk = await keyToJWK(derivedKey);
1522
- const {
1523
- alg: _a,
1524
- kty: _k,
1525
- key_ops: _ko,
1526
- ext: _e,
1527
- ...additionalKeyParams
1528
- } = typeof options.toJWK === "object" ? options.toJWK : {};
1529
- return { ...additionalKeyParams, ...jwk, alg: wrappingAlg, kty: "oct" };
1530
- }
1531
- return derivedKey;
1532
- }
1533
- async function deriveJWKFromPassword(password, alg, options, jwkParams) {
1534
- const {
1535
- // @ts-expect-error destructuring just to avoid passing it down
1536
- toJWK: _,
1537
- ...opts
1538
- } = options;
1539
- return deriveKeyFromPassword(password, alg, {
1540
- ...opts,
1541
- toJWK: jwkParams || true
1542
- });
1543
- }
1544
- async function importKey(key, alg) {
1545
- if (typeof key === "string") {
1546
- key = textEncoder.encode(key);
1547
- }
1548
- if (key instanceof Uint8Array) {
1549
- return key;
1550
- }
1551
- if (isCryptoKey(key)) {
1552
- return key;
1553
- }
1554
- if (isJWK(key)) {
1555
- if ("k" in key && typeof key.k === "string") {
1556
- return base64UrlDecode(key.k, false);
1557
- } else {
1558
- if (!key.alg && !alg) {
1559
- throw new TypeError(
1560
- "Algorithm must be provided when importing non-oct JWK"
1561
- );
1562
- }
1563
- return jwkTokey({
1564
- ...key,
1565
- alg: key.alg || alg
1566
- });
1567
- }
1568
- }
1569
- throw new Error("Invalid key type provided to importKey");
1570
- }
1571
- async function exportKey(key, jwk) {
1572
- const exportedJwk = await keyToJWK(key);
1573
- if (jwk) {
1574
- return { ...sanitizeObject(jwk), ...exportedJwk };
1575
- }
1576
- return exportedJwk;
1577
- }
1578
- async function wrapKey(alg, keyToWrap, wrappingKey, options = {}) {
1579
- const cekBytes = keyToWrap instanceof Uint8Array ? keyToWrap : new Uint8Array(await crypto.subtle.exportKey("raw", keyToWrap));
1580
- let importedWrappingKey;
1581
- const isPbes = alg.startsWith("PBES2");
1582
- const isAesKw = ["A128KW", "A192KW", "A256KW"].includes(alg);
1583
- if (isPbes && (typeof wrappingKey === "string" || wrappingKey instanceof Uint8Array)) {
1584
- importedWrappingKey = typeof wrappingKey === "string" ? textEncoder.encode(wrappingKey) : wrappingKey;
1585
- } else if (isPbes || isAesKw) {
1586
- if (typeof wrappingKey === "string") {
1587
- throw new TypeError(
1588
- "Wrapping key must be a CryptoKey, JWK, or Uint8Array for AES-KW or non-password PBES2"
1589
- );
1590
- }
1591
- importedWrappingKey = await importKey(wrappingKey, alg);
1592
- } else {
1593
- if (typeof wrappingKey === "string") {
1594
- throw new TypeError(
1595
- "Wrapping key must be a CryptoKey, JWK, or Uint8Array for non-PBES2 algorithms"
1596
- );
1597
- }
1598
- importedWrappingKey = await importKey(wrappingKey, alg);
1599
- }
1600
- switch (alg) {
1601
- // AES Key Wrap and PBES2 are handled by the same helper
1602
- case "A128KW":
1603
- case "A192KW":
1604
- case "A256KW":
1605
- case "PBES2-HS256+A128KW":
1606
- case "PBES2-HS384+A192KW":
1607
- case "PBES2-HS512+A256KW": {
1608
- const { p2s, p2c } = options;
1609
- if (isPbes && (!p2s || typeof p2c !== "number")) {
1610
- throw new Error(
1611
- "PBES2 requires 'p2s' (salt) and 'p2c' (count) options"
1612
- );
1613
- }
1614
- return wrap(alg, importedWrappingKey, cekBytes, p2c, p2s);
1615
- }
1616
- case "A128GCMKW":
1617
- case "A192GCMKW":
1618
- case "A256GCMKW": {
1619
- const { encryptedKey, iv, tag } = await encryptIV(
1620
- alg,
1621
- importedWrappingKey,
1622
- cekBytes,
1623
- options.iv
1624
- );
1625
- return { encryptedKey, iv, tag };
1626
- }
1627
- case "RSA-OAEP":
1628
- case "RSA-OAEP-256":
1629
- case "RSA-OAEP-384":
1630
- case "RSA-OAEP-512": {
1631
- const keyToWrapImported = await crypto.subtle.importKey(
1632
- "raw",
1633
- cekBytes,
1634
- { name: "AES-GCM", length: cekBytes.length * 8 },
1635
- true,
1636
- ["encrypt", "decrypt"]
1637
- );
1638
- const encryptedKey = new Uint8Array(
1639
- await crypto.subtle.wrapKey(
1640
- "raw",
1641
- keyToWrapImported,
1642
- importedWrappingKey,
1643
- { name: "RSA-OAEP" }
1644
- )
1645
- );
1646
- return { encryptedKey };
1647
- }
1648
- case "ECDH-ES":
1649
- case "ECDH-ES+A128KW":
1650
- case "ECDH-ES+A192KW":
1651
- case "ECDH-ES+A256KW": {
1652
- throw new Error(`Algorithm ${alg} not yet implemented in wrapKey`);
1653
- }
1654
- default: {
1655
- throw new Error(`Unsupported key wrapping algorithm: ${alg}`);
1656
- }
1657
- }
1658
- }
1659
- async function unwrapKey(alg, wrappedKey, unwrappingKey, options = {}) {
1660
- const { returnAs = true } = options;
1661
- const defaultExtractable = options.extractable !== false;
1662
- let importedUnwrappingKey;
1663
- const isPbes = alg.startsWith("PBES2");
1664
- const isAesKw = ["A128KW", "A192KW", "A256KW"].includes(alg);
1665
- if (isPbes && (typeof unwrappingKey === "string" || unwrappingKey instanceof Uint8Array)) {
1666
- importedUnwrappingKey = typeof unwrappingKey === "string" ? textEncoder.encode(unwrappingKey) : unwrappingKey;
1667
- } else if (isPbes || isAesKw) {
1668
- if (typeof unwrappingKey === "string") {
1669
- throw new TypeError(
1670
- "Unwrapping key must be a CryptoKey, JWK, or Uint8Array for AES-KW or non-password PBES2"
1671
- );
1672
- }
1673
- importedUnwrappingKey = await importKey(unwrappingKey, alg);
1674
- } else {
1675
- if (typeof unwrappingKey === "string") {
1676
- throw new TypeError(
1677
- "Unwrapping key must be a CryptoKey, JWK, or Uint8Array for non-PBES2 algorithms"
1678
- );
1679
- }
1680
- importedUnwrappingKey = await importKey(unwrappingKey, alg);
1681
- }
1682
- let unwrappedCekBytes;
1683
- switch (alg) {
1684
- // AES Key Wrap and PBES2 are handled by the same helper
1685
- case "A128KW":
1686
- case "A192KW":
1687
- case "A256KW":
1688
- case "PBES2-HS256+A128KW":
1689
- case "PBES2-HS384+A192KW":
1690
- case "PBES2-HS512+A256KW": {
1691
- const { p2s, p2c } = options;
1692
- let p2sBytes;
1693
- if (isPbes) {
1694
- if (!p2s || typeof p2c !== "number") {
1695
- throw new Error(
1696
- "PBES2 requires 'p2s' (salt) and 'p2c' (count) options"
1697
- );
1698
- }
1699
- p2sBytes = typeof p2s === "string" ? base64UrlDecode(p2s, false) : p2s;
1700
- }
1701
- unwrappedCekBytes = await unwrap(
1702
- alg,
1703
- importedUnwrappingKey,
1704
- wrappedKey,
1705
- p2c,
1706
- p2sBytes
1707
- );
1708
- break;
1709
- }
1710
- case "A128GCMKW":
1711
- case "A192GCMKW":
1712
- case "A256GCMKW": {
1713
- if (!options.iv || !options.tag) {
1714
- throw new Error(
1715
- "AES-GCMKW requires 'iv' and 'tag' options for unwrapping"
1716
- );
1717
- }
1718
- const ivBytes = typeof options.iv === "string" ? base64UrlDecode(options.iv, false) : options.iv;
1719
- const tagBytes = typeof options.tag === "string" ? base64UrlDecode(options.tag, false) : options.tag;
1720
- unwrappedCekBytes = await decryptIV(
1721
- alg,
1722
- importedUnwrappingKey,
1723
- wrappedKey,
1724
- ivBytes,
1725
- tagBytes
1726
- );
1727
- break;
1728
- }
1729
- case "RSA-OAEP":
1730
- case "RSA-OAEP-256":
1731
- case "RSA-OAEP-384":
1732
- case "RSA-OAEP-512": {
1733
- if (!(importedUnwrappingKey instanceof CryptoKey)) {
1734
- throw new TypeError(
1735
- "RSA-OAEP requires the unwrapping key to be provided as a CryptoKey"
1736
- );
1737
- }
1738
- unwrappedCekBytes = await decryptRSAES(
1739
- alg,
1740
- importedUnwrappingKey,
1741
- wrappedKey
1742
- );
1743
- if (!returnAs) {
1744
- break;
1745
- }
1746
- const inferredAlgorithm = options.unwrappedKeyAlgorithm || inferAesImportAlgorithm(options.enc, unwrappedCekBytes.length);
1747
- if (!inferredAlgorithm) {
1748
- throw new Error(
1749
- 'Unable to infer algorithm for RSA-OAEP unwrapped key. Provide "unwrappedKeyAlgorithm" in options.'
1750
- );
1751
- }
1752
- const keyUsages = options.keyUsage || ["encrypt", "decrypt"];
1753
- return await crypto.subtle.importKey(
1754
- "raw",
1755
- unwrappedCekBytes,
1756
- inferredAlgorithm,
1757
- defaultExtractable,
1758
- keyUsages
1759
- );
1760
- }
1761
- case "ECDH-ES":
1762
- case "ECDH-ES+A128KW":
1763
- case "ECDH-ES+A192KW":
1764
- case "ECDH-ES+A256KW": {
1765
- if (!options.epk) {
1766
- throw new Error("ECDH-ES requires 'epk' (Ephemeral Public Key) option");
1767
- }
1768
- if (!(importedUnwrappingKey instanceof CryptoKey)) {
1769
- throw new TypeError(
1770
- "ECDH-ES requires the unwrapping key to be a CryptoKey"
1771
- );
1772
- }
1773
- if (!allowed(importedUnwrappingKey)) {
1774
- throw new Error(
1775
- "ECDH with the provided key is not allowed or not supported"
1776
- );
1777
- }
1778
- const epkCandidate = options.epk instanceof CryptoKey ? options.epk : await normalizeKey(options.epk, alg);
1779
- if (!(epkCandidate instanceof CryptoKey)) {
1780
- throw new TypeError("Failed to normalize ECDH ephemeral public key");
1781
- }
1782
- const apuBytes = typeof options.apu === "string" ? base64UrlDecode(options.apu, false) : options.apu ?? new Uint8Array(0);
1783
- const apvBytes = typeof options.apv === "string" ? base64UrlDecode(options.apv, false) : options.apv ?? new Uint8Array(0);
1784
- const infoAlg = alg === "ECDH-ES" ? options.enc : alg;
1785
- if (!infoAlg) {
1786
- throw new Error(
1787
- "ECDH-ES requires content encryption algorithm ('enc') to derive the shared secret"
1788
- );
1789
- }
1790
- const keyLength = alg === "ECDH-ES" ? bitLengthCEK(infoAlg) : Number.parseInt(alg.slice(-5, -2), 10);
1791
- const sharedSecret = await deriveECDHESKey(
1792
- epkCandidate,
1793
- importedUnwrappingKey,
1794
- infoAlg,
1795
- keyLength,
1796
- apuBytes,
1797
- apvBytes
1798
- );
1799
- if (alg === "ECDH-ES") {
1800
- unwrappedCekBytes = sharedSecret;
1801
- } else {
1802
- const kwAlg = alg.slice(-6);
1803
- if (!(wrappedKey instanceof Uint8Array) || wrappedKey.length === 0) {
1804
- throw new Error(
1805
- "ECDH-ES key agreement with key wrapping requires an encrypted key"
1806
- );
1807
- }
1808
- unwrappedCekBytes = await unwrap(kwAlg, sharedSecret, wrappedKey);
1809
- }
1810
- break;
1811
- }
1812
- default: {
1813
- throw new Error(`Unsupported key unwrapping algorithm: ${alg}`);
1814
- }
1815
- }
1816
- if (!returnAs) {
1817
- return unwrappedCekBytes;
1818
- }
1819
- const finalKey = await crypto.subtle.importKey(
1820
- "raw",
1821
- unwrappedCekBytes,
1822
- options.unwrappedKeyAlgorithm || { name: "AES-GCM" },
1823
- defaultExtractable,
1824
- options.keyUsage || ["encrypt", "decrypt"]
1825
- );
1826
- return finalKey;
1827
- }
1828
- async function importJWKFromPEM(pem, pemType, alg, importOptions, jwkExtras) {
1829
- let cryptoKey;
1830
- const defaultExtractable = importOptions?.extractable !== false;
1831
- switch (pemType) {
1832
- case "pkcs8": {
1833
- cryptoKey = await fromPKCS8(pem, alg, {
1834
- ...importOptions,
1835
- extractable: defaultExtractable
1836
- });
1837
- break;
1838
- }
1839
- case "spki": {
1840
- cryptoKey = await fromSPKI(pem, alg, {
1841
- ...importOptions,
1842
- extractable: defaultExtractable
1843
- });
1844
- break;
1845
- }
1846
- case "x509": {
1847
- cryptoKey = await fromX509(pem, alg, {
1848
- ...importOptions,
1849
- extractable: defaultExtractable
1850
- });
1851
- break;
1852
- }
1853
- default: {
1854
- throw new TypeError(`Unsupported PEM type: ${pemType}`);
1855
- }
1856
- }
1857
- const finalJWKExtras = { alg, ...jwkExtras };
1858
- return exportKey(cryptoKey, finalJWKExtras);
1859
- }
1860
- async function exportJWKToPEM(jwk, pemFormat, algForCryptoKeyImport) {
1861
- if (jwk.kty === "oct") {
1862
- throw new TypeError(
1863
- "Octet (symmetric) JWKs (kty: 'oct') cannot be exported to PKCS8 or SPKI PEM formats."
1864
- );
1865
- }
1866
- const effectiveAlg = jwk.alg || algForCryptoKeyImport;
1867
- if (!effectiveAlg && (jwk.kty === "RSA" || jwk.kty === "EC" || jwk.kty === "OKP")) {
1868
- throw new TypeError(
1869
- "Algorithm (alg) must be provided in the JWK or as a parameter for converting this JWK type to a CryptoKey."
1870
- );
1871
- }
1872
- const jwkForImport = { ...jwk, ext: true };
1873
- const cryptoKeyCandidate = await importKey(jwkForImport, effectiveAlg);
1874
- if (!isCryptoKey(cryptoKeyCandidate)) {
1875
- throw new Error(
1876
- "Failed to convert JWK to a CryptoKey instance suitable for PEM export."
1877
- );
1878
- }
1879
- const cryptoKey = cryptoKeyCandidate;
1880
- switch (pemFormat) {
1881
- case "pkcs8": {
1882
- if (cryptoKey.type !== "private") {
1883
- throw new TypeError(
1884
- `Only 'private' type CryptoKeys can be exported to PKCS8 PEM format. Key type is '${cryptoKey.type}'.`
1885
- );
1886
- }
1887
- return toPKCS8(cryptoKey);
1888
- }
1889
- case "spki": {
1890
- if (cryptoKey.type !== "public") {
1891
- throw new TypeError(
1892
- `Only 'public' type CryptoKeys can be exported to SPKI PEM format. Key type is '${cryptoKey.type}'.`
1893
- );
1894
- }
1895
- return toSPKI(cryptoKey);
1896
- }
1897
- default: {
1898
- throw new TypeError(`Unsupported PEM format: ${pemFormat}`);
1899
- }
1900
- }
1901
- }
1902
- function getJWKFromSet(jwkSet, kidOrProtectedHeader) {
1903
- if (!jwkSet || !isJWKSet(jwkSet)) {
1904
- throw new TypeError("Invalid JWK Set provided");
1905
- }
1906
- if (typeof kidOrProtectedHeader === "string") {
1907
- const kid = kidOrProtectedHeader;
1908
- const selectedKey = jwkSet.keys.find((k) => k.kid === kid);
1909
- if (!selectedKey) {
1910
- throw new Error(`No key found in JWK Set with kid "${kid}".`);
1911
- }
1912
- return selectedKey;
1913
- } else if (typeof kidOrProtectedHeader === "object") {
1914
- const { kid, alg, kty } = kidOrProtectedHeader;
1915
- if (!kid) {
1916
- throw new Error(
1917
- "JWS Protected Header is missing 'kid' (Key ID) and a JWK Set was provided. Cannot select key from JWK Set automatically."
1918
- );
1919
- }
1920
- const selectedKey = jwkSet.keys.find((k) => {
1921
- return k.kid === kid && (!alg || k.alg === alg) && (!kty || k.kty === kty);
1922
- });
1923
- if (!selectedKey) {
1924
- let errorMessage = `No key found in JWK Set with kid "${kid}"`;
1925
- if (alg) {
1926
- errorMessage += ` and alg "${alg}"`;
1927
- }
1928
- if (kty) {
1929
- errorMessage += ` and kty "${kty}"`;
1930
- }
1931
- errorMessage += ".";
1932
- throw new Error(errorMessage);
1933
- }
1934
- return selectedKey;
1935
- }
1936
- throw new TypeError(
1937
- "`kidOrProtectedHeader` must be a string (kid) or an object (JOSE Protected Header)."
1938
- );
1939
- }
1940
- function getGenerateKeyParams(alg, options) {
1941
- let algorithm;
1942
- let keyUsages;
1943
- const defaultKeyUsage = options?.keyUsage;
1944
- switch (alg) {
1945
- // HMAC Signatures
1946
- case "HS256":
1947
- case "HS384":
1948
- case "HS512": {
1949
- algorithm = {
1950
- name: "HMAC",
1951
- hash: `SHA-${alg.slice(2)}`
1952
- };
1953
- keyUsages = defaultKeyUsage ?? ["sign", "verify"];
1954
- break;
1955
- }
1956
- // RSA Signatures
1957
- case "RS256":
1958
- case "RS384":
1959
- case "RS512": {
1960
- algorithm = {
1961
- name: "RSASSA-PKCS1-v1_5",
1962
- modulusLength: options?.modulusLength ?? 2048,
1963
- publicExponent: options?.publicExponent ?? new Uint8Array([1, 0, 1]),
1964
- hash: `SHA-${alg.slice(2)}`
1965
- };
1966
- keyUsages = defaultKeyUsage ?? ["sign", "verify"];
1967
- break;
1968
- }
1969
- // RSA PSS Signatures
1970
- case "PS256":
1971
- case "PS384":
1972
- case "PS512": {
1973
- algorithm = {
1974
- name: "RSA-PSS",
1975
- modulusLength: options?.modulusLength ?? 2048,
1976
- publicExponent: options?.publicExponent ?? new Uint8Array([1, 0, 1]),
1977
- hash: `SHA-${alg.slice(2)}`
1978
- };
1979
- keyUsages = defaultKeyUsage ?? ["sign", "verify"];
1980
- break;
1981
- }
1982
- // RSA Encryption
1983
- case "RSA-OAEP":
1984
- case "RSA-OAEP-256":
1985
- case "RSA-OAEP-384":
1986
- case "RSA-OAEP-512": {
1987
- algorithm = {
1988
- name: "RSA-OAEP",
1989
- modulusLength: options?.modulusLength ?? 2048,
1990
- publicExponent: options?.publicExponent ?? new Uint8Array([1, 0, 1]),
1991
- hash: `SHA-${Number.parseInt(alg.slice(9), 10) || 1}`
1992
- };
1993
- keyUsages = defaultKeyUsage ?? [
1994
- "encrypt",
1995
- "decrypt",
1996
- "wrapKey",
1997
- "unwrapKey"
1998
- ];
1999
- break;
2000
- }
2001
- // AES Key Wrap
2002
- case "A128KW":
2003
- case "A192KW":
2004
- case "A256KW": {
2005
- const length = Number.parseInt(alg.slice(1, 4), 10);
2006
- algorithm = { name: "AES-KW", length };
2007
- keyUsages = defaultKeyUsage ?? ["wrapKey", "unwrapKey"];
2008
- break;
2009
- }
2010
- // AES GCM Encryption
2011
- case "A128GCM":
2012
- case "A192GCM":
2013
- case "A256GCM":
2014
- case "A128GCMKW":
2015
- case "A192GCMKW":
2016
- case "A256GCMKW": {
2017
- const baseAlg = alg.replace("KW", "");
2018
- const length = Number.parseInt(baseAlg.slice(1, 4), 10);
2019
- algorithm = { name: "AES-GCM", length };
2020
- keyUsages = defaultKeyUsage ?? (alg.endsWith("KW") ? ["wrapKey", "unwrapKey"] : ["encrypt", "decrypt"]);
2021
- break;
2022
- }
2023
- // ECDSA Signatures
2024
- case "ES256":
2025
- case "ES384":
2026
- case "ES512": {
2027
- algorithm = { name: "ECDSA", namedCurve: `P-${alg.slice(2)}` };
2028
- keyUsages = defaultKeyUsage ?? ["sign", "verify"];
2029
- break;
2030
- }
2031
- case "Ed25519": {
2032
- keyUsages = defaultKeyUsage ?? ["sign", "verify"];
2033
- algorithm = { name: "Ed25519" };
2034
- break;
2035
- }
2036
- case "EdDSA": {
2037
- keyUsages = defaultKeyUsage ?? ["sign", "verify"];
2038
- const namedCurve = options?.namedCurve ?? "Ed25519";
2039
- switch (namedCurve) {
2040
- case "Ed25519":
2041
- case "Ed448": {
2042
- algorithm = { name: namedCurve };
2043
- break;
2044
- }
2045
- default: {
2046
- throw new Error(
2047
- "Unsupported namedCurve provided. Supported values are: Ed25519 and Ed448"
2048
- );
2049
- }
2050
- }
2051
- break;
2052
- }
2053
- // ECDSA Signatures
2054
- case "ECDH-ES":
2055
- case "ECDH-ES+A128KW":
2056
- case "ECDH-ES+A192KW":
2057
- case "ECDH-ES+A256KW": {
2058
- keyUsages = ["deriveBits"];
2059
- const namedCurve = options?.namedCurve ?? "P-256";
2060
- switch (namedCurve) {
2061
- case "P-256":
2062
- case "P-384":
2063
- case "P-521": {
2064
- algorithm = { name: "ECDH", namedCurve };
2065
- break;
2066
- }
2067
- case "X25519": {
2068
- algorithm = { name: "X25519" };
2069
- break;
2070
- }
2071
- default: {
2072
- throw new Error(
2073
- "Unsupported namedCurve provided. Supported values are: P-256, P-384, P-521 and X25519"
2074
- );
2075
- }
2076
- }
2077
- break;
2078
- }
2079
- default: {
2080
- throw new Error(
2081
- `Unsupported or invalid algorithm for key generation: ${alg}`
2082
- );
2083
- }
2084
- }
2085
- return { algorithm, keyUsages };
2086
- }
2087
- function inferAesImportAlgorithm(enc, cekLengthBytes) {
2088
- const bitLength = cekLengthBytes << 3;
2089
- if (enc) {
2090
- if (enc.includes("GCM")) {
2091
- return {
2092
- name: "AES-GCM",
2093
- length: Number.parseInt(enc.slice(1, 4), 10)
2094
- };
2095
- }
2096
- if (enc.includes("CBC-HS")) {
2097
- return void 0;
2098
- }
2099
- }
2100
- if (bitLength === 128 || bitLength === 192 || bitLength === 256) {
2101
- return { name: "AES-GCM", length: bitLength };
2102
- }
2103
- return void 0;
2104
- }
2105
-
2106
- const jwk = {
2107
- __proto__: null,
2108
- deriveJWKFromPassword: deriveJWKFromPassword,
2109
- deriveKeyFromPassword: deriveKeyFromPassword,
2110
- exportJWKToPEM: exportJWKToPEM,
2111
- exportKey: exportKey,
2112
- generateJWK: generateJWK,
2113
- generateKey: generateKey,
2114
- getJWKFromSet: getJWKFromSet,
2115
- importJWKFromPEM: importJWKFromPEM,
2116
- importKey: importKey,
2117
- unwrapKey: unwrapKey,
2118
- wrapKey: wrapKey
2119
- };
2120
-
2121
- export { encrypt as a, getJWKFromSet as b, generateJWK as c, decrypt as d, encryptKey as e, importJWKFromPEM as f, generateIV as g, exportJWKToPEM as h, importKey as i, jwk as j, deriveJWKFromPassword as k, generateKey as l, deriveKeyFromPassword as m, exportKey as n, sign as s, unwrapKey as u, verify as v, wrapKey as w };