jose 6.1.2 → 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/index.d.ts +4 -2
- 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 +20 -10
- package/dist/webapi/index.js +4 -2
- 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/check_key_type.js +2 -2
- package/dist/webapi/lib/deflate.js +44 -0
- package/package.json +1 -1
package/dist/types/index.d.ts
CHANGED
|
@@ -37,12 +37,14 @@ export type { KeyImportOptions } from './key/import.js';
|
|
|
37
37
|
export { decodeProtectedHeader } from './util/decode_protected_header.js';
|
|
38
38
|
export { decodeJwt } from './util/decode_jwt.js';
|
|
39
39
|
export type { ProtectedHeaderParameters } from './util/decode_protected_header.js';
|
|
40
|
-
|
|
40
|
+
import * as errors from './util/errors.js';
|
|
41
|
+
export { errors };
|
|
41
42
|
export { generateKeyPair } from './key/generate_key_pair.js';
|
|
42
43
|
export type { GenerateKeyPairResult, GenerateKeyPairOptions } from './key/generate_key_pair.js';
|
|
43
44
|
export { generateSecret } from './key/generate_secret.js';
|
|
44
45
|
export type { GenerateSecretOptions } from './key/generate_secret.js';
|
|
45
|
-
|
|
46
|
+
import * as base64url from './util/base64url.js';
|
|
47
|
+
export { base64url };
|
|
46
48
|
export type { CompactDecryptResult, CompactJWEHeaderParameters, CompactJWSHeaderParameters, CompactVerifyResult, CritOption, CryptoKey, DecryptOptions, EncryptOptions, FlattenedDecryptResult, FlattenedJWE, FlattenedJWS, FlattenedJWSInput, FlattenedVerifyResult, GeneralDecryptResult, GeneralJWE, GeneralJWS, GeneralJWSInput, GeneralVerifyResult, GetKeyFunction, JoseHeaderParameters, JSONWebKeySet, JWEHeaderParameters, JWEKeyManagementHeaderParameters, JWK_EC_Private, JWK_EC_Public, JWK_oct, JWK_OKP_Private, JWK_OKP_Public, JWK_RSA_Private, JWK_RSA_Public, JWK, JWKParameters, JWSHeaderParameters, JWTClaimVerificationOptions, JWTDecryptResult, JWTHeaderParameters, JWTPayload, JWTVerifyResult, KeyObject, ProduceJWT, ResolvedKey, SignOptions, VerifyOptions, } from './types.d.ts';
|
|
47
49
|
/**
|
|
48
50
|
* In prior releases this indicated whether a Node.js-specific build was loaded, this is now fixed
|
|
@@ -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
|
@@ -179,12 +179,11 @@ export interface GenericGetKeyFunction<IProtectedHeader, IToken, ReturnKeyTypes>
|
|
|
179
179
|
* @param IProtectedHeader Type definition of the JWE or JWS Protected Header.
|
|
180
180
|
* @param IToken Type definition of the consumed JWE or JWS token.
|
|
181
181
|
*/
|
|
182
|
-
export interface GetKeyFunction<IProtectedHeader, IToken>
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
> {}
|
|
182
|
+
export interface GetKeyFunction<IProtectedHeader, IToken> extends GenericGetKeyFunction<
|
|
183
|
+
IProtectedHeader,
|
|
184
|
+
IToken,
|
|
185
|
+
CryptoKey | KeyObject | JWK | Uint8Array
|
|
186
|
+
> {}
|
|
188
187
|
|
|
189
188
|
/**
|
|
190
189
|
* Flattened JWS definition for verify function inputs, allows payload as {@link !Uint8Array} for
|
|
@@ -416,12 +415,12 @@ export interface JWEHeaderParameters extends JoseHeaderParameters {
|
|
|
416
415
|
crit?: string[]
|
|
417
416
|
|
|
418
417
|
/**
|
|
419
|
-
* JWE "zip" (Compression Algorithm) Header Parameter.
|
|
418
|
+
* JWE "zip" (Compression Algorithm) Header Parameter.
|
|
420
419
|
*
|
|
421
|
-
*
|
|
422
|
-
*
|
|
420
|
+
* The only supported value is `"DEF"` (DEFLATE). Requires the `CompressionStream` /
|
|
421
|
+
* `DecompressionStream` APIs to be available in the runtime.
|
|
423
422
|
*
|
|
424
|
-
* @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}
|
|
425
424
|
*/
|
|
426
425
|
zip?: string
|
|
427
426
|
|
|
@@ -475,6 +474,17 @@ export interface DecryptOptions extends CritOption {
|
|
|
475
474
|
* this value is set to 10000.
|
|
476
475
|
*/
|
|
477
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
|
|
478
488
|
}
|
|
479
489
|
|
|
480
490
|
/** JWE Encryption options. */
|
package/dist/webapi/index.js
CHANGED
|
@@ -23,8 +23,10 @@ export { exportPKCS8, exportSPKI, exportJWK } from './key/export.js';
|
|
|
23
23
|
export { importSPKI, importPKCS8, importX509, importJWK } from './key/import.js';
|
|
24
24
|
export { decodeProtectedHeader } from './util/decode_protected_header.js';
|
|
25
25
|
export { decodeJwt } from './util/decode_jwt.js';
|
|
26
|
-
|
|
26
|
+
import * as errors from './util/errors.js';
|
|
27
|
+
export { errors };
|
|
27
28
|
export { generateKeyPair } from './key/generate_key_pair.js';
|
|
28
29
|
export { generateSecret } from './key/generate_secret.js';
|
|
29
|
-
|
|
30
|
+
import * as base64url from './util/base64url.js';
|
|
31
|
+
export { base64url };
|
|
30
32
|
export const cryptoRuntime = 'WebCryptoAPI';
|
|
@@ -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();
|
|
@@ -76,12 +76,12 @@ const asymmetricTypeCheck = (alg, key, usage) => {
|
|
|
76
76
|
case 'sign':
|
|
77
77
|
if (jwk.isPrivateJWK(key) && jwkMatchesOp(alg, key, usage))
|
|
78
78
|
return;
|
|
79
|
-
throw new TypeError(`JSON Web Key for this operation be a private JWK`);
|
|
79
|
+
throw new TypeError(`JSON Web Key for this operation must be a private JWK`);
|
|
80
80
|
case 'encrypt':
|
|
81
81
|
case 'verify':
|
|
82
82
|
if (jwk.isPublicJWK(key) && jwkMatchesOp(alg, key, usage))
|
|
83
83
|
return;
|
|
84
|
-
throw new TypeError(`JSON Web Key for this operation be a public JWK`);
|
|
84
|
+
throw new TypeError(`JSON Web Key for this operation must be a public JWK`);
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
if (!isKeyLike(key)) {
|
|
@@ -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
|
+
}
|