| import { JOSENotSupported, JWEInvalid } from '../util/errors.js'; | ||
| import { concat } from './buffer_utils.js'; | ||
| function supported(name) { | ||
| if (typeof globalThis[name] === 'undefined') { | ||
| throw new JOSENotSupported(`JWE "zip" (Compression Algorithm) Header Parameter requires the ${name} API.`); | ||
| } | ||
| } | ||
| export async function compress(input) { | ||
| supported('CompressionStream'); | ||
| const cs = new CompressionStream('deflate-raw'); | ||
| const writer = cs.writable.getWriter(); | ||
| writer.write(input); | ||
| writer.close(); | ||
| const chunks = []; | ||
| const reader = cs.readable.getReader(); | ||
| for (;;) { | ||
| const { value, done } = await reader.read(); | ||
| if (done) | ||
| break; | ||
| chunks.push(value); | ||
| } | ||
| return concat(...chunks); | ||
| } | ||
| export async function decompress(input, maxLength) { | ||
| supported('DecompressionStream'); | ||
| const ds = new DecompressionStream('deflate-raw'); | ||
| const writer = ds.writable.getWriter(); | ||
| writer.write(input); | ||
| writer.close(); | ||
| const chunks = []; | ||
| let length = 0; | ||
| const reader = ds.readable.getReader(); | ||
| for (;;) { | ||
| const { value, done } = await reader.read(); | ||
| if (done) | ||
| break; | ||
| chunks.push(value); | ||
| length += value.byteLength; | ||
| if (maxLength !== Infinity && length > maxLength) { | ||
| throw new JWEInvalid('Decompressed plaintext exceeded the configured limit'); | ||
| } | ||
| } | ||
| return concat(...chunks); | ||
| } |
@@ -19,2 +19,9 @@ /** | ||
| * | ||
| * > [!NOTE]\ | ||
| * > The function iterates over the `recipients` array in the General JWE and returns the decryption | ||
| * > result of the first recipient entry that can be successfully decrypted. The result only contains | ||
| * > the plaintext and headers of that successfully decrypted recipient entry. Other recipient entries | ||
| * > in the General JWE are not validated, and their headers are not included in the returned result. | ||
| * > Recipients of a General JWE should only rely on the returned (decrypted) data. | ||
| * | ||
| * @param jwe General JWE. | ||
@@ -21,0 +28,0 @@ * @param key Private Key or Secret to decrypt the JWE with. See |
@@ -21,2 +21,10 @@ /** | ||
| * | ||
| * > [!NOTE]\ | ||
| * > The function iterates over the `signatures` array in the General JWS and returns the verification | ||
| * > result of the first signature entry that can be successfully verified. The result only contains | ||
| * > the payload, protected header, and unprotected header of that successfully verified signature | ||
| * > entry. Other signature entries in the General JWS are not validated, and their headers are not | ||
| * > included in the returned result. Recipients of a General JWS should only rely on the returned | ||
| * > (verified) data. | ||
| * | ||
| * @param jws General JWS. | ||
@@ -23,0 +31,0 @@ * @param key Key to verify the JWS with. See |
@@ -418,8 +418,8 @@ /** Generic JSON Web Key Parameters. */ | ||
| /** | ||
| * JWE "zip" (Compression Algorithm) Header Parameter. This parameter is not supported anymore. | ||
| * JWE "zip" (Compression Algorithm) Header Parameter. | ||
| * | ||
| * @deprecated Compression of data SHOULD NOT be done before encryption, because such compressed | ||
| * data often reveals information about the plaintext. | ||
| * The only supported value is `"DEF"` (DEFLATE). Requires the `CompressionStream` / | ||
| * `DecompressionStream` APIs to be available in the runtime. | ||
| * | ||
| * @see {@link https://www.rfc-editor.org/rfc/rfc8725#name-avoid-compression-of-encryp Avoid Compression of Encryption Inputs} | ||
| * @see {@link https://www.rfc-editor.org/rfc/rfc7516#section-4.1.3 JWE "zip" Header Parameter} | ||
| */ | ||
@@ -478,2 +478,13 @@ zip?: string | ||
| maxPBES2Count?: number | ||
| /** | ||
| * Maximum allowed size (in bytes) of the decompressed plaintext when the JWE `"zip"` (Compression | ||
| * Algorithm) Header Parameter is present. By default this value is set to 250000 (250 KB). The | ||
| * value must be `0`, a positive safe integer, or `Infinity`. | ||
| * | ||
| * Set to `0` to reject all compressed JWEs during decryption. | ||
| * | ||
| * Set to `Infinity` to disable the decompressed size limit. | ||
| */ | ||
| maxDecompressedLength?: number | ||
| } | ||
@@ -480,0 +491,0 @@ |
@@ -13,2 +13,3 @@ import { decode as b64u } from '../../util/base64url.js'; | ||
| import { checkKeyType } from '../../lib/check_key_type.js'; | ||
| import { decompress } from '../../lib/deflate.js'; | ||
| export async function flattenedDecrypt(jwe, key, options) { | ||
@@ -64,5 +65,8 @@ if (!isObject(jwe)) { | ||
| validateCrit(JWEInvalid, new Map(), options?.crit, parsedProt, joseHeader); | ||
| if (joseHeader.zip !== undefined) { | ||
| throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported.'); | ||
| if (joseHeader.zip !== undefined && joseHeader.zip !== 'DEF') { | ||
| throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value.'); | ||
| } | ||
| if (joseHeader.zip !== undefined && !parsedProt?.zip) { | ||
| throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header Parameter MUST be in a protected header.'); | ||
| } | ||
| const { alg, enc } = joseHeader; | ||
@@ -146,2 +150,13 @@ if (typeof alg !== 'string' || !alg) { | ||
| const result = { plaintext }; | ||
| if (joseHeader.zip === 'DEF') { | ||
| const maxDecompressedLength = options?.maxDecompressedLength ?? 250_000; | ||
| if (maxDecompressedLength === 0) { | ||
| throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported.'); | ||
| } | ||
| if (maxDecompressedLength !== Infinity && | ||
| (!Number.isSafeInteger(maxDecompressedLength) || maxDecompressedLength < 1)) { | ||
| throw new TypeError('maxDecompressedLength must be 0, a positive safe integer, or Infinity'); | ||
| } | ||
| result.plaintext = await decompress(plaintext, maxDecompressedLength); | ||
| } | ||
| if (jwe.protected !== undefined) { | ||
@@ -148,0 +163,0 @@ result.protectedHeader = parsedProt; |
@@ -11,2 +11,3 @@ import { encode as b64u } from '../../util/base64url.js'; | ||
| import { checkKeyType } from '../../lib/check_key_type.js'; | ||
| import { compress } from '../../lib/deflate.js'; | ||
| export class FlattenedEncrypt { | ||
@@ -86,5 +87,8 @@ #plaintext; | ||
| validateCrit(JWEInvalid, new Map(), options?.crit, this.#protectedHeader, joseHeader); | ||
| if (joseHeader.zip !== undefined) { | ||
| throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported.'); | ||
| if (joseHeader.zip !== undefined && joseHeader.zip !== 'DEF') { | ||
| throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value.'); | ||
| } | ||
| if (joseHeader.zip !== undefined && !this.#protectedHeader?.zip) { | ||
| throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header Parameter MUST be in a protected header.'); | ||
| } | ||
| const { alg, enc } = joseHeader; | ||
@@ -144,3 +148,7 @@ if (typeof alg !== 'string' || !alg) { | ||
| } | ||
| const { ciphertext, tag, iv } = await encrypt(enc, this.#plaintext, cek, this.#iv, additionalData); | ||
| let plaintext = this.#plaintext; | ||
| if (joseHeader.zip === 'DEF') { | ||
| plaintext = await compress(plaintext); | ||
| } | ||
| const { ciphertext, tag, iv } = await encrypt(enc, plaintext, cek, this.#iv, additionalData); | ||
| const jwe = { | ||
@@ -147,0 +155,0 @@ ciphertext: b64u(ciphertext), |
@@ -136,5 +136,8 @@ import { FlattenedEncrypt } from '../flattened/encrypt.js'; | ||
| validateCrit(JWEInvalid, new Map(), recipient.options.crit, this.#protectedHeader, joseHeader); | ||
| if (joseHeader.zip !== undefined) { | ||
| throw new JOSENotSupported('JWE "zip" (Compression Algorithm) Header Parameter is not supported.'); | ||
| if (joseHeader.zip !== undefined && joseHeader.zip !== 'DEF') { | ||
| throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value.'); | ||
| } | ||
| if (joseHeader.zip !== undefined && !this.#protectedHeader?.zip) { | ||
| throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header Parameter MUST be in a protected header.'); | ||
| } | ||
| } | ||
@@ -141,0 +144,0 @@ const cek = generateCek(enc); |
@@ -12,3 +12,3 @@ import { JOSEError, JWKSNoMatchingKey, JWKSTimeout } from '../util/errors.js'; | ||
| const NAME = 'jose'; | ||
| const VERSION = 'v6.1.3'; | ||
| const VERSION = 'v6.2.0'; | ||
| USER_AGENT = `${NAME}/${VERSION}`; | ||
@@ -15,0 +15,0 @@ } |
+1
-1
| { | ||
| "name": "jose", | ||
| "version": "6.1.3", | ||
| "version": "6.2.0", | ||
| "description": "JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
261931
1.72%101
1%6425
1.5%