jose 6.2.11 → 6.2.13

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 (85) hide show
  1. package/README.md +2 -2
  2. package/dist/types/index.d.ts +1 -2
  3. package/dist/types/jwe/compact/decrypt.d.ts +9 -12
  4. package/dist/types/jwe/compact/encrypt.d.ts +14 -17
  5. package/dist/types/jwe/flattened/decrypt.d.ts +9 -12
  6. package/dist/types/jwe/flattened/encrypt.d.ts +17 -20
  7. package/dist/types/jwe/general/decrypt.d.ts +12 -17
  8. package/dist/types/jwe/general/encrypt.d.ts +19 -22
  9. package/dist/types/jwk/embedded.d.ts +3 -1
  10. package/dist/types/jwk/thumbprint.d.ts +4 -6
  11. package/dist/types/jwks/local.d.ts +5 -4
  12. package/dist/types/jwks/remote.d.ts +20 -21
  13. package/dist/types/jws/compact/sign.d.ts +7 -6
  14. package/dist/types/jws/compact/verify.d.ts +9 -12
  15. package/dist/types/jws/flattened/sign.d.ts +8 -7
  16. package/dist/types/jws/flattened/verify.d.ts +10 -12
  17. package/dist/types/jws/general/sign.d.ts +16 -17
  18. package/dist/types/jws/general/verify.d.ts +14 -18
  19. package/dist/types/jwt/decrypt.d.ts +15 -11
  20. package/dist/types/jwt/encrypt.d.ts +25 -23
  21. package/dist/types/jwt/sign.d.ts +4 -8
  22. package/dist/types/jwt/unsecured.d.ts +3 -7
  23. package/dist/types/jwt/verify.d.ts +12 -7
  24. package/dist/types/key/export.d.ts +6 -6
  25. package/dist/types/key/generate_key_pair.d.ts +9 -14
  26. package/dist/types/key/generate_secret.d.ts +10 -10
  27. package/dist/types/key/import.d.ts +21 -20
  28. package/dist/types/types.d.ts +217 -254
  29. package/dist/types/util/base64url.d.ts +7 -7
  30. package/dist/types/util/decode_jwt.d.ts +6 -1
  31. package/dist/types/util/decode_protected_header.d.ts +4 -3
  32. package/dist/types/util/errors.d.ts +30 -41
  33. package/dist/webapi/jwe/compact/decrypt.js +1 -2
  34. package/dist/webapi/jwe/compact/encrypt.js +9 -26
  35. package/dist/webapi/jwe/flattened/decrypt.js +3 -3
  36. package/dist/webapi/jwe/flattened/encrypt.js +11 -30
  37. package/dist/webapi/jwe/general/decrypt.js +6 -6
  38. package/dist/webapi/jwe/general/encrypt.js +36 -60
  39. package/dist/webapi/jwk/embedded.js +3 -4
  40. package/dist/webapi/jwk/thumbprint.js +11 -14
  41. package/dist/webapi/jwks/local.js +18 -11
  42. package/dist/webapi/jwks/remote.js +5 -5
  43. package/dist/webapi/jws/compact/sign.js +2 -4
  44. package/dist/webapi/jws/compact/verify.js +2 -2
  45. package/dist/webapi/jws/flattened/sign.js +8 -15
  46. package/dist/webapi/jws/flattened/verify.js +4 -14
  47. package/dist/webapi/jws/general/sign.js +6 -13
  48. package/dist/webapi/jws/general/verify.js +8 -10
  49. package/dist/webapi/jwt/decrypt.js +2 -3
  50. package/dist/webapi/jwt/encrypt.js +13 -27
  51. package/dist/webapi/jwt/sign.js +3 -3
  52. package/dist/webapi/jwt/unsecured.js +4 -5
  53. package/dist/webapi/jwt/verify.js +4 -4
  54. package/dist/webapi/key/export.js +12 -16
  55. package/dist/webapi/key/generate_key_pair.js +4 -13
  56. package/dist/webapi/key/generate_secret.js +5 -5
  57. package/dist/webapi/key/import.js +5 -9
  58. package/dist/webapi/lib/asn1.js +4 -6
  59. package/dist/webapi/lib/buffer_utils.js +39 -4
  60. package/dist/webapi/lib/content_encryption.js +29 -37
  61. package/dist/webapi/lib/deflate.js +9 -19
  62. package/dist/webapi/lib/jwe_algorithms.js +0 -4
  63. package/dist/webapi/lib/jwe_decrypt.js +30 -63
  64. package/dist/webapi/lib/jwe_encrypt.js +27 -60
  65. package/dist/webapi/lib/jws_algorithms.js +2 -2
  66. package/dist/webapi/lib/jws_sign.js +31 -45
  67. package/dist/webapi/lib/jws_verify.js +43 -48
  68. package/dist/webapi/lib/jwt_claims_set.js +45 -44
  69. package/dist/webapi/lib/key.js +122 -62
  70. package/dist/webapi/lib/key_management.js +57 -92
  71. package/dist/webapi/lib/{options.js → validate.js} +64 -3
  72. package/dist/webapi/util/base64url.js +5 -19
  73. package/dist/webapi/util/decode_jwt.js +13 -13
  74. package/dist/webapi/util/decode_protected_header.js +6 -6
  75. package/package.json +1 -1
  76. package/dist/webapi/lib/base64.js +0 -20
  77. package/dist/webapi/lib/crypto_key.js +0 -27
  78. package/dist/webapi/lib/helpers.js +0 -45
  79. package/dist/webapi/lib/invalid_key_input.js +0 -12
  80. package/dist/webapi/lib/is_key_like.js +0 -19
  81. package/dist/webapi/lib/jwk_metadata.js +0 -19
  82. package/dist/webapi/lib/jwk_to_key.js +0 -10
  83. package/dist/webapi/lib/key_options.js +0 -8
  84. package/dist/webapi/lib/signing.js +0 -22
  85. package/dist/webapi/lib/type_checks.js +0 -30
