diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d10488d28..50106b9d78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [2.0.6](https://github.com/panva/jose/compare/v2.0.5...v2.0.6) (2022-09-01) + + +### Bug Fixes + +* limit default PBES2 alg's computational expense ([c1512be](https://github.com/panva/jose/commit/c1512be6601a8b6e5a8193fbda9ecdf25349a1c2)) + ## [2.0.5](https://github.com/panva/jose/compare/v2.0.4...v2.0.5) (2021-04-09) diff --git a/docs/README.md b/docs/README.md index ed1a78c11c..f1d68a3cd1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1490,6 +1490,10 @@ operation. - `keyManagementAlgorithms`: `string[]` Array of algorithms to accept as the `alg` (key management), when the JWE does not use an Key Management algorithm from this list the decryption will fail. **Default:** 'undefined' - accepts all algorithms available on the key or key store. + - `maxPBES2Count`: `number` (PBES2 Key Management Algorithms only) Maximum allowed "p2c" (PBES2 + Count) Header Parameter value. The PBKDF2 iteration count defines the algorithm's computational + expense. + **Default:** '10000' - `complete`: `` When true returns an object with the parsed headers, verified AAD, the content encryption key, the key that was used to unwrap or derive the content encryption key, and cleartext instead of only the cleartext. diff --git a/lib/jwe/decrypt.js b/lib/jwe/decrypt.js index fb5da68aaa..9da8aead45 100644 --- a/lib/jwe/decrypt.js +++ b/lib/jwe/decrypt.js @@ -52,7 +52,7 @@ const validateAlgorithms = (algorithms, option) => { /* * @public */ -const jweDecrypt = (skipValidateHeaders, serialization, jwe, key, { crit = [], complete = false, keyManagementAlgorithms, contentEncryptionAlgorithms } = {}) => { +const jweDecrypt = (skipValidateHeaders, serialization, jwe, key, { crit = [], complete = false, keyManagementAlgorithms, contentEncryptionAlgorithms, maxPBES2Count = 10000 } = {}) => { key = getKey(key, true) keyManagementAlgorithms = validateAlgorithms(keyManagementAlgorithms, 'keyManagementAlgorithms') @@ -142,6 +142,12 @@ const jweDecrypt = (skipValidateHeaders, serialization, jwe, key, { crit = [], c check(key, ...(alg === 'dir' ? ['decrypt', enc] : ['keyManagementDecrypt', alg])) + if (alg.startsWith('PBES2')) { + if (opts && opts.p2c > maxPBES2Count) { + throw new errors.JWEInvalid('JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds') + } + } + try { if (alg === 'dir') { cek = JWK.asKey(key, { alg: enc, use: 'enc' }) diff --git a/package.json b/package.json index 8f7dfa9f58..fbcda65c7f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jose", - "version": "2.0.5", + "version": "2.0.6", "description": "JSON Web Almost Everything - JWA, JWS, JWE, JWK, JWT, JWKS for Node.js with minimal dependencies", "keywords": [ "access token", diff --git a/test/jwe/sanity.test.js b/test/jwe/sanity.test.js index edfa4bb945..fd8a083742 100644 --- a/test/jwe/sanity.test.js +++ b/test/jwe/sanity.test.js @@ -606,3 +606,13 @@ test('"enc" value must be supported error (when no alg was specified)', t => { JWE.encrypt('foo', k, { enc: 'foo' }) }, { instanceOf: errors.JOSENotSupported, message: 'unsupported encrypt alg: foo' }) }) + +if (!('electron' in process.versions)) { + test('decrypt PBES2 p2c limit', t => { + const k = generateSync('oct', 256) + const jwe = JWE.encrypt('foo', k, { alg: 'PBES2-HS256+A128KW' }) + t.throws(() => { + JWE.decrypt(jwe, k, { maxPBES2Count: 1000 }) + }, { instanceOf: errors.JWEInvalid, message: 'JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds' }) + }) +} diff --git a/types/index.d.ts b/types/index.d.ts index 9c4ff9af4d..30e146a019 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -401,6 +401,7 @@ export namespace JWE { crit?: string[]; contentEncryptionAlgorithms?: string[]; keyManagementAlgorithms?: string[]; + maxPBES2Count?: number; } interface completeDecrypt {