@lindorm/aes 0.5.5 → 0.6.1

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 (169) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/MERMAID.md +155 -0
  3. package/README.md +365 -199
  4. package/__tests__/INTEROP-RESULTS.md +66 -0
  5. package/__tests__/esm-smoke.test.ts +15 -0
  6. package/__tests__/fixtures/keys.ts +60 -0
  7. package/__tests__/helpers/buffer-utils.ts +11 -0
  8. package/__tests__/helpers/index.ts +2 -0
  9. package/__tests__/helpers/jwe-adapter.ts +117 -0
  10. package/__tests__/jose-jwe.test.ts +463 -0
  11. package/__tests__/noble-ciphers.test.ts +208 -0
  12. package/dist/classes/AesKit.d.ts +10 -8
  13. package/dist/classes/AesKit.d.ts.map +1 -1
  14. package/dist/classes/AesKit.js +73 -34
  15. package/dist/classes/AesKit.js.map +1 -1
  16. package/dist/constants/private/index.d.ts +0 -1
  17. package/dist/constants/private/index.d.ts.map +1 -1
  18. package/dist/constants/private/index.js +0 -1
  19. package/dist/constants/private/index.js.map +1 -1
  20. package/dist/constants/private/version.d.ts +3 -1
  21. package/dist/constants/private/version.d.ts.map +1 -1
  22. package/dist/constants/private/version.js +4 -2
  23. package/dist/constants/private/version.js.map +1 -1
  24. package/dist/interfaces/AesKit.d.ts +12 -7
  25. package/dist/interfaces/AesKit.d.ts.map +1 -1
  26. package/dist/mocks/mock-aes-kit.d.ts.map +1 -1
  27. package/dist/mocks/mock-aes-kit.js +12 -2
  28. package/dist/mocks/mock-aes-kit.js.map +1 -1
  29. package/dist/types/aes-decryption-data.d.ts +26 -17
  30. package/dist/types/aes-decryption-data.d.ts.map +1 -1
  31. package/dist/types/aes-encryption-data.d.ts +7 -17
  32. package/dist/types/aes-encryption-data.d.ts.map +1 -1
  33. package/dist/types/content.d.ts +1 -1
  34. package/dist/types/content.d.ts.map +1 -1
  35. package/dist/types/index.d.ts +1 -0
  36. package/dist/types/index.d.ts.map +1 -1
  37. package/dist/types/private/aes-data.d.ts.map +1 -1
  38. package/dist/types/private/aes-key-derivation.d.ts +1 -1
  39. package/dist/types/private/aes-key-derivation.d.ts.map +1 -1
  40. package/dist/types/private/auth-tag.d.ts +3 -0
  41. package/dist/types/private/auth-tag.d.ts.map +1 -1
  42. package/dist/types/private/content-encryption-key.d.ts +4 -2
  43. package/dist/types/private/content-encryption-key.d.ts.map +1 -1
  44. package/dist/types/private/index.d.ts +1 -1
  45. package/dist/types/private/index.d.ts.map +1 -1
  46. package/dist/types/private/index.js +1 -1
  47. package/dist/types/private/index.js.map +1 -1
  48. package/dist/types/private/prepared-encryption.d.ts +35 -0
  49. package/dist/types/private/prepared-encryption.d.ts.map +1 -0
  50. package/dist/types/private/{aes-string.js → prepared-encryption.js} +1 -1
  51. package/dist/types/private/prepared-encryption.js.map +1 -0
  52. package/dist/utils/is-aes.d.ts.map +1 -1
  53. package/dist/utils/is-aes.js +1 -5
  54. package/dist/utils/is-aes.js.map +1 -1
  55. package/dist/utils/parse-aes.js +3 -3
  56. package/dist/utils/parse-aes.js.map +1 -1
  57. package/dist/utils/private/aes-header.d.ts +42 -0
  58. package/dist/utils/private/aes-header.d.ts.map +1 -0
  59. package/dist/utils/private/aes-header.js +75 -0
  60. package/dist/utils/private/aes-header.js.map +1 -0
  61. package/dist/utils/private/calculate/calculate-content-encryption-key-size.js +3 -3
  62. package/dist/utils/private/calculate/calculate-key-wrap-encryption.d.ts.map +1 -1
  63. package/dist/utils/private/calculate/calculate-key-wrap-encryption.js +2 -1
  64. package/dist/utils/private/calculate/calculate-key-wrap-encryption.js.map +1 -1
  65. package/dist/utils/private/content.js +1 -1
  66. package/dist/utils/private/content.js.map +1 -1
  67. package/dist/utils/private/data/auth-tag-hmac.d.ts +2 -2
  68. package/dist/utils/private/data/auth-tag-hmac.d.ts.map +1 -1
  69. package/dist/utils/private/data/auth-tag-hmac.js +12 -4
  70. package/dist/utils/private/data/auth-tag-hmac.js.map +1 -1
  71. package/dist/utils/private/data/auth-tag.d.ts +2 -2
  72. package/dist/utils/private/data/auth-tag.d.ts.map +1 -1
  73. package/dist/utils/private/data/auth-tag.js +4 -2
  74. package/dist/utils/private/data/auth-tag.js.map +1 -1
  75. package/dist/utils/private/data/split-content-encryption-key.d.ts.map +1 -1
  76. package/dist/utils/private/data/split-content-encryption-key.js +6 -2
  77. package/dist/utils/private/data/split-content-encryption-key.js.map +1 -1
  78. package/dist/utils/private/diffie-hellman/diffie-hellman-key-wrap.d.ts +2 -2
  79. package/dist/utils/private/diffie-hellman/diffie-hellman-key-wrap.d.ts.map +1 -1
  80. package/dist/utils/private/diffie-hellman/diffie-hellman-key-wrap.js +12 -8
  81. package/dist/utils/private/diffie-hellman/diffie-hellman-key-wrap.js.map +1 -1
  82. package/dist/utils/private/diffie-hellman/diffie-hellman.d.ts +2 -2
  83. package/dist/utils/private/diffie-hellman/diffie-hellman.d.ts.map +1 -1
  84. package/dist/utils/private/diffie-hellman/diffie-hellman.js +12 -8
  85. package/dist/utils/private/diffie-hellman/diffie-hellman.js.map +1 -1
  86. package/dist/utils/private/diffie-hellman/shared-secret.d.ts.map +1 -1
  87. package/dist/utils/private/diffie-hellman/shared-secret.js +5 -1
  88. package/dist/utils/private/diffie-hellman/shared-secret.js.map +1 -1
  89. package/dist/utils/private/encoded-aes.d.ts +2 -2
  90. package/dist/utils/private/encoded-aes.d.ts.map +1 -1
  91. package/dist/utils/private/encoded-aes.js +86 -149
  92. package/dist/utils/private/encoded-aes.js.map +1 -1
  93. package/dist/utils/private/encrypt-content.d.ts +3 -0
  94. package/dist/utils/private/encrypt-content.d.ts.map +1 -0
  95. package/dist/utils/private/encrypt-content.js +35 -0
  96. package/dist/utils/private/encrypt-content.js.map +1 -0
  97. package/dist/utils/private/encrypt-encoded.d.ts +9 -0
  98. package/dist/utils/private/encrypt-encoded.d.ts.map +1 -0
  99. package/dist/utils/private/encrypt-encoded.js +53 -0
  100. package/dist/utils/private/encrypt-encoded.js.map +1 -0
  101. package/dist/utils/private/encrypt-serialised.d.ts +9 -0
  102. package/dist/utils/private/encrypt-serialised.d.ts.map +1 -0
  103. package/dist/utils/private/encrypt-serialised.js +48 -0
  104. package/dist/utils/private/encrypt-serialised.js.map +1 -0
  105. package/dist/utils/private/encrypt-tokenised.d.ts +9 -0
  106. package/dist/utils/private/encrypt-tokenised.d.ts.map +1 -0
  107. package/dist/utils/private/encrypt-tokenised.js +45 -0
  108. package/dist/utils/private/encrypt-tokenised.js.map +1 -0
  109. package/dist/utils/private/encryption.d.ts.map +1 -1
  110. package/dist/utils/private/encryption.js +27 -27
  111. package/dist/utils/private/encryption.js.map +1 -1
  112. package/dist/utils/private/index.d.ts +6 -0
  113. package/dist/utils/private/index.d.ts.map +1 -1
  114. package/dist/utils/private/index.js +6 -0
  115. package/dist/utils/private/index.js.map +1 -1
  116. package/dist/utils/private/key-derivation/concat-kdf.d.ts +14 -0
  117. package/dist/utils/private/key-derivation/concat-kdf.d.ts.map +1 -0
  118. package/dist/utils/private/key-derivation/concat-kdf.js +26 -0
  119. package/dist/utils/private/key-derivation/concat-kdf.js.map +1 -0
  120. package/dist/utils/private/key-derivation/index.d.ts +1 -1
  121. package/dist/utils/private/key-derivation/index.d.ts.map +1 -1
  122. package/dist/utils/private/key-derivation/index.js +1 -1
  123. package/dist/utils/private/key-derivation/index.js.map +1 -1
  124. package/dist/utils/private/key-derivation/pbkdf.d.ts +1 -0
  125. package/dist/utils/private/key-derivation/pbkdf.d.ts.map +1 -1
  126. package/dist/utils/private/key-derivation/pbkdf.js +13 -2
  127. package/dist/utils/private/key-derivation/pbkdf.js.map +1 -1
  128. package/dist/utils/private/key-wrap/ecb-key-wrap.d.ts.map +1 -1
  129. package/dist/utils/private/key-wrap/ecb-key-wrap.js +10 -3
  130. package/dist/utils/private/key-wrap/ecb-key-wrap.js.map +1 -1
  131. package/dist/utils/private/key-wrap/gcm-key-wrap.d.ts.map +1 -1
  132. package/dist/utils/private/key-wrap/gcm-key-wrap.js +6 -0
  133. package/dist/utils/private/key-wrap/gcm-key-wrap.js.map +1 -1
  134. package/dist/utils/private/oct/get-oct-key-key-wrap.d.ts +1 -1
  135. package/dist/utils/private/oct/get-oct-key-key-wrap.d.ts.map +1 -1
  136. package/dist/utils/private/oct/get-oct-key-key-wrap.js +7 -14
  137. package/dist/utils/private/oct/get-oct-key-key-wrap.js.map +1 -1
  138. package/dist/utils/private/oct/get-oct-pbkdf-key-wrap-keys.d.ts.map +1 -1
  139. package/dist/utils/private/oct/get-oct-pbkdf-key-wrap-keys.js +2 -0
  140. package/dist/utils/private/oct/get-oct-pbkdf-key-wrap-keys.js.map +1 -1
  141. package/dist/utils/private/prepare-encryption.d.ts +3 -0
  142. package/dist/utils/private/prepare-encryption.d.ts.map +1 -0
  143. package/dist/utils/private/prepare-encryption.js +27 -0
  144. package/dist/utils/private/prepare-encryption.js.map +1 -0
  145. package/dist/utils/private/serialised-aes.d.ts.map +1 -1
  146. package/dist/utils/private/serialised-aes.js +38 -46
  147. package/dist/utils/private/serialised-aes.js.map +1 -1
  148. package/dist/utils/private/tokenised-aes.d.ts +3 -3
  149. package/dist/utils/private/tokenised-aes.d.ts.map +1 -1
  150. package/dist/utils/private/tokenised-aes.js +73 -55
  151. package/dist/utils/private/tokenised-aes.js.map +1 -1
  152. package/dist/utils/private/validate-version.d.ts +2 -0
  153. package/dist/utils/private/validate-version.d.ts.map +1 -0
  154. package/dist/utils/private/validate-version.js +27 -0
  155. package/dist/utils/private/validate-version.js.map +1 -0
  156. package/jest.config.interop.mjs +24 -0
  157. package/package.json +18 -16
  158. package/tsconfig.interop.json +9 -0
  159. package/dist/constants/private/format.d.ts +0 -2
  160. package/dist/constants/private/format.d.ts.map +0 -1
  161. package/dist/constants/private/format.js +0 -5
  162. package/dist/constants/private/format.js.map +0 -1
  163. package/dist/types/private/aes-string.d.ts +0 -21
  164. package/dist/types/private/aes-string.d.ts.map +0 -1
  165. package/dist/types/private/aes-string.js.map +0 -1
  166. package/dist/utils/private/key-derivation/hkdf.d.ts +0 -13
  167. package/dist/utils/private/key-derivation/hkdf.d.ts.map +0 -1
  168. package/dist/utils/private/key-derivation/hkdf.js +0 -12
  169. package/dist/utils/private/key-derivation/hkdf.js.map +0 -1