@@ -1,4 +1,4 @@
1
- const encoder = new TextEncoder(), decoder = new TextDecoder(), strictDecoder = new TextDecoder("utf-8", { fatal: !0 }), MAX_INT32 = 2 ** 32;
1
+ const encoder = new TextEncoder(), decoder = new TextDecoder(), strictDecoder = new TextDecoder("utf-8", { fatal: !0 }), UINT32_RANGE = 2 ** 32;
2
2
  function concat(...buffers) {
3
3
  const size = buffers.reduce((acc, { length }) => acc + length, 0), buf = new Uint8Array(size);
4
4
  let i = 0;
@@ -7,19 +7,25 @@ function concat(...buffers) {
7
7
  return buf;
8
8
  }
9
9
  function writeUInt32BE(buf, value, offset) {
10
- if (value < 0 || value >= MAX_INT32)
11
- throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`);
10
+ if (value < 0 || value >= UINT32_RANGE)
11
+ throw new RangeError(`value must be >= 0 and <= ${UINT32_RANGE - 1}. Received ${value}`);
12
12
  buf.set([value >>> 24, value >>> 16, value >>> 8, value & 255], offset);
13
13
  }
14
14
  function uint64be(value) {
15
- const high = Math.floor(value / MAX_INT32), low = value % MAX_INT32, buf = new Uint8Array(8);
15
+ const high = Math.floor(value / UINT32_RANGE), low = value % UINT32_RANGE, buf = new Uint8Array(8);
16
16
  return writeUInt32BE(buf, high, 0), writeUInt32BE(buf, low, 4), buf;
17
17
  }
18
18
  function uint32be(value) {
19
19
  const buf = new Uint8Array(4);
20
20
  return writeUInt32BE(buf, value), buf;
21
21
  }
22
+ const NON_ASCII = /[^\x00-\x7f]/;
22
23
  function encode(string) {
24
+ if (typeof string == "string" && string.length >= 128) {
25
+ if (NON_ASCII.test(string))
26
+ throw new TypeError("non-ASCII string encountered in encode()");
27
+ return encoder.encode(string);
28
+ }
23
29
  const bytes = new Uint8Array(string.length);
24
30
  for (let i = 0; i < string.length; i++) {
25
31
  const code = string.charCodeAt(i);
@@ -29,10 +35,39 @@ function encode(string) {
29
35
  }
30
36
  return bytes;
31
37
  }
38
+ function encodeBase64(input, url = !1) {
39
+ if (Uint8Array.prototype.toBase64)
40
+ return input.toBase64({ alphabet: url ? "base64url" : "base64", omitPadding: url });
41
+ const CHUNK_SIZE = 32768, arr = [];
42
+ for (let i = 0; i < input.length; i += CHUNK_SIZE)
43
+ arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
44
+ const encoded = btoa(arr.join(""));
45
+ return url ? encoded.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_") : encoded;
46
+ }
47
+ function decodeBase64(encoded, url = !1) {
48
+ if (Uint8Array.fromBase64)
49
+ return Uint8Array.fromBase64(encoded, { alphabet: url ? "base64url" : "base64" });
50
+ if (url) {
51
+ if (encoded.includes("+") || encoded.includes("/"))
52
+ throw new TypeError("Invalid base64url");
53
+ encoded = encoded.replace(/-/g, "+").replace(/_/g, "/");
54
+ }
55
+ const binary = atob(encoded), bytes = new Uint8Array(binary.length);
56
+ for (let i = 0; i < binary.length; i++)
57
+ bytes[i] = binary.charCodeAt(i);
58
+ return bytes;
59
+ }
60
+ async function digest(algorithm, data) {
61
+ const subtleDigest = `SHA-${algorithm.slice(-3)}`;
62
+ return new Uint8Array(await crypto.subtle.digest(subtleDigest, data));
63
+ }
32
64
  export {
33
65
  concat,
66
+ decodeBase64,
34
67
  decoder,
68
+ digest,
35
69
  encode,
70
+ encodeBase64,
36
71
  encoder,
37
72
  strictDecoder,
38
73
  uint32be,
@@ -1,8 +1,6 @@
1
1
  import { concat, uint64be } from "./buffer_utils.js";
2
- import { checkCryptoKey } from "./crypto_key.js";
3
- import { invalidKeyInput } from "./invalid_key_input.js";
2
+ import { rawKey, invalidKeyInput, isCryptoKey } from "./key.js";
4
3
  import { JWEDecryptionFailed, JWEInvalid } from "../util/errors.js";
5
- import { isCryptoKey } from "./is_key_like.js";
6
4
  const generateCek = (enc) => crypto.getRandomValues(new Uint8Array(enc.cekBits >> 3));
7
5
  function checkCekLength(cek, expected) {
8
6
  const actual = cek.byteLength << 3;
@@ -17,20 +15,20 @@ function checkIvLength(enc, iv) {
17
15
  async function cbcKeySetup(enc, cek, usage) {
18
16
  if (!(cek instanceof Uint8Array))
19
17
  throw new TypeError(invalidKeyInput(cek, "Uint8Array"));
20
- const keySize = enc.cekBits >> 1, encKey = await crypto.subtle.importKey("raw", cek.subarray(keySize >> 3), "AES-CBC", !1, [usage]), macKey = await crypto.subtle.importKey("raw", cek.subarray(0, keySize >> 3), {
21
- hash: `SHA-${keySize << 1}`,
18
+ const keyLengthBits = enc.cekBits >> 1, encKey = await crypto.subtle.importKey("raw", cek.subarray(keyLengthBits >> 3), "AES-CBC", !1, [usage]), macKey = await crypto.subtle.importKey("raw", cek.subarray(0, keyLengthBits >> 3), {
19
+ hash: `SHA-${keyLengthBits << 1}`,
22
20
  name: "HMAC"
23
21
  }, !1, ["sign"]);
24
- return [encKey, macKey, keySize];
22
+ return [encKey, macKey, keyLengthBits];
25
23
  }
26
- async function cbcHmacTag(macKey, macData, keySize) {
27
- return new Uint8Array((await crypto.subtle.sign("HMAC", macKey, macData)).slice(0, keySize >> 3));
24
+ async function cbcHmacTag(macKey, macData, keyLengthBits) {
25
+ return new Uint8Array((await crypto.subtle.sign("HMAC", macKey, macData)).slice(0, keyLengthBits >> 3));
28
26
  }
29
27
  async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
30
- const [encKey, macKey, keySize] = await cbcKeySetup(enc, cek, "encrypt"), ciphertext = new Uint8Array(await crypto.subtle.encrypt({
28
+ const [encKey, macKey, keyLengthBits] = await cbcKeySetup(enc, cek, "encrypt"), ciphertext = new Uint8Array(await crypto.subtle.encrypt({
31
29
  iv,
32
30
  name: "AES-CBC"
33
- }, encKey, plaintext)), macData = concat(aad, iv, ciphertext, uint64be(aad.length * 8)), tag = await cbcHmacTag(macKey, macData, keySize);
31
+ }, encKey, plaintext)), al = uint64be(aad.length * 8), macData = concat(aad, iv, ciphertext, al), tag = await cbcHmacTag(macKey, macData, keyLengthBits);
34
32
  return { ciphertext, tag, iv };
35
33
  }
36
34
  async function timingSafeEqual(a, b) {
@@ -38,7 +36,7 @@ async function timingSafeEqual(a, b) {
38
36
  return crypto.subtle.verify(algorithm, key, aHmac, b);
39
37
  }
40
38
  async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
41
- const [encKey, macKey, keySize] = await cbcKeySetup(enc, cek, "decrypt"), macData = concat(aad, iv, ciphertext, uint64be(aad.length * 8)), expectedTag = await cbcHmacTag(macKey, macData, keySize);
39
+ const [encKey, macKey, keyLengthBits] = await cbcKeySetup(enc, cek, "decrypt"), al = uint64be(aad.length * 8), macData = concat(aad, iv, ciphertext, al), expectedTag = await cbcHmacTag(macKey, macData, keyLengthBits);
42
40
  try {
43
41
  if (await timingSafeEqual(tag, expectedTag))
44
42
  return new Uint8Array(await crypto.subtle.decrypt({ iv, name: "AES-CBC" }, encKey, ciphertext));
@@ -46,21 +44,31 @@ async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
46
44
  }
47
45
  throw new JWEDecryptionFailed();
48
46
  }
49
- async function gcmEncrypt(enc, plaintext, cek, iv, aad) {
50
- const encKey = cek instanceof Uint8Array ? await crypto.subtle.importKey("raw", cek, "AES-GCM", !1, [
51
- "encrypt"
52
- ]) : (checkCryptoKey(cek, enc.subtle, "encrypt"), cek), encrypted = new Uint8Array(await crypto.subtle.encrypt({
47
+ async function encrypt(enc, plaintext, cek, iv, aad) {
48
+ if (!isCryptoKey(cek) && !(cek instanceof Uint8Array))
49
+ throw new TypeError(invalidKeyInput(cek, "CryptoKey", "KeyObject", "Uint8Array", "JSON Web Key"));
50
+ if (iv ? checkIvLength(enc, iv) : iv = generateIv(enc), cek instanceof Uint8Array && checkCekLength(cek, enc.cekBits), enc.cbc)
51
+ return cbcEncrypt(enc, plaintext, cek, iv, aad);
52
+ const encKey = await rawKey(cek, enc.subtle, "encrypt"), encrypted = new Uint8Array(await crypto.subtle.encrypt({
53
53
  additionalData: aad,
54
54
  iv,
55
55
  name: "AES-GCM",
56
56
  tagLength: 128
57
- }, encKey, plaintext)), tag = encrypted.slice(-16);
58
- return { ciphertext: encrypted.slice(0, -16), tag, iv };
57
+ }, encKey, plaintext));
58
+ return { ciphertext: encrypted.subarray(0, -16), tag: encrypted.subarray(-16), iv };
59
59
  }
60
- async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) {
61
- const encKey = cek instanceof Uint8Array ? await crypto.subtle.importKey("raw", cek, "AES-GCM", !1, [
62
- "decrypt"
63
- ]) : (checkCryptoKey(cek, enc.subtle, "decrypt"), cek);
60
+ async function decrypt(enc, cek, ciphertext, iv, tag, aad) {
61
+ if (!isCryptoKey(cek) && !(cek instanceof Uint8Array))
62
+ throw new TypeError(invalidKeyInput(cek, "CryptoKey", "KeyObject", "Uint8Array", "JSON Web Key"));
63
+ if (!iv)
64
+ throw new JWEInvalid("JWE Initialization Vector missing");
65
+ if (!tag)
66
+ throw new JWEInvalid("JWE Authentication Tag missing");
67
+ if (!enc.cbc && tag.length !== 16)
68
+ throw new JWEInvalid("Invalid Authentication Tag length");
69
+ if (checkIvLength(enc, iv), cek instanceof Uint8Array && checkCekLength(cek, enc.cekBits), enc.cbc)
70
+ return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad);
71
+ const encKey = await rawKey(cek, enc.subtle, "decrypt");
64
72
  try {
65
73
  return new Uint8Array(await crypto.subtle.decrypt({
66
74
  additionalData: aad,
@@ -72,22 +80,6 @@ async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) {
72
80
  throw new JWEDecryptionFailed();
73
81
  }
74
82
  }
75
- async function encrypt(enc, plaintext, cek, iv, aad) {
76
- if (!isCryptoKey(cek) && !(cek instanceof Uint8Array))
77
- throw new TypeError(invalidKeyInput(cek, "CryptoKey", "KeyObject", "Uint8Array", "JSON Web Key"));
78
- return iv ? checkIvLength(enc, iv) : iv = generateIv(enc), cek instanceof Uint8Array && checkCekLength(cek, enc.cekBits), enc.cbc ? cbcEncrypt(enc, plaintext, cek, iv, aad) : gcmEncrypt(enc, plaintext, cek, iv, aad);
79
- }
80
- async function decrypt(enc, cek, ciphertext, iv, tag, aad) {
81
- if (!isCryptoKey(cek) && !(cek instanceof Uint8Array))
82
- throw new TypeError(invalidKeyInput(cek, "CryptoKey", "KeyObject", "Uint8Array", "JSON Web Key"));
83
- if (!iv)
84
- throw new JWEInvalid("JWE Initialization Vector missing");
85
- if (!tag)
86
- throw new JWEInvalid("JWE Authentication Tag missing");
87
- if (!enc.cbc && tag.length !== 16)
88
- throw new JWEInvalid("Invalid Authentication Tag length");
89
- return checkIvLength(enc, iv), cek instanceof Uint8Array && checkCekLength(cek, enc.cekBits), enc.cbc ? cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) : gcmDecrypt(enc, cek, ciphertext, iv, tag, aad);
90
- }
91
83
  export {
92
84
  checkCekLength,
93
85
  checkIvLength,
@@ -10,30 +10,14 @@ function supported(name) {
10
10
  if (typeof globalThis[name] > "u")
11
11
  throw new JOSENotSupported(`JWE "zip" (Compression Algorithm) Header Parameter requires the ${name} API.`);
12
12
  }
13
- async function compress(input) {
14
- supported("CompressionStream");
15
- const cs = new CompressionStream("deflate-raw"), writer = cs.writable.getWriter();
16
- writer.write(input).catch(() => {
17
- }), writer.close().catch(() => {
18
- });
19
- const chunks = [], reader = cs.readable.getReader();
20
- for (; ; ) {
21
- const { value, done } = await reader.read();
22
- if (done)
23
- break;
24
- chunks.push(value);
25
- }
26
- return concat(...chunks);
27
- }
28
- async function decompress(input, maxLength) {
29
- supported("DecompressionStream");
30
- const ds = new DecompressionStream("deflate-raw"), writer = ds.writable.getWriter();
13
+ async function transform(stream, input, maxLength = 1 / 0) {
14
+ const writer = stream.writable.getWriter();
31
15
  writer.write(input).catch(() => {
32
16
  }), writer.close().catch(() => {
33
17
  });
34
18
  const chunks = [];
35
19
  let length = 0;
36
- const reader = ds.readable.getReader();
20
+ const reader = stream.readable.getReader();
37
21
  for (; ; ) {
38
22
  const { value, done } = await reader.read();
39
23
  if (done)
@@ -43,6 +27,12 @@ async function decompress(input, maxLength) {
43
27
  }
44
28
  return concat(...chunks);
45
29
  }
30
+ async function compress(input) {
31
+ return supported("CompressionStream"), transform(new CompressionStream("deflate-raw"), input);
32
+ }
33
+ async function decompress(input, maxLength) {
34
+ return supported("DecompressionStream"), transform(new DecompressionStream("deflate-raw"), input, maxLength);
35
+ }
46
36
  export {
47
37
  compress,
48
38
  decompress,
@@ -105,15 +105,11 @@ function jweAlgorithm(alg) {
105
105
  function isJWECEKTransport(algorithm) {
106
106
  return algorithm.mode === "key-wrapping" || algorithm.mode === "key-encryption" || algorithm.mode === "key-agreement-with-key-wrapping";
107
107
  }
108
- function invalidJWEKeyManagementMode(_mode) {
109
- throw new TypeError("Invalid JWE key management mode");
110
- }
111
108
  function jweEncryption(enc) {
112
109
  return (typeof enc == "string" ? ENC[enc] : void 0) ?? unsupported("enc", "Encryption Algorithm");
113
110
  }
114
111
  export {
115
112
  JWE,
116
- invalidJWEKeyManagementMode,
117
113
  isJWECEKTransport,
118
114
  jweAlgorithm,
119
115
  jweEncryption
@@ -1,12 +1,10 @@
1
1
  import { decrypt, generateCek } from "./content_encryption.js";
2
- import { decodeBase64url, encodeBase64url, parseJoseHeader } from "./helpers.js";
2
+ import { decodeBase64url, encodeAsciiMember, parseJoseHeader, isDisjoint, isObject, validateCrit, validateAlgorithms, JWE_RECOGNIZED } from "./validate.js";
3
3
  import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from "../util/errors.js";
4
- import { isDisjoint, isObject } from "./type_checks.js";
5
4
  import { decryptKeyManagement } from "./key_management.js";
6
- import { concat, decoder, encode } from "./buffer_utils.js";
7
- import { validateCrit, validateAlgorithms, JWE_RECOGNIZED } from "./options.js";
5
+ import { decoder } from "./buffer_utils.js";
8
6
  import { prepareKey } from "./key.js";
9
- import { JWE, invalidJWEKeyManagementMode, isJWECEKTransport, jweAlgorithm, jweEncryption } from "./jwe_algorithms.js";
7
+ import { JWE, isJWECEKTransport, jweAlgorithm, jweEncryption } from "./jwe_algorithms.js";
10
8
  import { decompress, validateZip } from "./deflate.js";
11
9
  function snapshotSharedJWE(jwe) {
12
10
  const { aad, ciphertext, iv, protected: encodedProtected, tag, unprotected } = jwe;
@@ -44,10 +42,6 @@ function snapshotRecipientJWE(recipient) {
44
42
  ]));
45
43
  } else
46
44
  header = inputHeader;
47
- } catch (error) {
48
- return [void 0, headerAlg, error];
49
- }
50
- try {
51
45
  const { encrypted_key: encryptedKey } = recipient;
52
46
  return [{ encrypted_key: encryptedKey, header }, headerAlg];
53
47
  } catch (error) {
@@ -65,21 +59,15 @@ function checkRecipient(jwe) {
65
59
  }
66
60
  function shareJWE(jwe) {
67
61
  const { protected: encodedProtected, ciphertext, iv, tag, aad } = jwe;
68
- let parsedProt;
69
- encodedProtected !== void 0 && (parsedProt = parseJoseHeader(encodedProtected, JWEInvalid, "JWE Protected Header is invalid"));
70
- const protectedHeader = encodedProtected !== void 0 ? encode(encodedProtected) : new Uint8Array();
71
- return [
72
- parsedProt,
62
+ let protectedHeader;
63
+ return encodedProtected !== void 0 && (protectedHeader = parseJoseHeader(encodedProtected, JWEInvalid, "JWE Protected Header is invalid")), [
64
+ protectedHeader,
73
65
  decodeBase64url(ciphertext, "ciphertext", JWEInvalid),
74
66
  iv !== void 0 ? decodeBase64url(iv, "iv", JWEInvalid) : void 0,
75
67
  tag !== void 0 ? decodeBase64url(tag, "tag", JWEInvalid) : void 0,
76
- aad !== void 0 ? concat(protectedHeader, encode("."), encodeBase64url(aad, "aad", JWEInvalid)) : protectedHeader
68
+ encodeAsciiMember((encodedProtected ?? "") + (aad !== void 0 ? `.${aad}` : ""), "aad", JWEInvalid)
77
69
  ];
78
70
  }
79
- function decryptResult(jwe, decrypted) {
80
- const [plaintext, parsedProt, key, resolvedKey] = decrypted, { protected: encodedProtected, aad, unprotected, header } = jwe, result = { plaintext };
81
- return encodedProtected !== void 0 && (result.protectedHeader = parsedProt), aad !== void 0 && (result.additionalAuthenticatedData = decodeBase64url(aad, "aad", JWEInvalid)), unprotected !== void 0 && (result.sharedUnprotectedHeader = unprotected), header !== void 0 && (result.unprotectedHeader = header), resolvedKey ? { ...result, key } : result;
82
- }
83
71
  function prepareDecrypt(options) {
84
72
  return [
85
73
  options && validateAlgorithms("keyManagementAlgorithms", options.keyManagementAlgorithms),
@@ -89,20 +77,17 @@ function prepareDecrypt(options) {
89
77
  options?.maxDecompressedLength
90
78
  ];
91
79
  }
92
- async function decryptRecipient(jwe, token, shared, key) {
93
- const [parsedProt] = token, { header, unprotected } = jwe;
80
+ async function decryptJWE(jwe, shared, key, token = shareJWE(jwe)) {
81
+ const [protectedHeader, ciphertext, iv, tag, additionalAuthenticatedData] = token, { header, unprotected, aad } = jwe;
94
82
  let joseHeader;
95
83
  if (header !== void 0 || unprotected !== void 0) {
96
- if (!isDisjoint(parsedProt, header, unprotected))
84
+ if (!isDisjoint(protectedHeader, header, unprotected))
97
85
  throw new JWEInvalid("JWE Protected, JWE Unprotected Header, and JWE Per-Recipient Unprotected Header Parameter names must be disjoint");
98
- joseHeader = { ...parsedProt, ...header, ...unprotected };
86
+ joseHeader = { ...protectedHeader, ...header, ...unprotected };
99
87
  } else
100
- joseHeader = parsedProt ?? {};
101
- return decryptRecipientCore(jwe, token, shared, key, joseHeader);
102
- }
103
- async function decryptRecipientCore(jwe, token, shared, key, joseHeader) {
104
- const [keyManagementAlgorithms, contentEncryptionAlgorithms, crit, maxPBES2Count, maxDecompressedLength] = shared, [parsedProt, ciphertext, iv, tag, additionalData] = token, { encrypted_key: encodedKey } = jwe;
105
- validateCrit(JWEInvalid, JWE_RECOGNIZED, crit, parsedProt, joseHeader), validateZip(joseHeader, parsedProt);
88
+ joseHeader = protectedHeader ?? {};
89
+ const [keyManagementAlgorithms, contentEncryptionAlgorithms, crit, maxPBES2Count, maxDecompressedLength] = shared, { encrypted_key: encodedKey } = jwe;
90
+ validateCrit(JWEInvalid, JWE_RECOGNIZED, crit, protectedHeader, joseHeader), validateZip(joseHeader, protectedHeader);
106
91
  const { alg, enc } = joseHeader;
107
92
  if (typeof alg != "string" || !alg)
108
93
  throw new JWEInvalid("missing JWE Algorithm (alg) in JWE Header");
@@ -137,28 +122,13 @@ async function decryptRecipientCore(jwe, token, shared, key, joseHeader) {
137
122
  encryptedKey = new Uint8Array();
138
123
  }
139
124
  let resolvedKey = !1;
140
- typeof key == "function" && (key = await key(parsedProt, jwe), resolvedKey = !0);
125
+ typeof key == "function" && (key = await key(protectedHeader, jwe), resolvedKey = !0);
141
126
  const algEntry = selected ?? jweAlgorithm(alg);
142
127
  isJWECEKTransport(algEntry) && encryptedKey === void 0 && (encryptedKey = new Uint8Array());
143
- let k;
144
- const mode = algEntry.mode;
145
- switch (mode) {
146
- case "direct-encryption":
147
- k = await prepareKey(encEntry, key, "decrypt");
148
- break;
149
- case "direct-key-agreement":
150
- case "key-wrapping":
151
- case "key-encryption":
152
- case "key-agreement-with-key-wrapping":
153
- case "integrated-encryption":
154
- k = await prepareKey(algEntry, key, "decrypt");
155
- break;
156
- default:
157
- invalidJWEKeyManagementMode(mode);
158
- }
128
+ const k = await prepareKey(algEntry.mode === "direct-encryption" ? encEntry : algEntry, key, "decrypt");
159
129
  let plaintext;
160
130
  if (algEntry.mode === "integrated-encryption")
161
- plaintext = await algEntry.decrypt(k, encryptedKey, ciphertext, additionalData, parsedProt, joseHeader);
131
+ plaintext = await algEntry.decrypt(k, encryptedKey, ciphertext, additionalAuthenticatedData, protectedHeader, joseHeader);
162
132
  else {
163
133
  const encryption = encEntry;
164
134
  let cek;
@@ -169,7 +139,7 @@ async function decryptRecipientCore(jwe, token, shared, key, joseHeader) {
169
139
  throw err;
170
140
  cek = generateCek(encryption);
171
141
  }
172
- plaintext = await decrypt(encryption, cek, ciphertext, iv, tag, additionalData);
142
+ plaintext = await decrypt(encryption, cek, ciphertext, iv, tag, additionalAuthenticatedData);
173
143
  }
174
144
  if (joseHeader.zip === "DEF") {
175
145
  const decompressionLimit = maxDecompressedLength ?? 25e4;
@@ -181,10 +151,16 @@ async function decryptRecipientCore(jwe, token, shared, key, joseHeader) {
181
151
  throw cause instanceof JWEInvalid ? cause : new JWEInvalid("Failed to decompress plaintext", { cause });
182
152
  });
183
153
  }
184
- return [plaintext, parsedProt, k, resolvedKey];
185
- }
186
- async function decryptJWE(jwe, shared, key) {
187
- return decryptRecipient(jwe, shareJWE(jwe), shared, key);
154
+ return {
155
+ plaintext,
156
+ ...protectedHeader && { protectedHeader },
157
+ ...aad !== void 0 && {
158
+ additionalAuthenticatedData: decodeBase64url(aad, "aad", JWEInvalid)
159
+ },
160
+ ...unprotected && { sharedUnprotectedHeader: unprotected },
161
+ ...header && { unprotectedHeader: header },
162
+ ...resolvedKey && { key: k }
163
+ };
188
164
  }
189
165
  async function decryptCompact(jwe, shared, key) {
190
166
  if (jwe instanceof Uint8Array && (jwe = decoder.decode(jwe)), typeof jwe != "string")
@@ -192,27 +168,18 @@ async function decryptCompact(jwe, shared, key) {
192
168
  const { 0: protectedHeader, 1: encryptedKey, 2: iv, 3: ciphertext, 4: tag, length } = jwe.split(".");
193
169
  if (length !== 5)
194
170
  throw new JWEInvalid("Invalid Compact JWE");
195
- const flattened = {
171
+ return decryptJWE({
196
172
  ciphertext,
197
173
  iv: iv || void 0,
198
174
  protected: protectedHeader,
199
175
  tag: tag || void 0,
200
176
  encrypted_key: encryptedKey || void 0
201
- }, parsedProt = parseJoseHeader(protectedHeader, JWEInvalid, "JWE Protected Header is invalid"), protectedBytes = encode(protectedHeader), token = [
202
- parsedProt,
203
- decodeBase64url(ciphertext, "ciphertext", JWEInvalid),
204
- iv ? decodeBase64url(iv, "iv", JWEInvalid) : void 0,
205
- tag ? decodeBase64url(tag, "tag", JWEInvalid) : void 0,
206
- protectedBytes
207
- ];
208
- return decryptRecipientCore(flattened, token, shared, key, parsedProt);
177
+ }, shared, key);
209
178
  }
210
179
  export {
211
180
  checkRecipient,
212
181
  decryptCompact,
213
182
  decryptJWE,
214
- decryptRecipient,
215
- decryptResult,
216
183
  prepareDecrypt,
217
184
  shareJWE,
218
185
  snapshotRecipientJWE,
@@ -1,21 +1,22 @@
1
1
  import { encode as b64u } from "../util/base64url.js";
2
- import { checkCekLength, encrypt, generateCek } from "./content_encryption.js";
2
+ import { encrypt } from "./content_encryption.js";
3
3
  import { encryptKeyManagement } from "./key_management.js";
4
4
  import { JWEInvalid } from "../util/errors.js";
5
- import { assertUint8Array, isDisjoint, isObject } from "./type_checks.js";
6
- import { concat, encode } from "./buffer_utils.js";
7
- import { serializeJoseHeader, validateCrit, validateCritDuplicates, JWE_RECOGNIZED } from "./options.js";
5
+ import { assertUint8Array, isDisjoint, isObject, serializeJoseHeader, validateCrit, validateCritDuplicates, JWE_RECOGNIZED } from "./validate.js";
6
+ import { encode } from "./buffer_utils.js";
8
7
  import { prepareKey } from "./key.js";
9
- import { JWE, invalidJWEKeyManagementMode, isJWECEKTransport, jweAlgorithm, jweEncryption } from "./jwe_algorithms.js";
8
+ import { JWE, jweAlgorithm, jweEncryption } from "./jwe_algorithms.js";
10
9
  import { compress, validateZip } from "./deflate.js";
11
- import { unprotected } from "./helpers.js";
12
10
  function checkDisjoint(protectedHeader, unprotectedHeader, sharedUnprotectedHeader) {
13
11
  if (!isDisjoint(protectedHeader, unprotectedHeader, sharedUnprotectedHeader))
14
12
  throw new JWEInvalid("JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint");
15
13
  }
16
- function checkEncryptHeaders(input) {
14
+ function checkEncryptHeaders(input, options, sharedHeadersNormalized = !1) {
15
+ if (!input[1] && !input[2] && !input[3])
16
+ throw new JWEInvalid("either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()");
17
+ options !== void 0 && (input[8] = options?.crit);
17
18
  let [, protectedHeader, unprotectedHeader, sharedUnprotectedHeader, aad, cek, iv, keyManagementParameters, crit] = input;
18
- if (aad !== void 0 && assertUint8Array(aad, "JWE Additional Authenticated Data"), cek !== void 0 && assertUint8Array(cek, "JWE Content Encryption Key"), iv !== void 0 && assertUint8Array(iv, "JWE Initialization Vector"), protectedHeader !== void 0 && (protectedHeader = serializeJoseHeader(JWEInvalid, protectedHeader)[0], input[1] = protectedHeader), unprotectedHeader !== void 0 && (unprotectedHeader = serializeJoseHeader(JWEInvalid, unprotectedHeader)[0], input[2] = unprotectedHeader), sharedUnprotectedHeader !== void 0 && (sharedUnprotectedHeader = serializeJoseHeader(JWEInvalid, sharedUnprotectedHeader)[0], input[3] = sharedUnprotectedHeader), keyManagementParameters !== void 0 && !isObject(keyManagementParameters))
19
+ if (aad !== void 0 && assertUint8Array(aad, "JWE Additional Authenticated Data"), cek !== void 0 && assertUint8Array(cek, "JWE Content Encryption Key"), iv !== void 0 && assertUint8Array(iv, "JWE Initialization Vector"), !sharedHeadersNormalized && protectedHeader !== void 0 && (protectedHeader = serializeJoseHeader(JWEInvalid, protectedHeader)[0], input[1] = protectedHeader), unprotectedHeader !== void 0 && (unprotectedHeader = serializeJoseHeader(JWEInvalid, unprotectedHeader)[0], input[2] = unprotectedHeader), !sharedHeadersNormalized && sharedUnprotectedHeader !== void 0 && (sharedUnprotectedHeader = serializeJoseHeader(JWEInvalid, sharedUnprotectedHeader)[0], input[3] = sharedUnprotectedHeader), keyManagementParameters !== void 0 && !isObject(keyManagementParameters))
19
20
  throw new TypeError("JWE Key Management Parameters must be an object");
20
21
  checkDisjoint(protectedHeader, unprotectedHeader, sharedUnprotectedHeader);
21
22
  const joseHeader = {
@@ -27,82 +28,48 @@ function checkEncryptHeaders(input) {
27
28
  const { alg, enc } = joseHeader;
28
29
  if (typeof alg != "string" || !alg)
29
30
  throw new JWEInvalid('JWE "alg" (Algorithm) Header Parameter missing or invalid');
30
- if (JWE[alg]?.mode === "integrated-encryption") {
31
+ const algEntry = JWE[alg];
32
+ if (algEntry?.mode === "integrated-encryption") {
31
33
  if (enc !== void 0)
32
34
  throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must not be present for integrated encryption');
33
35
  if (cek !== void 0)
34
36
  throw new TypeError(`setContentEncryptionKey cannot be called with JWE "alg" (Algorithm) Header ${alg}`);
35
37
  if (iv !== void 0)
36
38
  throw new TypeError(`setInitializationVector cannot be called with JWE "alg" (Algorithm) Header ${alg}`);
37
- return [joseHeader, alg, void 0, void 0];
39
+ return [joseHeader, void 0, algEntry];
38
40
  }
39
41
  if (typeof enc != "string" || !enc)
40
42
  throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');
41
- return [joseHeader, alg, enc, jweEncryption(enc)];
42
- }
43
- function checkProducedEncryptedKey(encryptedKey) {
44
- if (!(encryptedKey instanceof Uint8Array) || !encryptedKey.byteLength)
45
- throw new TypeError("JWE key management algorithm did not produce an Encrypted Key");
46
- }
47
- async function transportCek(algEntry, encEntry, key, providedCek, joseHeader, providedParameters) {
48
- const preparedKey = await prepareKey(algEntry, key, "encrypt"), cek = providedCek ?? generateCek(encEntry);
49
- checkCekLength(cek, encEntry.cekBits);
50
- const [, encryptedKey, parameters] = await encryptKeyManagement(algEntry, encEntry, preparedKey, joseHeader, cek, providedParameters);
51
- return checkProducedEncryptedKey(encryptedKey), [cek, encryptedKey, parameters];
43
+ return [joseHeader, jweEncryption(enc), algEntry];
52
44
  }
53
- async function encryptJWE(input, checked, key, resolvedAlgEntry) {
54
- const [joseHeader, alg, , encEntry] = checked, [inputPlaintext, inputProtectedHeader, inputUnprotectedHeader, sharedUnprotectedHeader, aad, providedCek, inputIv, keyManagementParameters, , unprotectedParameters] = input;
45
+ async function encryptJWE(input, checked, key) {
46
+ const [joseHeader, encEntry, selected] = checked, [inputPlaintext, inputProtectedHeader, inputUnprotectedHeader, sharedUnprotectedHeader, aad, providedCek, inputIv, keyManagementParameters, , unprotectedParameters] = input;
55
47
  let protectedHeader = inputProtectedHeader, unprotectedHeader = inputUnprotectedHeader;
56
- const algEntry = resolvedAlgEntry ?? jweAlgorithm(alg);
57
- if (providedCek !== void 0 && !isJWECEKTransport(algEntry))
58
- throw new TypeError(`setContentEncryptionKey cannot be called with JWE "alg" (Algorithm) Header ${alg}`);
59
- let encryptedKey, parameters, cek, integratedKey;
60
- const mode = algEntry.mode;
61
- switch (mode) {
62
- case "direct-encryption":
63
- cek = await prepareKey(encEntry, key, "encrypt");
64
- break;
65
- case "direct-key-agreement": {
66
- const preparedKey = await prepareKey(algEntry, key, "encrypt");
67
- [cek, , parameters] = await encryptKeyManagement(algEntry, encEntry, preparedKey, joseHeader, void 0, keyManagementParameters);
68
- break;
69
- }
70
- case "key-wrapping":
71
- case "key-encryption":
72
- case "key-agreement-with-key-wrapping":
73
- [cek, encryptedKey, parameters] = await transportCek(algEntry, encEntry, key, providedCek, joseHeader, keyManagementParameters);
74
- break;
75
- case "integrated-encryption":
76
- integratedKey = await prepareKey(algEntry, key, "encrypt");
77
- break;
78
- default:
79
- invalidJWEKeyManagementMode(mode);
80
- }
81
- parameters && (unprotectedParameters ? unprotectedHeader = unprotectedHeader ? { ...unprotectedHeader, ...parameters } : parameters : protectedHeader = protectedHeader ? { ...protectedHeader, ...parameters } : parameters, checkDisjoint(protectedHeader, unprotectedHeader, sharedUnprotectedHeader));
82
- let protectedHeaderS, protectedHeaderB;
83
- protectedHeader ? (protectedHeaderS = b64u(JSON.stringify(protectedHeader)), protectedHeaderB = encode(protectedHeaderS)) : (protectedHeaderS = "", protectedHeaderB = new Uint8Array());
84
- let additionalData, aadMember;
85
- aad?.byteLength ? (aadMember = b64u(aad), additionalData = concat(protectedHeaderB, encode("."), encode(aadMember))) : additionalData = protectedHeaderB;
48
+ const algEntry = selected ?? jweAlgorithm(joseHeader.alg);
49
+ let encryptedKey, parameters, cek;
50
+ algEntry.mode === "integrated-encryption" ? cek = await prepareKey(algEntry, key, "encrypt") : [cek, encryptedKey, parameters] = await encryptKeyManagement(algEntry, encEntry, key, joseHeader, providedCek, keyManagementParameters), parameters && (unprotectedParameters ? unprotectedHeader = unprotectedHeader ? { ...unprotectedHeader, ...parameters } : parameters : protectedHeader = protectedHeader ? { ...protectedHeader, ...parameters } : parameters, checkDisjoint(protectedHeader, unprotectedHeader, sharedUnprotectedHeader));
51
+ const encodedProtectedHeader = protectedHeader ? b64u(JSON.stringify(protectedHeader)) : "", encodedAad = aad?.byteLength ? b64u(aad) : void 0, additionalAuthenticatedData = encode(encodedAad ? `${encodedProtectedHeader}.${encodedAad}` : encodedProtectedHeader);
86
52
  let plaintext = inputPlaintext;
87
53
  joseHeader.zip === "DEF" && (plaintext = await compress(plaintext).catch((cause) => {
88
54
  throw new JWEInvalid("Failed to compress plaintext", { cause });
89
55
  }));
90
56
  let ciphertext, tag, iv;
91
- algEntry.mode === "integrated-encryption" ? [encryptedKey, ciphertext] = await algEntry.encrypt(integratedKey, plaintext, additionalData, protectedHeader, joseHeader, keyManagementParameters) : { ciphertext, tag, iv } = await encrypt(encEntry, plaintext, cek, inputIv, additionalData);
57
+ algEntry.mode === "integrated-encryption" ? [encryptedKey, ciphertext] = await algEntry.encrypt(cek, plaintext, additionalAuthenticatedData, protectedHeader, joseHeader, keyManagementParameters) : { ciphertext, tag, iv } = await encrypt(encEntry, plaintext, cek, inputIv, additionalAuthenticatedData);
92
58
  const jwe = {
93
59
  ciphertext: b64u(ciphertext)
94
60
  };
95
- return iv && (jwe.iv = b64u(iv)), tag && (jwe.tag = b64u(tag)), encryptedKey?.byteLength && (jwe.encrypted_key = b64u(encryptedKey)), aadMember && (jwe.aad = aadMember), protectedHeader && (jwe.protected = protectedHeaderS), sharedUnprotectedHeader && (jwe.unprotected = sharedUnprotectedHeader), unprotectedHeader && (jwe.header = unprotectedHeader), jwe;
61
+ return iv && (jwe.iv = b64u(iv)), tag && (jwe.tag = b64u(tag)), encryptedKey?.byteLength && (jwe.encrypted_key = b64u(encryptedKey)), encodedAad && (jwe.aad = encodedAad), protectedHeader && (jwe.protected = encodedProtectedHeader), sharedUnprotectedHeader && (jwe.unprotected = sharedUnprotectedHeader), unprotectedHeader && (jwe.header = unprotectedHeader), jwe;
96
62
  }
97
63
  async function createJWE(input, key, options) {
98
- if (!input[1] && !input[2] && !input[3])
99
- throw new JWEInvalid("either setProtectedHeader, setUnprotectedHeader, or sharedUnprotectedHeader must be called before #encrypt()");
100
- return options !== void 0 && (input[8] = options?.crit, input[9] = options ? unprotected in options : !1), encryptJWE(input, checkEncryptHeaders(input), key);
64
+ return encryptJWE(input, checkEncryptHeaders(input, options), key);
65
+ }
66
+ function compactJWE(jwe) {
67
+ return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join(".");
101
68
  }
102
69
  export {
103
70
  checkDisjoint,
104
71
  checkEncryptHeaders,
72
+ compactJWE,
105
73
  createJWE,
106
- encryptJWE,
107
- transportCek
74
+ encryptJWE
108
75
  };
@@ -34,8 +34,8 @@ function eddsa() {
34
34
  usages: sig
35
35
  };
36
36
  }
37
- function mldsa(bits) {
38
- const subtle = { name: `ML-DSA-${bits}` };
37
+ function mldsa(parameterSet) {
38
+ const subtle = { name: `ML-DSA-${parameterSet}` };
39
39
  return {
40
40
  kty: ["AKP"],
41
41
  subtle,