Skip to content

Commit

Permalink
fix: limit default PBES2 alg's computational expense
Browse files Browse the repository at this point in the history
Also adds an option to opt-in to higher computation expense.
  • Loading branch information
panva committed Sep 1, 2022
1 parent 2269f4b commit c1512be
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 1 deletion.
4 changes: 4 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`: `<boolean>` 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.
Expand Down
8 changes: 7 additions & 1 deletion lib/jwe/decrypt.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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' })
Expand Down
10 changes: 10 additions & 0 deletions test/jwe/sanity.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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' })
})
}
1 change: 1 addition & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ export namespace JWE {
crit?: string[];
contentEncryptionAlgorithms?: string[];
keyManagementAlgorithms?: string[];
maxPBES2Count?: number;
}

interface completeDecrypt {
Expand Down

0 comments on commit c1512be

Please sign in to comment.