jose 6.1.3 → 6.2.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.
- package/dist/types/jwe/general/decrypt.d.ts +7 -0
- package/dist/types/jws/general/verify.d.ts +8 -0
- package/dist/types/types.d.ts +15 -4
- package/dist/webapi/jwe/flattened/decrypt.js +17 -2
- package/dist/webapi/jwe/flattened/encrypt.js +11 -3
- package/dist/webapi/jwe/general/encrypt.js +5 -2
- package/dist/webapi/jwks/remote.js +1 -1
- package/dist/webapi/lib/deflate.js +44 -0
- package/package.json +1 -1
|
@@ -16,6 +16,13 @@ export interface GeneralDecryptGetKey extends types.GetKeyFunction<types.JWEHead
|
|
|
16
16
|
* This function is exported (as a named export) from the main `'jose'` module entry point as well
|
|
17
17
|
* as from its subpath export `'jose/jwe/general/decrypt'`.
|
|
18
18
|
*
|
|
19
|
+
* > [!NOTE]\
|
|
20
|
+
* > The function iterates over the `recipients` array in the General JWE and returns the decryption
|
|
21
|
+
* > result of the first recipient entry that can be successfully decrypted. The result only contains
|
|
22
|
+
* > the plaintext and headers of that successfully decrypted recipient entry. Other recipient entries
|
|
23
|
+
* > in the General JWE are not validated, and their headers are not included in the returned result.
|
|
24
|
+
* > Recipients of a General JWE should only rely on the returned (decrypted) data.
|
|
25
|
+
*
|
|
19
26
|
* @param jwe General JWE.
|
|
20
27
|
* @param key Private Key or Secret to decrypt the JWE with. See
|
|
21
28
|
* {@link https://github.com/panva/jose/issues/210#jwe-alg Algorithm Key Requirements}.
|
|
@@ -18,6 +18,14 @@ export interface GeneralVerifyGetKey extends types.GenericGetKeyFunction<types.J
|
|
|
18
18
|
* This function is exported (as a named export) from the main `'jose'` module entry point as well
|
|
19
19
|
* as from its subpath export `'jose/jws/general/verify'`.
|
|
20
20
|
*
|
|
21
|
+
* > [!NOTE]\
|
|
22
|
+
* > The function iterates over the `signatures` array in the General JWS and returns the verification
|
|
23
|
+
* > result of the first signature entry that can be successfully verified. The result only contains
|
|
24
|
+
* > the payload, protected header, and unprotected header of that successfully verified signature
|
|
25
|
+
* > entry. Other signature entries in the General JWS are not validated, and their headers are not
|
|
26
|
+
* > included in the returned result. Recipients of a General JWS should only rely on the returned
|
|
27
|
+
* > (verified) data.
|
|
28
|
+
*
|
|
21
29
|
* @param jws General JWS.
|
|
22
30
|
* @param key Key to verify the JWS with. See
|
|
23
31
|
* {@link https://github.com/panva/jose/issues/210#jws-alg Algorithm Key Requirements}.
|
package/dist/types/types.d.ts
CHANGED
|
@@ -415,12 +415,12 @@ export interface JWEHeaderParameters extends JoseHeaderParameters {
|
|
|
415
415
|
crit?: string[]
|
|
416
416
|
|
|
417
417
|
/**
|
|
418
|
-
* JWE "zip" (Compression Algorithm) Header Parameter.
|
|
418
|
+
* JWE "zip" (Compression Algorithm) Header Parameter.
|
|
419
419
|
*
|
|
420
|
-
*
|
|
421
|
-
*
|
|
420
|
+
* The only supported value is `"DEF"` (DEFLATE). Requires the `CompressionStream` /
|
|
421
|
+
* `DecompressionStream` APIs to be available in the runtime.
|
|
422
422
|
*
|
|
423
|
-
* @see {@link https://www.rfc-editor.org/rfc/
|
|
423
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc7516#section-4.1.3 JWE "zip" Header Parameter}
|
|
424
424
|
*/
|
|
425
425
|
zip?: string
|
|
426
426
|
|
|
@@ -474,6 +474,17 @@ export interface DecryptOptions extends CritOption {
|
|
|
474
474
|
* this value is set to 10000.
|
|
475
475
|
*/
|
|
476
476
|
maxPBES2Count?: number
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Maximum allowed size (in bytes) of the decompressed plaintext when the JWE `"zip"` (Compression
|
|
480
|
+
* Algorithm) Header Parameter is present. By default this value is set to 250000 (250 KB). The
|
|
481
|
+
* value must be `0`, a positive safe integer, or `Infinity`.
|
|
482
|
+
*
|
|
483
|
+
* Set to `0` to reject all compressed JWEs during decryption.
|
|
484
|
+
*
|
|
485
|
+
* Set to `Infinity` to disable the decompressed size limit.
|
|
486
|
+
*/
|
|
487
|
+
maxDecompressedLength?: number
|
|
477
488
|
}
|
|
478
489
|
|
|
479
490
|
/** JWE Encryption options. */
|
|
@@ -10,6 +10,7 @@ import { validateCrit } from '../../lib/validate_crit.js';
|
|
|
10
10
|
import { validateAlgorithms } from '../../lib/validate_algorithms.js';
|
|
11
11
|
import { normalizeKey } from '../../lib/normalize_key.js';
|
|
12
12
|
import { checkKeyType } from '../../lib/check_key_type.js';
|
|
13
|
+
import { decompress } from '../../lib/deflate.js';
|
|
13
14
|
export async function flattenedDecrypt(jwe, key, options) {
|
|
14
15
|
if (!isObject(jwe)) {
|
|
15
16
|
throw new JWEInvalid('Flattened JWE must be an object');
|
|
@@ -60,8 +61,11 @@ export async function flattenedDecrypt(jwe, key, options) {
|
|
|
60
61
|
...jwe.unprotected,
|
|
61
62
|
};
|
|
62
63
|
validateCrit(JWEInvalid, new Map(), options?.crit, parsedProt, joseHeader);
|
|
63
|
-
if (joseHeader.zip !== undefined) {
|
|
64
|
-
throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter
|
|
64
|
+
if (joseHeader.zip !== undefined && joseHeader.zip !== 'DEF') {
|
|
65
|
+
throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value.');
|
|
66
|
+
}
|
|
67
|
+
if (joseHeader.zip !== undefined && !parsedProt?.zip) {
|
|
68
|
+
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header Parameter MUST be in a protected header.');
|
|
65
69
|
}
|
|
66
70
|
const { alg, enc } = joseHeader;
|
|
67
71
|
if (typeof alg !== 'string' || !alg) {
|
|
@@ -141,6 +145,17 @@ export async function flattenedDecrypt(jwe, key, options) {
|
|
|
141
145
|
}
|
|
142
146
|
const plaintext = await decrypt(enc, cek, ciphertext, iv, tag, additionalData);
|
|
143
147
|
const result = { plaintext };
|
|
148
|
+
if (joseHeader.zip === 'DEF') {
|
|
149
|
+
const maxDecompressedLength = options?.maxDecompressedLength ?? 250_000;
|
|
150
|
+
if (maxDecompressedLength === 0) {
|
|
151
|
+
throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported.');
|
|
152
|
+
}
|
|
153
|
+
if (maxDecompressedLength !== Infinity &&
|
|
154
|
+
(!Number.isSafeInteger(maxDecompressedLength) || maxDecompressedLength < 1)) {
|
|
155
|
+
throw new TypeError('maxDecompressedLength must be 0, a positive safe integer, or Infinity');
|
|
156
|
+
}
|
|
157
|
+
result.plaintext = await decompress(plaintext, maxDecompressedLength);
|
|
158
|
+
}
|
|
144
159
|
if (jwe.protected !== undefined) {
|
|
145
160
|
result.protectedHeader = parsedProt;
|
|
146
161
|
}
|
|
@@ -8,6 +8,7 @@ import { concat, encode } from '../../lib/buffer_utils.js';
|
|
|
8
8
|
import { validateCrit } from '../../lib/validate_crit.js';
|
|
9
9
|
import { normalizeKey } from '../../lib/normalize_key.js';
|
|
10
10
|
import { checkKeyType } from '../../lib/check_key_type.js';
|
|
11
|
+
import { compress } from '../../lib/deflate.js';
|
|
11
12
|
export class FlattenedEncrypt {
|
|
12
13
|
#plaintext;
|
|
13
14
|
#protectedHeader;
|
|
@@ -82,8 +83,11 @@ export class FlattenedEncrypt {
|
|
|
82
83
|
...this.#sharedUnprotectedHeader,
|
|
83
84
|
};
|
|
84
85
|
validateCrit(JWEInvalid, new Map(), options?.crit, this.#protectedHeader, joseHeader);
|
|
85
|
-
if (joseHeader.zip !== undefined) {
|
|
86
|
-
throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter
|
|
86
|
+
if (joseHeader.zip !== undefined && joseHeader.zip !== 'DEF') {
|
|
87
|
+
throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value.');
|
|
88
|
+
}
|
|
89
|
+
if (joseHeader.zip !== undefined && !this.#protectedHeader?.zip) {
|
|
90
|
+
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header Parameter MUST be in a protected header.');
|
|
87
91
|
}
|
|
88
92
|
const { alg, enc } = joseHeader;
|
|
89
93
|
if (typeof alg !== 'string' || !alg) {
|
|
@@ -139,7 +143,11 @@ export class FlattenedEncrypt {
|
|
|
139
143
|
else {
|
|
140
144
|
additionalData = protectedHeaderB;
|
|
141
145
|
}
|
|
142
|
-
|
|
146
|
+
let plaintext = this.#plaintext;
|
|
147
|
+
if (joseHeader.zip === 'DEF') {
|
|
148
|
+
plaintext = await compress(plaintext);
|
|
149
|
+
}
|
|
150
|
+
const { ciphertext, tag, iv } = await encrypt(enc, plaintext, cek, this.#iv, additionalData);
|
|
143
151
|
const jwe = {
|
|
144
152
|
ciphertext: b64u(ciphertext),
|
|
145
153
|
};
|
|
@@ -133,8 +133,11 @@ export class GeneralEncrypt {
|
|
|
133
133
|
throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients');
|
|
134
134
|
}
|
|
135
135
|
validateCrit(JWEInvalid, new Map(), recipient.options.crit, this.#protectedHeader, joseHeader);
|
|
136
|
-
if (joseHeader.zip !== undefined) {
|
|
137
|
-
throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter
|
|
136
|
+
if (joseHeader.zip !== undefined && joseHeader.zip !== 'DEF') {
|
|
137
|
+
throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value.');
|
|
138
|
+
}
|
|
139
|
+
if (joseHeader.zip !== undefined && !this.#protectedHeader?.zip) {
|
|
140
|
+
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header Parameter MUST be in a protected header.');
|
|
138
141
|
}
|
|
139
142
|
}
|
|
140
143
|
const cek = generateCek(enc);
|
|
@@ -9,7 +9,7 @@ function isCloudflareWorkers() {
|
|
|
9
9
|
let USER_AGENT;
|
|
10
10
|
if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {
|
|
11
11
|
const NAME = 'jose';
|
|
12
|
-
const VERSION = 'v6.
|
|
12
|
+
const VERSION = 'v6.2.0';
|
|
13
13
|
USER_AGENT = `${NAME}/${VERSION}`;
|
|
14
14
|
}
|
|
15
15
|
export const customFetch = Symbol();
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
|
|
2
|
+
import { concat } from './buffer_utils.js';
|
|
3
|
+
function supported(name) {
|
|
4
|
+
if (typeof globalThis[name] === 'undefined') {
|
|
5
|
+
throw new JOSENotSupported(`JWE "zip" (Compression Algorithm) Header Parameter requires the ${name} API.`);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export async function compress(input) {
|
|
9
|
+
supported('CompressionStream');
|
|
10
|
+
const cs = new CompressionStream('deflate-raw');
|
|
11
|
+
const writer = cs.writable.getWriter();
|
|
12
|
+
writer.write(input);
|
|
13
|
+
writer.close();
|
|
14
|
+
const chunks = [];
|
|
15
|
+
const reader = cs.readable.getReader();
|
|
16
|
+
for (;;) {
|
|
17
|
+
const { value, done } = await reader.read();
|
|
18
|
+
if (done)
|
|
19
|
+
break;
|
|
20
|
+
chunks.push(value);
|
|
21
|
+
}
|
|
22
|
+
return concat(...chunks);
|
|
23
|
+
}
|
|
24
|
+
export async function decompress(input, maxLength) {
|
|
25
|
+
supported('DecompressionStream');
|
|
26
|
+
const ds = new DecompressionStream('deflate-raw');
|
|
27
|
+
const writer = ds.writable.getWriter();
|
|
28
|
+
writer.write(input);
|
|
29
|
+
writer.close();
|
|
30
|
+
const chunks = [];
|
|
31
|
+
let length = 0;
|
|
32
|
+
const reader = ds.readable.getReader();
|
|
33
|
+
for (;;) {
|
|
34
|
+
const { value, done } = await reader.read();
|
|
35
|
+
if (done)
|
|
36
|
+
break;
|
|
37
|
+
chunks.push(value);
|
|
38
|
+
length += value.byteLength;
|
|
39
|
+
if (maxLength !== Infinity && length > maxLength) {
|
|
40
|
+
throw new JWEInvalid('Decompressed plaintext exceeded the configured limit');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return concat(...chunks);
|
|
44
|
+
}
|