@@ -0,0 +1,66 @@
1
+ # AES Interop Test Results
2
+
3
+ ## Summary
4
+
5
+ All 59 interop tests pass. Zero divergences found between `@lindorm/aes`,
6
+ `@noble/ciphers`, and `jose`.
7
+
8
+ | Suite | Tests | Pass | Fail | Skip |
9
+ | ------------- | ------ | ------ | ----- | ----- |
10
+ | noble-ciphers | 21 | 21 | 0 | 0 |
11
+ | jose-jwe | 38 | 38 | 0 | 0 |
12
+ | **Total** | **59** | **59** | **0** | **0** |
13
+
14
+ ## noble/ciphers Primitive Tests
15
+
16
+ | Primitive | Key Sizes | Direction | Result |
17
+ | ----------------- | ------------- | ------------------------------ | ------ |
18
+ | AES-GCM | 128, 192, 256 | ours → noble | PASS |
19
+ | AES-GCM | 128, 192, 256 | noble → ours | PASS |
20
+ | AES-GCM | 128, 192, 256 | byte-identical (pinned IV) | PASS |
21
+ | AES-KW (RFC 3394) | 128, 192, 256 | ours → noble | PASS |
22
+ | AES-KW (RFC 3394) | 128, 192, 256 | noble → ours | PASS |
23
+ | AES-KW (RFC 3394) | 128, 192, 256 | byte-identical (deterministic) | PASS |
24
+ | AES-CBC (raw) | 128, 192, 256 | byte-identical (PKCS7) | PASS |
25
+
26
+ ## jose JWE Tests
27
+
28
+ | Algorithm | Encryption | Direction | Result |
29
+ | ---------------------- | ------------------------------------------- | ----------- | ------ |
30
+ | dir | A128GCM, A192GCM, A256GCM | ours → jose | PASS |
31
+ | dir | A128GCM, A192GCM, A256GCM | jose → ours | PASS |
32
+ | dir | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512 | ours → jose | PASS |
33
+ | dir | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512 | jose → ours | PASS |
34
+ | A128KW, A192KW, A256KW | A128GCM, A256GCM | ours → jose | PASS |
35
+ | A128KW, A192KW, A256KW | A128GCM, A256GCM | jose → ours | PASS |
36
+ | A128KW, A192KW, A256KW | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512 | ours → jose | PASS |
37
+ | A128KW, A192KW, A256KW | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512 | jose → ours | PASS |
38
+ | A128GCMKW, A256GCMKW | A256GCM | ours → jose | PASS |
39
+ | A128GCMKW, A256GCMKW | A256GCM | jose → ours | PASS |
40
+ | Pinned deterministic | A256GCM (byte-identical) | comparison | PASS |
41
+ | Pinned deterministic | A256GCM (round-trip) | comparison | PASS |
42
+ | Pinned deterministic | A128CBC-HS256 (byte-identical) | comparison | PASS |
43
+ | Pinned deterministic | A128CBC-HS256 (round-trip) | comparison | PASS |
44
+
45
+ ## Validated RFC Compliance
46
+
47
+ - **RFC 7516** (JWE): AAD computation, flattened serialization format
48
+ - **RFC 7518** (JWA): AES-GCM, AES-CBC-HMAC-SHA2, AES Key Wrap, AES-GCM Key Wrap
49
+ - **RFC 3394**: AES Key Wrap (deterministic, AIV verification)
50
+
51
+ ## Notes
52
+
53
+ - GCMKW "ours → jose" direction uses a two-pass approach due to the circular
54
+ dependency between key-wrap params and JWE AAD. Content is re-encrypted with
55
+ the correct AAD after extracting key-wrap params from the first pass.
56
+ - jose v6 rejects `setContentEncryptionKey()` with `alg: "dir"`, so deterministic
57
+ pinned tests use A\*KW algorithms instead. Content encryption is identical
58
+ regardless of key management algorithm.
59
+ - `@noble/ciphers` GCM returns ciphertext with auth tag appended (last 16 bytes).
60
+ Tests correctly split/concatenate when converting between formats.
61
+
62
+ ## Environment
63
+
64
+ - Node.js >= 24.4.0
65
+ - `@noble/ciphers` ^1.2.1
66
+ - `jose` ^6.1.3
@@ -0,0 +1,15 @@
1
+ import { gcm, cbc, aeskw } from "@noble/ciphers/aes";
2
+ import { FlattenedEncrypt, flattenedDecrypt } from "jose";
3
+
4
+ describe("ESM import smoke test", () => {
5
+ test("should import @noble/ciphers", () => {
6
+ expect(gcm).toBeDefined();
7
+ expect(cbc).toBeDefined();
8
+ expect(aeskw).toBeDefined();
9
+ });
10
+
11
+ test("should import jose", () => {
12
+ expect(FlattenedEncrypt).toBeDefined();
13
+ expect(flattenedDecrypt).toBeDefined();
14
+ });
15
+ });
@@ -0,0 +1,60 @@
1
+ import { randomUUID } from "crypto";
2
+ import {
3
+ Kryptos,
4
+ KryptosAlgorithm,
5
+ KryptosEncryption,
6
+ KryptosKit,
7
+ } from "@lindorm/kryptos";
8
+
9
+ // Fixed raw symmetric keys for dir mode (CEK = key)
10
+ export const RAW_KEY_128 = Buffer.from("000102030405060708090a0b0c0d0e0f", "hex");
11
+ export const RAW_KEY_192 = Buffer.from(
12
+ "000102030405060708090a0b0c0d0e0f1011121314151617",
13
+ "hex",
14
+ );
15
+ export const RAW_KEY_256 = Buffer.from(
16
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
17
+ "hex",
18
+ );
19
+
20
+ // CBC-HMAC composite keys (double-length: half for HMAC, half for AES-CBC)
21
+ export const RAW_KEY_256_CBC = Buffer.from(
22
+ "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
23
+ "hex",
24
+ );
25
+ export const RAW_KEY_384_CBC = Buffer.from(
26
+ "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f",
27
+ "hex",
28
+ );
29
+ export const RAW_KEY_512_CBC = Buffer.from(
30
+ "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf",
31
+ "hex",
32
+ );
33
+
34
+ // Key Encryption Keys for KW modes
35
+ export const KEK_128 = Buffer.from("c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", "hex");
36
+ export const KEK_192 = Buffer.from(
37
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7",
38
+ "hex",
39
+ );
40
+ export const KEK_256 = Buffer.from(
41
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfefff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
42
+ "hex",
43
+ );
44
+
45
+ /**
46
+ * Helper to create a Kryptos oct key from raw bytes.
47
+ */
48
+ export const createOctKryptos = (
49
+ raw: Buffer,
50
+ algorithm: KryptosAlgorithm,
51
+ encryption?: KryptosEncryption,
52
+ ): Kryptos =>
53
+ KryptosKit.from.der({
54
+ id: randomUUID(),
55
+ algorithm,
56
+ encryption,
57
+ privateKey: raw,
58
+ type: "oct",
59
+ use: "enc",
60
+ });
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Convert Buffer to Uint8Array (zero-copy view).
3
+ */
4
+ export const toUint8Array = (buf: Buffer): Uint8Array =>
5
+ new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
6
+
7
+ /**
8
+ * Convert Uint8Array to Buffer (zero-copy view).
9
+ */
10
+ export const toBuffer = (arr: Uint8Array): Buffer =>
11
+ Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength);
@@ -0,0 +1,2 @@
1
+ export * from "./buffer-utils";
2
+ export * from "./jwe-adapter";
@@ -0,0 +1,117 @@
1
+ import type { FlattenedJWE } from "jose";
2
+ import type { AesDecryptionRecord } from "../../src/types/aes-decryption-data";
3
+ import type { AesEncryptionRecord } from "../../src/types/aes-encryption-data";
4
+
5
+ /**
6
+ * Build a JWE protected header JSON string, its base64url encoding,
7
+ * and the AAD buffer (ASCII bytes of the base64url-encoded header).
8
+ *
9
+ * Per RFC 7516 section 5.1 step 14, the JWE AAD is the ASCII representation
10
+ * of the base64url-encoded protected header.
11
+ *
12
+ * For A*GCMKW algorithms, the key-wrap iv and tag go into the protected header
13
+ * per RFC 7518 section 4.7.
14
+ */
15
+ export const buildProtectedHeader = (
16
+ algorithm: string,
17
+ encryption: string,
18
+ gcmkwParams?: { iv: Buffer; tag: Buffer },
19
+ ): {
20
+ headerJson: string;
21
+ headerB64u: string;
22
+ aadBuffer: Buffer;
23
+ } => {
24
+ const header: Record<string, string> = { alg: algorithm, enc: encryption };
25
+
26
+ if (gcmkwParams) {
27
+ header.iv = gcmkwParams.iv.toString("base64url");
28
+ header.tag = gcmkwParams.tag.toString("base64url");
29
+ }
30
+
31
+ const headerJson = JSON.stringify(header);
32
+ const headerB64u = Buffer.from(headerJson, "utf8").toString("base64url");
33
+ const aadBuffer = Buffer.from(headerB64u, "ascii");
34
+
35
+ return { headerJson, headerB64u, aadBuffer };
36
+ };
37
+
38
+ /**
39
+ * Convert our AesEncryptionRecord to a jose FlattenedJWE object.
40
+ *
41
+ * Field mapping:
42
+ * - protected: base64url-encoded protected header (passed in)
43
+ * - iv: base64url of record.initialisationVector
44
+ * - ciphertext: base64url of record.content
45
+ * - tag: base64url of record.authTag
46
+ * - encrypted_key: base64url of record.publicEncryptionKey (absent for dir)
47
+ */
48
+ export const toFlattenedJWE = (
49
+ record: AesEncryptionRecord,
50
+ headerB64u: string,
51
+ ): FlattenedJWE => {
52
+ const jwe: FlattenedJWE = {
53
+ protected: headerB64u,
54
+ iv: record.initialisationVector.toString("base64url"),
55
+ ciphertext: record.content.toString("base64url"),
56
+ tag: record.authTag.toString("base64url"),
57
+ };
58
+
59
+ if (record.publicEncryptionKey) {
60
+ jwe.encrypted_key = record.publicEncryptionKey.toString("base64url");
61
+ }
62
+
63
+ return jwe;
64
+ };
65
+
66
+ /**
67
+ * Convert a jose FlattenedJWE back to our AesDecryptionRecord + the AAD buffer.
68
+ *
69
+ * Parses the protected header to extract algorithm, encryption, and optional
70
+ * GCMKW parameters (iv, tag for key-wrap).
71
+ *
72
+ * Field mapping (inverse of toFlattenedJWE):
73
+ * - content: Buffer from base64url ciphertext
74
+ * - initialisationVector: Buffer from base64url iv
75
+ * - authTag: Buffer from base64url tag
76
+ * - publicEncryptionKey: Buffer from base64url encrypted_key (undefined for dir)
77
+ * - publicEncryptionIv: Buffer from protected header iv param (GCMKW only)
78
+ * - publicEncryptionTag: Buffer from protected header tag param (GCMKW only)
79
+ * - encryption: enc value from protected header
80
+ * - algorithm: alg value from protected header
81
+ */
82
+ export const fromFlattenedJWE = (
83
+ jwe: FlattenedJWE,
84
+ ): {
85
+ record: AesDecryptionRecord;
86
+ aad: Buffer;
87
+ } => {
88
+ if (!jwe.protected) {
89
+ throw new Error("FlattenedJWE missing protected header");
90
+ }
91
+ if (!jwe.iv) {
92
+ throw new Error("FlattenedJWE missing iv");
93
+ }
94
+ if (!jwe.tag) {
95
+ throw new Error("FlattenedJWE missing tag");
96
+ }
97
+
98
+ const headerJson = Buffer.from(jwe.protected, "base64url").toString("utf8");
99
+ const header = JSON.parse(headerJson) as Record<string, string>;
100
+
101
+ const aad = Buffer.from(jwe.protected, "ascii");
102
+
103
+ const record: AesDecryptionRecord = {
104
+ algorithm: header.alg as AesDecryptionRecord["algorithm"],
105
+ encryption: header.enc as AesDecryptionRecord["encryption"],
106
+ content: Buffer.from(jwe.ciphertext, "base64url"),
107
+ initialisationVector: Buffer.from(jwe.iv, "base64url"),
108
+ authTag: Buffer.from(jwe.tag, "base64url"),
109
+ publicEncryptionKey: jwe.encrypted_key
110
+ ? Buffer.from(jwe.encrypted_key, "base64url")
111
+ : undefined,
112
+ publicEncryptionIv: header.iv ? Buffer.from(header.iv, "base64url") : undefined,
113
+ publicEncryptionTag: header.tag ? Buffer.from(header.tag, "base64url") : undefined,
114
+ };
115
+
116
+ return { record, aad };
117
+ };