Skip to content

Commit

Permalink
refactor: remove support for JWE "zip" (Compression Algorithm) Header…
Browse files Browse the repository at this point in the history
… Parameter

BREAKING CHANGE: The JWE "zip" (Compression Algorithm) Header Parameter
is no longer supported by this JOSE implementation.
  • Loading branch information
panva committed Oct 25, 2023
1 parent 28c4f8c commit 16998b1
Show file tree
Hide file tree
Showing 9 changed files with 17 additions and 123 deletions.
3 changes: 0 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,12 @@ export type {
GeneralJWE,
JWEHeaderParameters,
CritOption,
DeflateOption,
DecryptOptions,
EncryptOptions,
JWTClaimVerificationOptions,
VerifyOptions,
SignOptions,
JWTPayload,
DeflateFunction,
InflateFunction,
FlattenedDecryptResult,
GeneralDecryptResult,
CompactDecryptResult,
Expand Down
17 changes: 3 additions & 14 deletions src/jwe/flattened/decrypt.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { decode as base64url } from '../../runtime/base64url.js'
import decrypt from '../../runtime/decrypt.js'
import { inflate } from '../../runtime/zlib.js'

import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.js'
import isDisjoint from '../../lib/is_disjoint.js'
Expand Down Expand Up @@ -142,15 +141,9 @@ export async function flattenedDecrypt(
validateCrit(JWEInvalid, new Map(), options?.crit, parsedProt, joseHeader)

if (joseHeader.zip !== undefined) {
if (!parsedProt || !parsedProt.zip) {
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected')
}

if (joseHeader.zip !== 'DEF') {
throw new JOSENotSupported(
'Unsupported JWE "zip" (Compression Algorithm) Header Parameter value',
)
}
throw new JOSENotSupported(
'JWE "zip" (Compression Algorithm) Header Parameter is not supported.',
)
}

const { alg, enc } = joseHeader
Expand Down Expand Up @@ -239,10 +232,6 @@ export async function flattenedDecrypt(
}
let plaintext = await decrypt(enc, cek, ciphertext, iv, tag, additionalData)

if (joseHeader.zip === 'DEF') {
plaintext = await (options?.inflateRaw || inflate)(plaintext)
}

const result: FlattenedDecryptResult = { plaintext }

if (jwe.protected !== undefined) {
Expand Down
23 changes: 4 additions & 19 deletions src/jwe/flattened/encrypt.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { encode as base64url } from '../../runtime/base64url.js'
import encrypt from '../../runtime/encrypt.js'
import { deflate } from '../../runtime/zlib.js'

import type {
KeyLike,
Expand Down Expand Up @@ -190,15 +189,9 @@ export class FlattenedEncrypt {
validateCrit(JWEInvalid, new Map(), options?.crit, this._protectedHeader, joseHeader)

if (joseHeader.zip !== undefined) {
if (!this._protectedHeader || !this._protectedHeader.zip) {
throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected')
}

if (joseHeader.zip !== 'DEF') {
throw new JOSENotSupported(
'Unsupported JWE "zip" (Compression Algorithm) Header Parameter value',
)
}
throw new JOSENotSupported(
'JWE "zip" (Compression Algorithm) Header Parameter is not supported.',
)
}

const { alg, enc } = joseHeader
Expand Down Expand Up @@ -271,15 +264,7 @@ export class FlattenedEncrypt {
additionalData = protectedHeader
}

let ciphertext: Uint8Array
let tag: Uint8Array

if (joseHeader.zip === 'DEF') {
const deflated = await (options?.deflateRaw || deflate)(this._plaintext)
;({ ciphertext, tag } = await encrypt(enc, deflated, cek, this._iv, additionalData))
} else {
;({ ciphertext, tag } = await encrypt(enc, this._plaintext, cek, this._iv, additionalData))
}
const { ciphertext, tag } = await encrypt(enc, this._plaintext, cek, this._iv, additionalData)

const jwe: FlattenedJWE = {
ciphertext: base64url(ciphertext),
Expand Down
24 changes: 7 additions & 17 deletions src/jwe/general/encrypt.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FlattenedEncrypt, unprotected } from '../flattened/encrypt.js'
import { JWEInvalid } from '../../util/errors.js'
import { JOSENotSupported, JWEInvalid } from '../../util/errors.js'
import generateCek from '../../lib/cek.js'
import isDisjoint from '../../lib/is_disjoint.js'
import encryptKeyManagement from '../../lib/encrypt_key_management.js'
Expand All @@ -11,7 +11,6 @@ import type {
GeneralJWE,
JWEHeaderParameters,
CritOption,
DeflateOption,
} from '../../types.d'

export interface Recipient {
Expand Down Expand Up @@ -149,18 +148,12 @@ export class GeneralEncrypt {
return this
}

/**
* Encrypts and resolves the value of the General JWE object.
*
* @param options JWE Encryption options.
*/
async encrypt(options?: DeflateOption): Promise<GeneralJWE> {
/** Encrypts and resolves the value of the General JWE object. */
async encrypt(): Promise<GeneralJWE> {
if (!this._recipients.length) {
throw new JWEInvalid('at least one recipient must be added')
}

options = { deflateRaw: options?.deflateRaw }

if (this._recipients.length === 1) {
const [recipient] = this._recipients

Expand All @@ -169,7 +162,7 @@ export class GeneralEncrypt {
.setProtectedHeader(this._protectedHeader)
.setSharedUnprotectedHeader(this._unprotectedHeader)
.setUnprotectedHeader(recipient.unprotectedHeader!)
.encrypt(recipient.key, { ...recipient.options, ...options })
.encrypt(recipient.key, { ...recipient.options })

let jwe: GeneralJWE = {
ciphertext: flattened.ciphertext,
Expand Down Expand Up @@ -229,11 +222,9 @@ export class GeneralEncrypt {
validateCrit(JWEInvalid, new Map(), recipient.options.crit, this._protectedHeader, joseHeader)

if (joseHeader.zip !== undefined) {
if (!this._protectedHeader || !this._protectedHeader.zip) {
throw new JWEInvalid(
'JWE "zip" (Compression Algorithm) Header MUST be integrity protected',
)
}
throw new JOSENotSupported(
'JWE "zip" (Compression Algorithm) Header Parameter is not supported.',
)
}
}

Expand Down Expand Up @@ -269,7 +260,6 @@ export class GeneralEncrypt {
.setKeyManagementParameters({ p2c })
.encrypt(recipient.key, {
...recipient.options,
...options,
// @ts-expect-error
[unprotected]: true,
})
Expand Down
13 changes: 0 additions & 13 deletions src/runtime/browser/zlib.ts

This file was deleted.

10 changes: 0 additions & 10 deletions src/runtime/node/zlib.ts

This file was deleted.

45 changes: 2 additions & 43 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ export interface JWEHeaderParameters extends JoseHeaderParameters {
crit?: string[]

/**
* JWE "zip" (Compression Algorithm) Header Parameter.
* JWE "zip" (Compression Algorithm) Header Parameter. This parameter is not supported anymore.
*
* @deprecated Compression of data SHOULD NOT be done before encryption, because such compressed
* data often reveals information about the plaintext.
Expand Down Expand Up @@ -415,12 +415,6 @@ export interface DecryptOptions extends CritOption {
*/
contentEncryptionAlgorithms?: string[]

/**
* In a browser runtime you have to provide an implementation for Inflate Raw when you expect JWEs
* with compressed plaintext.
*/
inflateRaw?: InflateFunction

/**
* (PBES2 Key Management Algorithms only) Maximum allowed "p2c" (PBES2 Count) Header Parameter
* value. The PBKDF2 iteration count defines the algorithm's computational expense. By default
Expand All @@ -429,17 +423,8 @@ export interface DecryptOptions extends CritOption {
maxPBES2Count?: number
}

/** JWE Deflate option. */
export interface DeflateOption {
/**
* In a browser runtime you have to provide an implementation for Deflate Raw when you will be
* producing JWEs with compressed plaintext.
*/
deflateRaw?: DeflateFunction
}

/** JWE Encryption options. */
export interface EncryptOptions extends CritOption, DeflateOption {}
export interface EncryptOptions extends CritOption {}

/** JWT Claims Set verification options. */
export interface JWTClaimVerificationOptions {
Expand Down Expand Up @@ -553,32 +538,6 @@ export interface JWTPayload {
[propName: string]: unknown
}

/**
* Deflate Raw implementation, e.g. promisified
* {@link https://nodejs.org/api/zlib.html#zlibdeflaterawbuffer-options-callback zlib.deflateRaw}.
*
* @deprecated Compression of data SHOULD NOT be done before encryption, because such compressed
* data often reveals information about the plaintext.
*
* @see {@link https://www.rfc-editor.org/rfc/rfc8725#name-avoid-compression-of-encryp Avoid Compression of Encryption Inputs}
*/
export interface DeflateFunction {
(input: Uint8Array): Promise<Uint8Array>
}

/**
* Inflate Raw implementation, e.g. promisified
* {@link https://nodejs.org/api/zlib.html#zlibinflaterawbuffer-options-callback zlib.inflateRaw}.
*
* @deprecated Compression of data SHOULD NOT be done before encryption, because such compressed
* data often reveals information about the plaintext.
*
* @see {@link https://www.rfc-editor.org/rfc/rfc8725#name-avoid-compression-of-encryp Avoid Compression of Encryption Inputs}
*/
export interface InflateFunction {
(input: Uint8Array): Promise<Uint8Array>
}

export interface FlattenedDecryptResult {
/** JWE AAD. */
additionalAuthenticatedData?: Uint8Array
Expand Down
2 changes: 1 addition & 1 deletion tap/cookbook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export default (QUnit: QUnit, lib: typeof jose) => {
if (env.isElectron && vector.electron === false) {
return false
}
if (vector.input.zip && !env.hasZlib) {
if (vector.input.zip) {
return false
}
return true
Expand Down
3 changes: 0 additions & 3 deletions tap/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,3 @@ export const isWebKit = isBrowser && (await isEngine('WebKit'))
export const isWebKitAbove17 = isBrowser && isWebKit && (await isVersionAtLeast(17))

export const isGecko = isBrowser && (await isEngine('Gecko'))

// @ts-ignore
export const hasZlib = isNode && [...process.argv].reverse()[0] !== '#dist/webapi'

0 comments on commit 16998b1

Please sign in to comment.