@interop/minimal-cipher 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/LICENSE +27 -0
  2. package/README.md +220 -0
  3. package/dist/Cipher.d.ts +210 -0
  4. package/dist/Cipher.d.ts.map +1 -0
  5. package/dist/Cipher.js +313 -0
  6. package/dist/Cipher.js.map +1 -0
  7. package/dist/DecryptTransformer.d.ts +14 -0
  8. package/dist/DecryptTransformer.d.ts.map +1 -0
  9. package/dist/DecryptTransformer.js +125 -0
  10. package/dist/DecryptTransformer.js.map +1 -0
  11. package/dist/EncryptTransformer.d.ts +28 -0
  12. package/dist/EncryptTransformer.d.ts.map +1 -0
  13. package/dist/EncryptTransformer.js +94 -0
  14. package/dist/EncryptTransformer.js.map +1 -0
  15. package/dist/algorithms/a256gcm.d.ts +39 -0
  16. package/dist/algorithms/a256gcm.d.ts.map +1 -0
  17. package/dist/algorithms/a256gcm.js +101 -0
  18. package/dist/algorithms/a256gcm.js.map +1 -0
  19. package/dist/algorithms/aeskw.d.ts +5 -0
  20. package/dist/algorithms/aeskw.d.ts.map +1 -0
  21. package/dist/algorithms/aeskw.js +68 -0
  22. package/dist/algorithms/aeskw.js.map +1 -0
  23. package/dist/algorithms/c20p-browser.d.ts +51 -0
  24. package/dist/algorithms/c20p-browser.d.ts.map +1 -0
  25. package/dist/algorithms/c20p-browser.js +106 -0
  26. package/dist/algorithms/c20p-browser.js.map +1 -0
  27. package/dist/algorithms/c20p.d.ts +51 -0
  28. package/dist/algorithms/c20p.d.ts.map +1 -0
  29. package/dist/algorithms/c20p.js +110 -0
  30. package/dist/algorithms/c20p.js.map +1 -0
  31. package/dist/algorithms/ecdhkdf.d.ts +24 -0
  32. package/dist/algorithms/ecdhkdf.d.ts.map +1 -0
  33. package/dist/algorithms/ecdhkdf.js +76 -0
  34. package/dist/algorithms/ecdhkdf.js.map +1 -0
  35. package/dist/algorithms/fips.d.ts +8 -0
  36. package/dist/algorithms/fips.d.ts.map +1 -0
  37. package/dist/algorithms/fips.js +8 -0
  38. package/dist/algorithms/fips.js.map +1 -0
  39. package/dist/algorithms/p256.d.ts +24 -0
  40. package/dist/algorithms/p256.d.ts.map +1 -0
  41. package/dist/algorithms/p256.js +106 -0
  42. package/dist/algorithms/p256.js.map +1 -0
  43. package/dist/algorithms/recommended.d.ts +8 -0
  44. package/dist/algorithms/recommended.d.ts.map +1 -0
  45. package/dist/algorithms/recommended.js +8 -0
  46. package/dist/algorithms/recommended.js.map +1 -0
  47. package/dist/algorithms/x25519-helper-browser.d.ts +7 -0
  48. package/dist/algorithms/x25519-helper-browser.d.ts.map +1 -0
  49. package/dist/algorithms/x25519-helper-browser.js +25 -0
  50. package/dist/algorithms/x25519-helper-browser.js.map +1 -0
  51. package/dist/algorithms/x25519-helper.d.ts +7 -0
  52. package/dist/algorithms/x25519-helper.d.ts.map +1 -0
  53. package/dist/algorithms/x25519-helper.js +51 -0
  54. package/dist/algorithms/x25519-helper.js.map +1 -0
  55. package/dist/algorithms/x25519.d.ts +44 -0
  56. package/dist/algorithms/x25519.d.ts.map +1 -0
  57. package/dist/algorithms/x25519.js +112 -0
  58. package/dist/algorithms/x25519.js.map +1 -0
  59. package/dist/algorithms/xc20p.d.ts +40 -0
  60. package/dist/algorithms/xc20p.d.ts.map +1 -0
  61. package/dist/algorithms/xc20p.js +160 -0
  62. package/dist/algorithms/xc20p.js.map +1 -0
  63. package/dist/baseX.d.ts +7 -0
  64. package/dist/baseX.d.ts.map +1 -0
  65. package/dist/baseX.js +11 -0
  66. package/dist/baseX.js.map +1 -0
  67. package/dist/crypto.d.ts +3 -0
  68. package/dist/crypto.d.ts.map +1 -0
  69. package/dist/crypto.js +3 -0
  70. package/dist/crypto.js.map +1 -0
  71. package/dist/index.d.ts +5 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +5 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/types.d.ts +119 -0
  76. package/dist/types.d.ts.map +1 -0
  77. package/dist/types.js +5 -0
  78. package/dist/types.js.map +1 -0
  79. package/dist/util.d.ts +2 -0
  80. package/dist/util.d.ts.map +1 -0
  81. package/dist/util.js +11 -0
  82. package/dist/util.js.map +1 -0
  83. package/package.json +99 -0
package/dist/Cipher.js ADDED
@@ -0,0 +1,313 @@
1
+ /*!
2
+ * Copyright (c) 2019-2026 Digital Bazaar, Inc.
3
+ */
4
+ import { base64url } from './baseX.js';
5
+ import * as fipsAlgorithm from './algorithms/fips.js';
6
+ import * as recAlgorithm from './algorithms/recommended.js';
7
+ import { DecryptTransformer } from './DecryptTransformer.js';
8
+ import { EncryptTransformer } from './EncryptTransformer.js';
9
+ import { stringToUint8Array } from './util.js';
10
+ const VERSIONS = ['recommended', 'fips'];
11
+ export class Cipher {
12
+ version;
13
+ cipher;
14
+ keyAgreement;
15
+ /**
16
+ * Creates a new Cipher instance that can be used to encrypt or decrypt
17
+ * data. A version must be supplied for encrypting data; the version
18
+ * indicates whether a FIPS-compliant algorithm or the latest recommended
19
+ * algorithm will be used.
20
+ *
21
+ * @param {string} [version='recommended'] - `fips` to use a FIPS-compliant
22
+ * algorithm, `recommended` to use the latest recommended algorithm when
23
+ * encrypting.
24
+ *
25
+ * @returns {Cipher} A Cipher used to encrypt and decrypt data.
26
+ */
27
+ constructor({ version = 'recommended' } = {}) {
28
+ if (typeof version !== 'string') {
29
+ throw new TypeError('"version" must be a string.');
30
+ }
31
+ if (!VERSIONS.includes(version)) {
32
+ throw new Error(`Unsupported version "${version}".`);
33
+ }
34
+ this.version = version;
35
+ if (version === 'fips') {
36
+ this.cipher = fipsAlgorithm.cipher;
37
+ this.keyAgreement = fipsAlgorithm.keyAgreement;
38
+ }
39
+ else {
40
+ this.cipher = recAlgorithm.cipher;
41
+ this.keyAgreement = recAlgorithm.keyAgreement;
42
+ }
43
+ }
44
+ /**
45
+ * Creates a TransformStream that will encrypt some data for one or more
46
+ * recipients and output a stream of chunks, each containing an object
47
+ * with the property `jwe` with a JWE value.
48
+ *
49
+ * A list of recipients must be given in the `recipients` array, identified
50
+ * by key agreement keys. An ephemeral ECDH key will be generated and used to
51
+ * derive shared KEKs that will wrap a randomly generated CEK. Each recipient
52
+ * in the `recipients` array will be updated to include the generated
53
+ * ephemeral ECDH key.
54
+ *
55
+ * @param {object} options - The options for the stream.
56
+ * @param {Array} options.recipients - An array of recipients for the
57
+ * encrypted content.
58
+ * @param {Function} options.keyResolver - A function that returns a Promise
59
+ * that resolves a key ID to a DH public key.
60
+ * @param {number} [options.chunkSize=1048576] - The size, in bytes,
61
+ * of the chunks to break the incoming data into.
62
+ *
63
+ * @returns {Promise<TransformStream>} Resolves to a TransformStream.
64
+ */
65
+ async createEncryptStream({ recipients, keyResolver, chunkSize }) {
66
+ const transformer = await this.createEncryptTransformer({
67
+ recipients,
68
+ keyResolver,
69
+ chunkSize
70
+ });
71
+ return new TransformStream(transformer);
72
+ }
73
+ /**
74
+ * Creates a TransformStream that will decrypt one or more chunks, each one
75
+ * that is an object with a `jwe` property that has a JWE as a value. The
76
+ * stream will output chunks of Uint8Arrays consisting of the decrypted
77
+ * data from each chunk.
78
+ *
79
+ * The only JWEs currently supported use an `alg` of `ECDH-ES+A256KW` and
80
+ * `enc` of `A256GCM` or `XC20P`. These parameters refer to data that has been
81
+ * encrypted using a 256-bit AES-GCM or XChaCha20Poly1305 content encryption
82
+ * key (CEK) that has been wrapped using a 256-bit AES-KW key encryption key
83
+ * (KEK) generated via a shared secret between an ephemeral ECDH key and a
84
+ * static ECDH key (ECDH-ES).
85
+ *
86
+ * @param {object} options - Options for createDecryptStream.
87
+ * @param {object} options.keyAgreementKey - A key agreement key API with
88
+ * `id` and deriveSecret`.
89
+ *
90
+ * @returns {Promise<TransformStream>} Resolves to the TransformStream.
91
+ */
92
+ async createDecryptStream({ keyAgreementKey }) {
93
+ const transformer = await this.createDecryptTransformer({ keyAgreementKey });
94
+ return new TransformStream(transformer);
95
+ }
96
+ /**
97
+ * Encrypts some data for one or more recipients and outputs a JWE. The
98
+ * data to encrypt can be given as a Uint8Array or a string.
99
+ *
100
+ * A list of recipients must be given in the `recipients` array, identified
101
+ * by key agreement keys. An ephemeral ECDH key will be generated and used to
102
+ * derive shared KEKs that will wrap a randomly generated CEK. Each recipient
103
+ * in the `recipients` array will be updated to include the generated
104
+ * ephemeral ECDH key.
105
+ *
106
+ * @param {object} options - Options for encrypt.
107
+ * @param {Uint8Array|string} [options.data] - The data to encrypt.
108
+ * @param {Array} options.recipients - An array of recipients for the\
109
+ * encrypted content.
110
+ * @param {Function} options.keyResolver - A function that returns a Promise
111
+ * that resolves a key ID to a DH public key.
112
+ *
113
+ * @returns {Promise<object>} Resolves to a JWE.
114
+ */
115
+ async encrypt({ data, recipients, keyResolver }) {
116
+ if (!(data instanceof Uint8Array) && typeof data !== 'string') {
117
+ throw new TypeError('"data" must be a Uint8Array or a string.');
118
+ }
119
+ let bytes = data;
120
+ if (data) {
121
+ bytes = stringToUint8Array(data);
122
+ }
123
+ const transformer = await this.createEncryptTransformer({
124
+ recipients,
125
+ keyResolver
126
+ });
127
+ return transformer.encrypt(bytes);
128
+ }
129
+ /**
130
+ * Encrypts an object. The object will be serialized to JSON and passed
131
+ * to `encrypt`. See `encrypt` for other parameters.
132
+ *
133
+ * @param {object} options - Options to use.
134
+ * @param {object} options.obj - The object to encrypt.
135
+ * @param {object} options.rest - The other options to be passed to encrypt.
136
+ *
137
+ * @returns {Promise<object>} Resolves to a JWE.
138
+ */
139
+ async encryptObject({ obj, ...rest }) {
140
+ if (typeof obj !== 'object') {
141
+ throw new TypeError('"obj" must be an object.');
142
+ }
143
+ return this.encrypt({ data: JSON.stringify(obj), ...rest });
144
+ }
145
+ /**
146
+ * Decrypts a single JWE.
147
+ *
148
+ * The only JWEs currently supported use an `alg` of `ECDH-ES+A256KW` and
149
+ * `enc` of `A256GCM` or `XC20P`. These parameters refer to data that has been
150
+ * encrypted using a 256-bit AES-GCM or XChaCha20Poly1305 content encryption
151
+ * key (CEK) that has been wrapped using a 256-bit AES-KW key encryption key
152
+ * (KEK) generated via a shared secret between an ephemeral ECDH key and a
153
+ * static ECDH key (ECDH-ES).
154
+ *
155
+ * Note: This version also supports decrypting data that was encrypted using
156
+ * `C20P` (ChaCha20Poly1305) for backwards compatibility.
157
+ *
158
+ * @param {object} options - Options for decrypt.
159
+ * @param {object} options.jwe - The JWE to decrypt.
160
+ * @param {object} options.keyAgreementKey - A key agreement key API with
161
+ * `id` and `deriveSecret`.
162
+ *
163
+ * @returns {Promise<Uint8Array>} - Resolves to the decrypted data
164
+ * or `null` if the decryption failed.
165
+ */
166
+ async decrypt({ jwe, keyAgreementKey }) {
167
+ const transformer = await this.createDecryptTransformer({ keyAgreementKey });
168
+ return transformer.decrypt(jwe);
169
+ }
170
+ /**
171
+ * Decrypts a JWE that must contain an encrypted object. This method will
172
+ * call `decrypt` and then `JSON.parse` the resulting decrypted UTF-8 data.
173
+ *
174
+ * @param {object} options - Options.
175
+ * @param {object} options.jwe - The JWE to decrypt.
176
+ * @param {object} options.keyAgreementKey - A key agreement key API with
177
+ * `id` and `deriveSecret`.
178
+ *
179
+ * @returns {Promise<object>} - Resolves to the decrypted object or `null`
180
+ * if the decryption failed.
181
+ */
182
+ async decryptObject({ jwe, keyAgreementKey }) {
183
+ const data = await this.decrypt({ jwe, keyAgreementKey });
184
+ if (!data) {
185
+ // decryption failed
186
+ return null;
187
+ }
188
+ return JSON.parse(new TextDecoder().decode(data));
189
+ }
190
+ /**
191
+ * Creates an EncryptTransformer that can be used to encrypt one or more
192
+ * chunks of data.
193
+ *
194
+ * A list of recipients must be given in the `recipients` array, identified
195
+ * by key agreement keys. An ephemeral ECDH key will be generated and used to
196
+ * derive shared KEKs that will wrap a randomly generated CEK. Each recipient
197
+ * in the `recipients` array will be updated to include the generated
198
+ * ephemeral ECDH key.
199
+ *
200
+ * @param {object} options - Options for the transformer.
201
+ * @param {Array} options.recipients - An array of recipients for the
202
+ * encrypted content.
203
+ * @param {Function} options.keyResolver - A function that returns
204
+ * a Promise that resolves a key ID to a DH public key.
205
+ * @param {number} [options.chunkSize=1048576] - The size, in bytes, of the
206
+ * chunks to break the incoming data into (only applies if returning a
207
+ * stream).
208
+ *
209
+ * @returns {Promise<EncryptTransformer>} - Resolves to an EncryptTransformer.
210
+ */
211
+ async createEncryptTransformer({ recipients, keyResolver, chunkSize }) {
212
+ if (!(Array.isArray(recipients) && recipients.length > 0)) {
213
+ throw new TypeError('"recipients" must be a non-empty array.');
214
+ }
215
+ // ensure all recipients use the supported key agreement algorithm
216
+ const { keyAgreement } = this;
217
+ const { JWE_ALG: alg } = keyAgreement;
218
+ if (!recipients.every(e => e.header && e.header.alg === alg)) {
219
+ throw new Error(`All recipients must use the algorithm "${alg}".`);
220
+ }
221
+ const { cipher } = this;
222
+ // generate a CEK for encrypting the content
223
+ const cek = await cipher.generateKey();
224
+ // derive ephemeral ECDH key pair to use with all recipients
225
+ const ephemeralKeyPair = await keyAgreement.generateEphemeralKeyPair();
226
+ recipients = await Promise.all(recipients.map(recipient => this._createRecipient({ recipient, cek, ephemeralKeyPair, keyResolver })));
227
+ // create shared protected header as associated authenticated data (aad)
228
+ // ASCII(BASE64URL(UTF8(JWE Protected Header)))
229
+ const enc = cipher.JWE_ENC;
230
+ const jweProtectedHeader = JSON.stringify({ enc });
231
+ const encodedProtectedHeader = base64url.encode(stringToUint8Array(jweProtectedHeader));
232
+ // UTF8-encoding a base64url-encoded string is the same as ASCII
233
+ const additionalData = stringToUint8Array(encodedProtectedHeader);
234
+ return new EncryptTransformer({
235
+ recipients,
236
+ encodedProtectedHeader,
237
+ cipher,
238
+ additionalData,
239
+ cek,
240
+ chunkSize
241
+ });
242
+ }
243
+ /**
244
+ * Creates a DecryptTransformer.
245
+ *
246
+ * @param {object} options - Options to use.
247
+ * @param {object} options.keyAgreementKey - A key agreement key API with
248
+ * `id` and `deriveSecret`.
249
+ *
250
+ * @returns {Promise<DecryptTransformer>} - Resolves to a DecryptTransformer.
251
+ */
252
+ async createDecryptTransformer({ keyAgreementKey }) {
253
+ return new DecryptTransformer({
254
+ keyAgreement: this.keyAgreement,
255
+ keyAgreementKey
256
+ });
257
+ }
258
+ /**
259
+ * Creates a JWE recipient using the given inputs.
260
+ *
261
+ * @see https://tools.ietf.org/html/rfc7516#section-4
262
+ *
263
+ * @param {object} options - Options to use.
264
+ * @param {object} options.recipient - A recipient with a header with a
265
+ * kid and alg.
266
+ * @param {object} options.ephemeralKeyPair - An ephemeral key pair.
267
+ * @param {object} options.cek - A content encryption key.
268
+ * @param {Function} options.keyResolver - A function that can resolve keys.
269
+ *
270
+ * @returns {Promise<object>} A JWE recipient object.
271
+ */
272
+ async _createRecipient({ recipient, ephemeralKeyPair, cek, keyResolver }) {
273
+ if (!recipient) {
274
+ throw new TypeError('"options.recipient" is required.');
275
+ }
276
+ if (!ephemeralKeyPair) {
277
+ throw new TypeError('"options.ephemeralKeyPair" is required.');
278
+ }
279
+ if (!cek) {
280
+ throw new TypeError('"options.cek" is required.');
281
+ }
282
+ if (!keyResolver) {
283
+ throw new TypeError('"options.keyResolver" is required.');
284
+ }
285
+ // resolve public DH key for recipient
286
+ const { keyAgreement } = this;
287
+ const staticPublicKey = await keyResolver({ id: recipient.header.kid });
288
+ // derive KEKs for each recipient
289
+ const derivedResult = await keyAgreement.kekFromStaticPeer({
290
+ ephemeralKeyPair,
291
+ staticPublicKey
292
+ });
293
+ const { kek, epk, apu, apv } = derivedResult;
294
+ const header = {
295
+ // contains the key id - kid
296
+ // contains the algorithm - alg
297
+ ...recipient.header,
298
+ // the ephemeralKeyPair
299
+ epk,
300
+ // base64 encoded ephemeralKeyPair's publicKey
301
+ apu,
302
+ // base64 encoded staticPublicKey's id
303
+ apv
304
+ };
305
+ return {
306
+ ...recipient,
307
+ header,
308
+ // the cek is wrapped so the recipient can use it to decrypt later
309
+ encrypted_key: await kek.wrapKey({ unwrappedKey: cek })
310
+ };
311
+ }
312
+ }
313
+ //# sourceMappingURL=Cipher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Cipher.js","sourceRoot":"","sources":["../src/Cipher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { JWE, KeyAgreementAlgorithm, KeyAgreementKey } from './types.js';
2
+ export declare class DecryptTransformer {
3
+ keyAgreement: KeyAgreementAlgorithm;
4
+ keyAgreementKey: KeyAgreementKey;
5
+ constructor({ keyAgreement, keyAgreementKey }?: {
6
+ keyAgreement?: KeyAgreementAlgorithm;
7
+ keyAgreementKey?: KeyAgreementKey;
8
+ });
9
+ transform(chunk: {
10
+ jwe: JWE;
11
+ }, controller: TransformStreamDefaultController): Promise<void>;
12
+ decrypt(jwe: JWE): Promise<Uint8Array | null>;
13
+ }
14
+ //# sourceMappingURL=DecryptTransformer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecryptTransformer.d.ts","sourceRoot":"","sources":["../src/DecryptTransformer.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAGV,GAAG,EACH,qBAAqB,EACrB,eAAe,EAEhB,MAAM,YAAY,CAAA;AAenB,qBAAa,kBAAkB;IAC7B,YAAY,EAAE,qBAAqB,CAAA;IACnC,eAAe,EAAE,eAAe,CAAA;gBAEpB,EACV,YAAY,EACZ,eAAe,EAChB,GAAE;QACD,YAAY,CAAC,EAAE,qBAAqB,CAAA;QACpC,eAAe,CAAC,EAAE,eAAe,CAAA;KAC7B;IAWA,SAAS,CACb,KAAK,EAAE;QAAE,GAAG,EAAE,GAAG,CAAA;KAAE,EACnB,UAAU,EAAE,gCAAgC,GAC3C,OAAO,CAAC,IAAI,CAAC;IAiBV,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;CAgFpD"}
@@ -0,0 +1,125 @@
1
+ /*!
2
+ * Copyright (c) 2019-2026 Digital Bazaar, Inc.
3
+ */
4
+ import { base64url } from './baseX.js';
5
+ import * as fipsAlgorithm from './algorithms/fips.js';
6
+ import * as recAlgorithm from './algorithms/recommended.js';
7
+ import { stringToUint8Array } from './util.js';
8
+ // support `C20P` for backwards compatibility
9
+ import * as c20p from './algorithms/c20p.js';
10
+ const CIPHER_ALGORITHMS = {
11
+ [fipsAlgorithm.cipher.JWE_ENC]: fipsAlgorithm.cipher,
12
+ [recAlgorithm.cipher.JWE_ENC]: recAlgorithm.cipher,
13
+ // backwards compatibility for decryption only (*not* encryption)
14
+ [c20p.JWE_ENC]: c20p
15
+ };
16
+ // only supported key algorithm
17
+ const KEY_ALGORITHM = 'ECDH-ES+A256KW';
18
+ export class DecryptTransformer {
19
+ keyAgreement;
20
+ keyAgreementKey;
21
+ constructor({ keyAgreement, keyAgreementKey } = {}) {
22
+ if (!keyAgreement) {
23
+ throw new TypeError('"keyAgreement" is a required parameter.');
24
+ }
25
+ if (!keyAgreementKey) {
26
+ throw new TypeError('"keyAgreementKey" is a required parameter.');
27
+ }
28
+ this.keyAgreement = keyAgreement;
29
+ this.keyAgreementKey = keyAgreementKey;
30
+ }
31
+ async transform(chunk, controller) {
32
+ // assumes `chunk` is an object with a JWE under the `jwe` property
33
+ if (!(chunk && typeof chunk === 'object')) {
34
+ throw new TypeError('"chunk" must be an object.');
35
+ }
36
+ const { jwe } = chunk;
37
+ const data = await this.decrypt(jwe);
38
+ if (data === null) {
39
+ const error = new Error('Invalid decryption key.');
40
+ error.name = 'DataError';
41
+ throw error;
42
+ }
43
+ controller.enqueue(data);
44
+ }
45
+ async decrypt(jwe) {
46
+ // validate JWE
47
+ if (!(jwe && typeof jwe === 'object')) {
48
+ throw new TypeError('"jwe" must be an object.');
49
+ }
50
+ if (typeof jwe.protected !== 'string') {
51
+ throw new TypeError('"jwe.protected" is missing or not a string.');
52
+ }
53
+ if (typeof jwe.iv !== 'string') {
54
+ throw new Error('Invalid or missing "iv".');
55
+ }
56
+ if (typeof jwe.ciphertext !== 'string') {
57
+ throw new Error('Invalid or missing "ciphertext".');
58
+ }
59
+ if (typeof jwe.tag !== 'string') {
60
+ throw new Error('Invalid or missing "tag".');
61
+ }
62
+ // validate encryption header
63
+ let header;
64
+ let additionalData;
65
+ try {
66
+ // ASCII(BASE64URL(UTF8(JWE Protected Header)))
67
+ additionalData = stringToUint8Array(jwe.protected);
68
+ header = JSON.parse(new TextDecoder().decode(base64url.decode(jwe.protected)));
69
+ }
70
+ catch {
71
+ throw new Error('Invalid JWE "protected" header.');
72
+ }
73
+ if (!(header.enc && typeof header.enc === 'string')) {
74
+ throw new Error('Invalid JWE "enc" header.');
75
+ }
76
+ const cipher = CIPHER_ALGORITHMS[header.enc];
77
+ if (!cipher) {
78
+ throw new Error('Unsupported encryption algorithm "${header.enc}".');
79
+ }
80
+ if (!Array.isArray(jwe.recipients)) {
81
+ throw new TypeError('"jwe.recipients" must be an array.');
82
+ }
83
+ // find `keyAgreementKey` matching recipient
84
+ const { keyAgreementKey } = this;
85
+ const recipient = _findRecipient(jwe.recipients, keyAgreementKey);
86
+ if (!recipient) {
87
+ throw new Error('No matching recipient found for key agreement key.');
88
+ }
89
+ // get wrapped CEK
90
+ const { encrypted_key: wrappedKey } = recipient;
91
+ if (typeof wrappedKey !== 'string') {
92
+ throw new Error('Invalid or missing "encrypted_key".');
93
+ }
94
+ // TODO: consider a cache of encrypted_key => CEKs to reduce unwrapping
95
+ // calls which may even need to hit the network (e.g., Web KMS)
96
+ // derive KEK and unwrap CEK
97
+ const { epk } = recipient.header;
98
+ const { keyAgreement } = this;
99
+ const { kek } = await keyAgreement.kekFromEphemeralPeer({
100
+ keyAgreementKey,
101
+ epk: epk
102
+ });
103
+ const cek = await kek.unwrapKey({ wrappedKey });
104
+ if (!cek) {
105
+ // failed to unwrap key
106
+ return null;
107
+ }
108
+ // decrypt content
109
+ const { ciphertext, iv, tag } = jwe;
110
+ return cipher.decrypt({
111
+ ciphertext: base64url.decode(ciphertext),
112
+ iv: base64url.decode(iv),
113
+ tag: base64url.decode(tag),
114
+ additionalData,
115
+ cek
116
+ });
117
+ }
118
+ }
119
+ function _findRecipient(recipients, key) {
120
+ return recipients.find(e => e.header &&
121
+ e.header.kid === key.id &&
122
+ !key.algorithm &&
123
+ e.header.alg === KEY_ALGORITHM);
124
+ }
125
+ //# sourceMappingURL=DecryptTransformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecryptTransformer.js","sourceRoot":"","sources":["../src/DecryptTransformer.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,KAAK,aAAa,MAAM,sBAAsB,CAAA;AACrD,OAAO,KAAK,YAAY,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAU9C,6CAA6C;AAC7C,OAAO,KAAK,IAAI,MAAM,sBAAsB,CAAA;AAE5C,MAAM,iBAAiB,GAAoC;IACzD,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,MAAM;IACpD,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC,MAAM;IAClD,iEAAiE;IACjE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI;CACrB,CAAA;AAED,+BAA+B;AAC/B,MAAM,aAAa,GAAG,gBAAgB,CAAA;AAEtC,MAAM,OAAO,kBAAkB;IAC7B,YAAY,CAAuB;IACnC,eAAe,CAAiB;IAEhC,YAAY,EACV,YAAY,EACZ,eAAe,KAIb,EAAE;QACJ,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAA;QAChE,CAAC;QACD,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAA;QACnE,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;QAChC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAA;IACxC,CAAC;IAED,KAAK,CAAC,SAAS,CACb,KAAmB,EACnB,UAA4C;QAE5C,mEAAmE;QACnE,IAAI,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAA;QACnD,CAAC;QACD,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAA;QAErB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACpC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAA;YAClD,KAAK,CAAC,IAAI,GAAG,WAAW,CAAA;YACxB,MAAM,KAAK,CAAA;QACb,CAAC;QAED,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAQ;QACpB,eAAe;QACf,IAAI,CAAC,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,SAAS,CAAC,0BAA0B,CAAC,CAAA;QACjD,CAAC;QACD,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YACtC,MAAM,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAA;QACpE,CAAC;QACD,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;QAC7C,CAAC;QACD,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;QACrD,CAAC;QACD,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;QAC9C,CAAC;QAED,6BAA6B;QAE7B,IAAI,MAAW,CAAA;QACf,IAAI,cAAc,CAAA;QAClB,IAAI,CAAC;YACH,+CAA+C;YAC/C,cAAc,GAAG,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;YAClD,MAAM,GAAG,IAAI,CAAC,KAAK,CACjB,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAC1D,CAAA;QACH,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;QACpD,CAAC;QACD,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;QAC9C,CAAC;QACD,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;QACtE,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,SAAS,CAAC,oCAAoC,CAAC,CAAA;QAC3D,CAAC;QAED,4CAA4C;QAC5C,MAAM,EAAE,eAAe,EAAE,GAAG,IAAI,CAAA;QAChC,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,CAAA;QACjE,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;QACvE,CAAC;QACD,kBAAkB;QAClB,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,SAAS,CAAA;QAC/C,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;QACxD,CAAC;QAED,uEAAuE;QACvE,+DAA+D;QAE/D,4BAA4B;QAC5B,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,MAAM,CAAA;QAChC,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,CAAA;QAC7B,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,YAAY,CAAC,oBAAoB,CAAC;YACtD,eAAe;YACf,GAAG,EAAE,GAAU;SAChB,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,CAAC,CAAA;QAC/C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,uBAAuB;YACvB,OAAO,IAAI,CAAA;QACb,CAAC;QAED,kBAAkB;QAClB,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,GAAG,CAAA;QACnC,OAAO,MAAM,CAAC,OAAO,CAAC;YACpB,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC;YACxC,EAAE,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC;YAC1B,cAAc;YACd,GAAG;SACJ,CAAC,CAAA;IACJ,CAAC;CACF;AAED,SAAS,cAAc,CACrB,UAAuB,EACvB,GAAoB;IAEpB,OAAO,UAAU,CAAC,IAAI,CACpB,CAAC,CAAC,EAAE,CACF,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE;QACvB,CAAC,GAAG,CAAC,SAAS;QACd,CAAC,CAAC,MAAM,CAAC,GAAG,KAAK,aAAa,CACjC,CAAA;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { CipherAlgorithm, JWE, Recipient } from './types.js';
2
+ interface EncryptTransformerOptions {
3
+ recipients: Recipient[];
4
+ encodedProtectedHeader: string;
5
+ cipher: CipherAlgorithm;
6
+ additionalData: Uint8Array;
7
+ cek: Uint8Array;
8
+ chunkSize?: number;
9
+ }
10
+ export declare class EncryptTransformer {
11
+ recipients: Recipient[];
12
+ encodedProtectedHeader: string;
13
+ cipher: CipherAlgorithm;
14
+ additionalData: Uint8Array;
15
+ cek: Uint8Array;
16
+ chunkSize: number;
17
+ offset: number;
18
+ totalOffset: number;
19
+ index: number;
20
+ buffer: Uint8Array;
21
+ constructor({ recipients, encodedProtectedHeader, cipher, additionalData, cek, chunkSize }: EncryptTransformerOptions);
22
+ start(): void;
23
+ transform(chunk: Uint8Array | null, controller: TransformStreamDefaultController): Promise<void>;
24
+ flush(controller: TransformStreamDefaultController): Promise<void>;
25
+ encrypt(data: Uint8Array): Promise<JWE>;
26
+ }
27
+ export {};
28
+ //# sourceMappingURL=EncryptTransformer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EncryptTransformer.d.ts","sourceRoot":"","sources":["../src/EncryptTransformer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAKjE,UAAU,yBAAyB;IACjC,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB,sBAAsB,EAAE,MAAM,CAAA;IAC9B,MAAM,EAAE,eAAe,CAAA;IACvB,cAAc,EAAE,UAAU,CAAA;IAC1B,GAAG,EAAE,UAAU,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,qBAAa,kBAAkB;IAC7B,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB,sBAAsB,EAAE,MAAM,CAAA;IAC9B,MAAM,EAAE,eAAe,CAAA;IACvB,cAAc,EAAE,UAAU,CAAA;IAC1B,GAAG,EAAE,UAAU,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAG,UAAU,CAAA;gBAEP,EACV,UAAU,EACV,sBAAsB,EACtB,MAAM,EACN,cAAc,EACd,GAAG,EACH,SAA8B,EAC/B,EAAE,yBAAyB;IAY5B,KAAK,IAAI,IAAI;IAIP,SAAS,CACb,KAAK,EAAE,UAAU,GAAG,IAAI,EACxB,UAAU,EAAE,gCAAgC,GAC3C,OAAO,CAAC,IAAI,CAAC;IAiCV,KAAK,CAAC,UAAU,EAAE,gCAAgC,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBlE,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC;CAkB9C"}
@@ -0,0 +1,94 @@
1
+ /*!
2
+ * Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
3
+ */
4
+ import { base64url } from './baseX.js';
5
+ // 1 MiB = 1048576
6
+ const DEFAULT_CHUNK_SIZE = 1048576;
7
+ export class EncryptTransformer {
8
+ recipients;
9
+ encodedProtectedHeader;
10
+ cipher;
11
+ additionalData;
12
+ cek;
13
+ chunkSize;
14
+ offset;
15
+ totalOffset;
16
+ index;
17
+ buffer;
18
+ constructor({ recipients, encodedProtectedHeader, cipher, additionalData, cek, chunkSize = DEFAULT_CHUNK_SIZE }) {
19
+ this.recipients = recipients;
20
+ this.encodedProtectedHeader = encodedProtectedHeader;
21
+ this.cipher = cipher;
22
+ this.additionalData = additionalData;
23
+ this.cek = cek;
24
+ this.chunkSize = chunkSize;
25
+ this.offset = 0;
26
+ this.totalOffset = 0;
27
+ this.index = 0;
28
+ }
29
+ start() {
30
+ this.buffer = new Uint8Array(this.chunkSize);
31
+ }
32
+ async transform(chunk, controller) {
33
+ const { buffer } = this;
34
+ // assumes `chunk` is a Uint8Array...
35
+ if (!(chunk instanceof Uint8Array)) {
36
+ throw new TypeError('"chunk" must be an object.');
37
+ }
38
+ while (chunk) {
39
+ const space = buffer.length - this.offset;
40
+ if (chunk.length <= space) {
41
+ buffer.set(chunk, this.offset);
42
+ this.offset += chunk.byteLength;
43
+ this.totalOffset += chunk.byteLength;
44
+ chunk = null;
45
+ }
46
+ else {
47
+ const partial = new Uint8Array(chunk.buffer, chunk.byteOffset, space);
48
+ chunk = new Uint8Array(chunk.buffer, chunk.byteOffset + space, chunk.length - space);
49
+ buffer.set(partial, this.offset);
50
+ this.offset += space;
51
+ this.totalOffset += space;
52
+ }
53
+ // flush if buffer is full and more data remains
54
+ if (chunk) {
55
+ await this.flush(controller);
56
+ }
57
+ }
58
+ }
59
+ async flush(controller) {
60
+ if (this.offset === 0) {
61
+ // nothing to flush
62
+ return;
63
+ }
64
+ // encrypt data
65
+ const { buffer } = this;
66
+ const data = new Uint8Array(buffer.buffer, buffer.byteOffset, this.offset);
67
+ const jwe = await this.encrypt(data);
68
+ // clear buffer
69
+ this.offset = 0;
70
+ controller.enqueue({
71
+ index: this.index++,
72
+ offset: this.totalOffset,
73
+ jwe
74
+ });
75
+ }
76
+ async encrypt(data) {
77
+ const { cipher, additionalData, cek } = this;
78
+ const { ciphertext, iv, tag } = await cipher.encrypt({
79
+ data,
80
+ additionalData,
81
+ cek
82
+ });
83
+ // represent encrypted data as JWE
84
+ const jwe = {
85
+ protected: this.encodedProtectedHeader,
86
+ recipients: this.recipients,
87
+ iv: base64url.encode(iv),
88
+ ciphertext: base64url.encode(ciphertext),
89
+ tag: base64url.encode(tag)
90
+ };
91
+ return jwe;
92
+ }
93
+ }
94
+ //# sourceMappingURL=EncryptTransformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EncryptTransformer.js","sourceRoot":"","sources":["../src/EncryptTransformer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { CipherDecryptOptions, CipherEncryptOptions, EncryptResult } from '../types.js';
2
+ export declare const JWE_ENC = "A256GCM";
3
+ /**
4
+ * Generates a content encryption key (CEK). The 256-bit key is intended to be
5
+ * used as an AES-GCM key.
6
+ *
7
+ * @returns {Promise<Uint8Array>} - Resolves to the generated key.
8
+ */
9
+ export declare function generateKey(): Promise<Uint8Array>;
10
+ /**
11
+ * Encrypts some data. The data will be encrypted using the given 256-bit
12
+ * AES-GCM content encryption key (CEK).
13
+ *
14
+ * @param {object} options - The options to use.
15
+ * @param {Uint8Array} options.data - The data to encrypt.
16
+ * @param {Uint8Array} options.additionalData - Optional additional
17
+ * authentication data.
18
+ * @param {Uint8Array} options.cek - The content encryption key to use.
19
+ *
20
+ * @returns {Promise<object>} - A Promise that resolves to
21
+ * `{ciphertext, iv, tag}`.
22
+ */
23
+ export declare function encrypt({ data, additionalData, cek }: CipherEncryptOptions): Promise<EncryptResult>;
24
+ /**
25
+ * Decrypts some encrypted data. The data must have been encrypted using
26
+ * the given 256-bit AES-GCM content encryption key.
27
+ *
28
+ * @param {object} options - The options to use.
29
+ * @param {Uint8Array} options.ciphertext - The data to decrypt.
30
+ * @param {Uint8Array} options.iv - The initialization vector.
31
+ * @param {Uint8Array} options.tag - The authentication tag.
32
+ * @param {Uint8Array} options.additionalData - Optional additional
33
+ * authentication data.
34
+ * @param {Uint8Array} options.cek - The content encryption key to use.
35
+ *
36
+ * @returns {Promise<Uint8Array>} - The decrypted data.
37
+ */
38
+ export declare function decrypt({ ciphertext, iv, tag, additionalData, cek }: CipherDecryptOptions): Promise<Uint8Array>;
39
+ //# sourceMappingURL=a256gcm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a256gcm.d.ts","sourceRoot":"","sources":["../../src/algorithms/a256gcm.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACd,MAAM,aAAa,CAAA;AAEpB,eAAO,MAAM,OAAO,YAAY,CAAA;AAEhC;;;;;GAKG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,UAAU,CAAC,CASvD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,OAAO,CAAC,EAC5B,IAAI,EACJ,cAAc,EACd,GAAG,EACJ,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CAiC/C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,OAAO,CAAC,EAC5B,UAAU,EACV,EAAE,EACF,GAAG,EACH,cAAc,EACd,GAAG,EACJ,EAAE,oBAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,CA+B5C"}