jose/test/jwe/sanity.test.js
2019-07-27 21:19:14 +02:00

586 lines
22 KiB
JavaScript

const test = require('ava')
const base64url = require('../../lib/help/base64url')
const { JWKS, JWK: { generateSync }, JWE, errors } = require('../..')
test('algorithms option be an array of strings', t => {
;[{}, new Object(), false, null, Infinity, 0, '', Buffer.from('foo')].forEach((val) => { // eslint-disable-line no-new-object
t.throws(() => {
JWE.decrypt({
header: { alg: 'HS256' },
payload: 'foo',
ciphertext: 'bar'
}, generateSync('oct'), { algorithms: val })
}, { instanceOf: TypeError, message: '"algorithms" option must be an array of non-empty strings' })
t.throws(() => {
JWE.decrypt({
header: { alg: 'HS256' },
payload: 'foo',
ciphertext: 'bar'
}, generateSync('oct'), { algorithms: [val] })
}, { instanceOf: TypeError, message: '"algorithms" option must be an array of non-empty strings' })
})
})
test('compact parts length check', t => {
t.throws(() => {
JWE.decrypt('', generateSync('oct'))
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'JWE malformed or invalid serialization' })
t.throws(() => {
JWE.decrypt('...', generateSync('oct'))
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'JWE malformed or invalid serialization' })
t.throws(() => {
JWE.decrypt('.....', generateSync('oct'))
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'JWE malformed or invalid serialization' })
})
test('verify key or store argument', t => {
;[{}, new Object(), false, null, Infinity, 0, Buffer.from('foo')].forEach((val) => { // eslint-disable-line no-new-object
t.throws(() => {
JWE.decrypt('....', val)
}, { instanceOf: TypeError, message: 'key must be an instance of a key instantiated by JWK.asKey or a JWKS.KeyStore' })
})
})
test('JWE no alg specified but cannot resolve', t => {
const k1 = generateSync('RSA', undefined, { alg: 'foo' })
t.throws(() => {
JWE.encrypt('foo', k1)
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'could not resolve a usable "alg" for a recipient' })
})
test('JWE no alg/enc specified (multi recipient)', t => {
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(generateSync('RSA'))
encrypt.recipient(generateSync('oct', 256))
if (!('electron' in process.versions)) {
encrypt.recipient(generateSync('EC'))
}
const jwe = encrypt.encrypt('general')
t.is(jwe.unprotected, undefined)
t.deepEqual(base64url.JSON.decode(jwe.protected), { enc: 'A128CBC-HS256' })
t.deepEqual(jwe.recipients[0].header, { alg: 'RSA-OAEP' })
if (!('electron' in process.versions)) {
t.deepEqual(jwe.recipients[1].header, { alg: 'A256KW' })
const { epk, ...rest } = jwe.recipients[2].header
t.deepEqual(rest, { alg: 'ECDH-ES+A128KW' })
} else {
const { alg, ...rest } = jwe.recipients[1].header
t.is(alg, 'A256GCMKW')
t.true('iv' in rest)
t.true('tag' in rest)
}
})
test('JWE no alg/enc specified (multi recipient) with per-recipient headers', t => {
const encrypt = new JWE.Encrypt('foo')
const k1 = generateSync('RSA', undefined, { kid: 'kid_1' })
encrypt.recipient(k1, { kid: k1.kid })
const k2 = generateSync('oct', 256, { kid: 'kid_3' })
encrypt.recipient(k2, { kid: k2.kid })
if (!('electron' in process.versions)) {
const k3 = generateSync('EC', undefined, { kid: 'kid_2' })
encrypt.recipient(k3, { kid: k3.kid })
}
const jwe = encrypt.encrypt('general')
t.is(jwe.unprotected, undefined)
t.deepEqual(base64url.JSON.decode(jwe.protected), { enc: 'A128CBC-HS256' })
t.deepEqual(jwe.recipients[0].header, { alg: 'RSA-OAEP', kid: 'kid_1' })
if (!('electron' in process.versions)) {
t.deepEqual(jwe.recipients[1].header, { alg: 'A256KW', kid: 'kid_3' })
const { epk, ...rest } = jwe.recipients[2].header
t.deepEqual(rest, { alg: 'ECDH-ES+A128KW', kid: 'kid_2' })
} else {
const { alg, kid, ...rest } = jwe.recipients[1].header
t.is(alg, 'A256GCMKW')
t.is(kid, 'kid_3')
t.true('iv' in rest)
t.true('tag' in rest)
}
})
test('JWE no alg/enc specified (single rsa), no protected header', t => {
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(generateSync('RSA'))
const jwe = encrypt.encrypt('flattened')
t.is(jwe.unprotected, undefined)
t.is(jwe.header, undefined)
t.deepEqual(base64url.JSON.decode(jwe.protected), { alg: 'RSA-OAEP', enc: 'A128CBC-HS256' })
})
test('JWE no alg/enc specified (single rsa), with protected header', t => {
const k = generateSync('RSA', undefined, { kid: 'jwk key id' })
const encrypt = new JWE.Encrypt('foo', { kid: k.kid })
encrypt.recipient(k)
const jwe = encrypt.encrypt('flattened')
t.is(jwe.unprotected, undefined)
t.is(jwe.header, undefined)
t.deepEqual(base64url.JSON.decode(jwe.protected), { alg: 'RSA-OAEP', enc: 'A128CBC-HS256', kid: 'jwk key id' })
})
test('JWE no alg specified (single rsa), with protected header', t => {
const k = generateSync('RSA')
const encrypt = new JWE.Encrypt('foo', { enc: 'A256CBC-HS512' })
encrypt.recipient(k)
const jwe = encrypt.encrypt('flattened')
t.is(jwe.unprotected, undefined)
t.is(jwe.header, undefined)
t.deepEqual(base64url.JSON.decode(jwe.protected), { alg: 'RSA-OAEP', enc: 'A256CBC-HS512' })
})
test('JWE no alg specified (single rsa), with unprotected header', t => {
const k = generateSync('RSA')
const encrypt = new JWE.Encrypt('foo', undefined, { enc: 'A256CBC-HS512' })
encrypt.recipient(k)
const jwe = encrypt.encrypt('flattened')
t.deepEqual(jwe.unprotected, { enc: 'A256CBC-HS512' })
t.is(jwe.header, undefined)
t.deepEqual(base64url.JSON.decode(jwe.protected), { alg: 'RSA-OAEP' })
})
test('JWE no alg/enc specified (single oct)', t => {
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(generateSync('oct', 128))
const jwe = encrypt.encrypt('flattened')
t.is(jwe.unprotected, undefined)
t.is(jwe.header, undefined)
if (!('electron' in process.versions)) {
t.deepEqual(base64url.JSON.decode(jwe.protected), { alg: 'A128KW', enc: 'A128CBC-HS256' })
} else {
const { iv, tag, ...rest } = base64url.JSON.decode(jwe.protected)
t.deepEqual(rest, { alg: 'A128GCMKW', enc: 'A128CBC-HS256' })
t.truthy(iv)
t.truthy(tag)
}
})
test('JWE no alg/enc specified (single ec)', t => {
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(generateSync('EC'))
const jwe = encrypt.encrypt('flattened')
t.is(jwe.unprotected, undefined)
t.is(jwe.header, undefined)
const { epk, ...rest } = base64url.JSON.decode(jwe.protected)
t.deepEqual(rest, { alg: 'ECDH-ES', enc: 'A128CBC-HS256' })
})
test('JWE no alg/enc specified (only on a key)', t => {
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(generateSync('RSA', undefined, { alg: 'RSA1_5', use: 'enc' }))
const jwe = encrypt.encrypt('flattened')
t.is(jwe.unprotected, undefined)
t.is(jwe.header, undefined)
t.deepEqual(base64url.JSON.decode(jwe.protected), { alg: 'RSA1_5', enc: 'A128CBC-HS256' })
})
test('aes_cbc_hmac_sha2 decrypt iv check (missing)', t => {
const k = generateSync('oct', undefined, { alg: 'A128CBC-HS256' })
const encrypted = JWE.encrypt.flattened('foo', k, { alg: 'dir', enc: k.alg })
delete encrypted.iv
t.throws(() => {
JWE.decrypt(encrypted, k)
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'JWE malformed or invalid serialization' })
})
test('aes_cbc_hmac_sha2 decrypt iv check (invalid length)', t => {
const k = generateSync('oct', undefined, { alg: 'A128CBC-HS256' })
const encrypted = JWE.encrypt.flattened('foo', k, { alg: 'dir', enc: k.alg })
encrypted.iv = encrypted.iv.substr(0, 15)
t.throws(() => {
JWE.decrypt(encrypted, k)
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'invalid iv' })
})
test('aes_cbc_hmac_sha2 decrypt tag check (missing)', t => {
const k = generateSync('oct', undefined, { alg: 'A128CBC-HS256' })
const encrypted = JWE.encrypt.flattened('foo', k, { alg: 'dir', enc: k.alg })
delete encrypted.tag
t.throws(() => {
JWE.decrypt(encrypted, k)
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'JWE malformed or invalid serialization' })
})
test('aes_cbc_hmac_sha2 decrypt tag check (invalid length)', t => {
const k = generateSync('oct', undefined, { alg: 'A128CBC-HS256' })
const encrypted = JWE.encrypt.flattened('foo', k, { alg: 'dir', enc: k.alg })
encrypted.tag = encrypted.tag.substr(0, 15)
t.throws(() => {
JWE.decrypt(encrypted, k)
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'invalid tag' })
})
test('aes_gcm decrypt iv check (missing)', t => {
const k = generateSync('oct', 128, { alg: 'A128GCM' })
const encrypted = JWE.encrypt.flattened('foo', k, { alg: 'dir', enc: k.alg })
delete encrypted.iv
t.throws(() => {
JWE.decrypt(encrypted, k)
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'JWE malformed or invalid serialization' })
})
test('aes_gcm decrypt iv check (invalid length)', t => {
const k = generateSync('oct', 128, { alg: 'A128GCM' })
const encrypted = JWE.encrypt.flattened('foo', k, { alg: 'dir', enc: k.alg })
encrypted.iv = encrypted.iv.substr(0, 15)
t.throws(() => {
JWE.decrypt(encrypted, k)
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'invalid iv' })
})
test('aes_gcm decrypt tag check (missing)', t => {
const k = generateSync('oct', 128, { alg: 'A128GCM' })
const encrypted = JWE.encrypt.flattened('foo', k, { alg: 'dir', enc: k.alg })
delete encrypted.tag
t.throws(() => {
JWE.decrypt(encrypted, k)
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'JWE malformed or invalid serialization' })
})
test('aes_gcm decrypt tag check (invalid length)', t => {
const k = generateSync('oct', 128, { alg: 'A128GCM' })
const encrypted = JWE.encrypt.flattened('foo', k, { alg: 'dir', enc: k.alg })
encrypted.tag = encrypted.tag.substr(0, 15)
t.throws(() => {
JWE.decrypt(encrypted, k)
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'invalid tag' })
})
test('JWE encrypt accepts buffer', t => {
const k = generateSync('oct')
JWE.encrypt(Buffer.from('foo'), k)
t.pass()
})
test('JWE encrypt accepts string', t => {
const k = generateSync('oct')
JWE.encrypt('foo', k)
t.pass()
})
test('JWE encrypt rejects other', t => {
const k = generateSync('oct')
;[[], {}, false, true, undefined, null, Infinity, 0].forEach((val) => {
t.throws(() => {
JWE.encrypt(val, k)
}, { instanceOf: TypeError, message: 'cleartext argument must be a Buffer or a string' })
})
})
test('JWE encrypt protectedHeader rejects non objects if provided', t => {
const k = generateSync('oct')
;[[], false, true, null, Infinity, 0, Buffer.from('foo')].forEach((val) => {
t.throws(() => {
JWE.encrypt('foo', k, val)
}, { instanceOf: TypeError, message: 'protectedHeader argument must be a plain object when provided' })
})
})
test('JWE encrypt unprotectedHeader rejects non objects if provided', t => {
;[[], false, true, null, Infinity, 0, Buffer.from('foo')].forEach((val) => {
t.throws(() => {
new JWE.Encrypt('foo', undefined, val) // eslint-disable-line no-new
}, { instanceOf: TypeError, message: 'unprotectedHeader argument must be a plain object when provided' })
})
})
test('JWE encrypt per-recipient header rejects non objects if provided', t => {
const k = generateSync('oct')
const enc = new JWE.Encrypt('foo')
;[[], false, true, null, Infinity, 0, Buffer.from('foo')].forEach((val) => {
t.throws(() => {
enc.recipient(k, val)
}, { instanceOf: TypeError, message: 'header argument must be a plain object when provided' })
})
})
test('JWE encrypt aad rejects non buffers and non strings', t => {
;[[], false, true, null, Infinity, 0].forEach((val) => {
t.throws(() => {
new JWE.Encrypt('foo', undefined, undefined, val) // eslint-disable-line no-new
}, { instanceOf: TypeError, message: 'aad argument must be a Buffer or a string when provided' })
})
})
test('JWE encrypt rejects non keys', t => {
;[[], false, true, undefined, null, Infinity, 0].forEach((val) => {
t.throws(() => {
JWE.encrypt('foo', val)
}, { instanceOf: TypeError, message: 'key must be an instance of a key instantiated by JWK.asKey' })
})
})
test('JWE must have recipients', t => {
const encrypt = new JWE.Encrypt('foo')
t.throws(() => {
encrypt.encrypt('compact')
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'missing recipients' })
})
test('JWE valid serialization must be provided', t => {
;[[], false, true, null, Infinity, 0, 'foo', ''].forEach((val) => {
const encrypt = new JWE.Encrypt('foo')
t.throws(() => {
encrypt.encrypt(val)
}, { instanceOf: TypeError, message: 'serialization must be one of "compact", "flattened", "general"' })
})
})
test('JWE compact does not support multiple recipients', t => {
const k = generateSync('oct')
const k2 = generateSync('EC')
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(k)
encrypt.recipient(k2)
t.throws(() => {
encrypt.encrypt('compact')
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'JWE Compact Serialization doesn\'t support multiple recipients, JWE unprotected headers or AAD' })
})
test('JWE compact does not support unprotected header', t => {
const k = generateSync('oct')
t.throws(() => {
JWE.encrypt('foo', k, undefined, { foo: 1 })
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'JWE Compact Serialization doesn\'t support multiple recipients, JWE unprotected headers or AAD' })
})
test('JWE compact does not support aad', t => {
const k = generateSync('oct')
t.throws(() => {
JWE.encrypt('foo', k, undefined, undefined, 'aad')
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'JWE Compact Serialization doesn\'t support multiple recipients, JWE unprotected headers or AAD' })
})
test('JWE flattened does not support multiple recipients', t => {
const k = generateSync('oct')
const k2 = generateSync('EC')
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(k)
encrypt.recipient(k2)
t.throws(() => {
encrypt.encrypt('flattened')
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'Flattened JWE JSON Serialization doesn\'t support multiple recipients' })
})
test('JWE must only have one Content Encryption algorithm (encrypt)', t => {
const k = generateSync('oct')
const k2 = generateSync('RSA')
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(k, { enc: 'A128CBC-HS256' })
encrypt.recipient(k2, { enc: 'A128GCM' })
t.throws(() => {
encrypt.encrypt('general')
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'there must only be one Content Encryption algorithm' })
})
test('JWE must only have one Content Encryption algorithm (decrypt)', t => {
const k = generateSync('oct')
const k2 = generateSync('RSA')
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(k, { enc: 'A128GCM' })
encrypt.recipient(k2, { enc: 'A128GCM' })
const jwe = encrypt.encrypt('general')
t.throws(() => {
jwe.recipients[0].header.enc = 'A128CBC-HS256'
JWE.decrypt(jwe, k)
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'there must only be one Content Encryption algorithm' })
})
test('JWE must have a Content Encryption algorithm (decrypt)', t => {
const k = generateSync('oct')
const k2 = generateSync('RSA')
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(k, { enc: 'A128GCM' })
encrypt.recipient(k2, { enc: 'A128GCM' })
const jwe = encrypt.encrypt('general')
t.throws(() => {
delete jwe.recipients[0].header.enc
delete jwe.recipients[1].header.enc
JWE.decrypt(jwe, k)
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'missing Content Encryption algorithm' })
})
test('JWE oct dir is only usable with a single recipient', t => {
const k = generateSync('oct', undefined, { alg: 'A128CBC-HS256', use: 'enc' })
const k2 = generateSync('RSA')
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(k, { alg: 'dir' })
encrypt.recipient(k2)
t.throws(() => {
encrypt.encrypt('general')
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'dir and ECDH-ES alg may only be used with a single recipient' })
})
test('JWE EC ECDH-ES is only usable with a single recipient', t => {
const k = generateSync('EC', undefined, { alg: 'ECDH-ES', use: 'enc' })
const k2 = generateSync('RSA')
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(k, { alg: 'ECDH-ES' })
encrypt.recipient(k2)
t.throws(() => {
encrypt.encrypt('general')
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'dir and ECDH-ES alg may only be used with a single recipient' })
})
test('JWE prot, unprot and per-recipient headers must be disjoint', t => {
const k = generateSync('oct')
t.throws(() => {
const encrypt = new JWE.Encrypt('foo', { foo: 1 }, { foo: 2 })
encrypt.recipient(k)
encrypt.encrypt('flattened')
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'JWE Shared Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint' })
t.throws(() => {
const encrypt = new JWE.Encrypt('foo', { foo: 1 })
encrypt.recipient(k, { foo: 2 })
encrypt.encrypt('flattened')
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'JWE Shared Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint' })
t.throws(() => {
const encrypt = new JWE.Encrypt('foo', undefined, { foo: 1 })
encrypt.recipient(k, { foo: 2 })
encrypt.encrypt('flattened')
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: 'JWE Shared Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint' })
})
if (!('electron' in process.versions)) {
test('JWE decrypt algorithms whitelist', t => {
const k = generateSync('oct')
const jwe = JWE.encrypt('foo', k, { alg: 'PBES2-HS256+A128KW' })
JWE.decrypt(jwe, k, { algorithms: ['PBES2-HS256+A128KW', 'PBES2-HS384+A192KW'] })
t.throws(() => {
JWE.decrypt(jwe, k, { algorithms: ['PBES2-HS384+A192KW'] })
}, { instanceOf: errors.JOSEAlgNotWhitelisted, code: 'ERR_JOSE_ALG_NOT_WHITELISTED', message: 'alg not whitelisted' })
})
test('JWE decrypt algorithms whitelist with a keystore', t => {
const k = generateSync('oct')
const k2 = generateSync('oct')
const ks = new JWKS.KeyStore(k, k2)
const jwe = JWE.encrypt('foo', k2, { alg: 'PBES2-HS256+A128KW' })
JWE.decrypt(jwe, ks, { algorithms: ['PBES2-HS256+A128KW', 'PBES2-HS384+A192KW'] })
t.throws(() => {
JWE.decrypt(jwe, ks, { algorithms: ['PBES2-HS384+A192KW'] })
}, { instanceOf: errors.JOSEAlgNotWhitelisted, code: 'ERR_JOSE_ALG_NOT_WHITELISTED' })
})
}
test('JWE decrypt algorithms whitelist with direct encryption', t => {
const k = generateSync('oct')
const jwe = JWE.encrypt('foo', k, { alg: 'dir' })
JWE.decrypt(jwe, k, { algorithms: ['A128CBC-HS256'] })
t.throws(() => {
JWE.decrypt(jwe, k, { algorithms: ['PBES2-HS384+A192KW'] })
}, { instanceOf: errors.JOSEAlgNotWhitelisted, code: 'ERR_JOSE_ALG_NOT_WHITELISTED' })
})
test('JWE decrypt algorithms whitelist (multi-recipient)', t => {
const k = generateSync('oct')
const k2 = generateSync('RSA')
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(k)
encrypt.recipient(k2)
const jwe = encrypt.encrypt('general')
JWE.decrypt(jwe, k, { algorithms: ['electron' in process.versions ? 'A256GCMKW' : 'A256KW'] })
JWE.decrypt(jwe, k2, { algorithms: ['RSA-OAEP'] })
let err
err = t.throws(() => {
JWE.decrypt(jwe, k, { algorithms: ['RSA-OAEP'] })
}, { instanceOf: errors.JOSEMultiError, code: 'ERR_JOSE_MULTIPLE_ERRORS' })
;[...err].forEach((e, i) => {
if (i === 0) {
t.is(e.constructor, errors.JOSEAlgNotWhitelisted)
} else {
t.is(e.constructor, errors.JWKKeySupport)
}
})
err = t.throws(() => {
JWE.decrypt(jwe, k2, { algorithms: ['electron' in process.versions ? 'A256GCMKW' : 'A256KW'] })
}, { instanceOf: errors.JOSEMultiError, code: 'ERR_JOSE_MULTIPLE_ERRORS' })
;[...err].forEach((e, i) => {
if (i === 0) {
t.is(e.constructor, errors.JWKKeySupport)
} else {
t.is(e.constructor, errors.JOSEAlgNotWhitelisted)
}
})
})
test('JWE "zip" must be integrity protected', t => {
const k = generateSync('oct')
t.throws(() => {
JWE.encrypt.flattened('foo', k, undefined, { zip: 'DEF' })
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: '"zip" Header Parameter MUST be integrity protected' })
})
test('JWE "zip" only DEF is supported', t => {
const k = generateSync('oct')
t.throws(() => {
JWE.encrypt.flattened('foo', k, { zip: 'FOO' })
}, { instanceOf: errors.JOSENotSupported, code: 'ERR_JOSE_NOT_SUPPORTED', message: 'only "DEF" compression algorithm is supported' })
})
test('JWE "zip" must be integrity protected (decrypt)', t => {
const k = generateSync('oct')
const jwe = JWE.encrypt.flattened('foo', k, { zip: 'DEF' })
const prot = base64url.JSON.decode(jwe.protected)
delete prot.zip
jwe.protected = base64url.JSON.encode(prot)
jwe.unprotected = { zip: 'DEF' }
t.throws(() => {
JWE.decrypt(jwe, k)
}, { instanceOf: errors.JWEInvalid, code: 'ERR_JWE_INVALID', message: '"zip" Header Parameter MUST be integrity protected' })
})
test('JWE "zip" only DEF is supported (decrypt)', t => {
const k = generateSync('oct')
const jwe = JWE.encrypt.flattened('foo', k, { zip: 'DEF' })
const prot = base64url.JSON.decode(jwe.protected)
prot.zip = 'foo'
jwe.protected = base64url.JSON.encode(prot)
t.throws(() => {
JWE.decrypt(jwe, k)
}, { instanceOf: errors.JOSENotSupported, code: 'ERR_JOSE_NOT_SUPPORTED', message: 'only "DEF" compression algorithm is supported' })
})
test('JWE keystore match multi but fails with decryption error', t => {
const k = generateSync('oct')
const ks = new JWKS.KeyStore(generateSync('oct'), generateSync('oct'))
const jwe = JWE.encrypt('foo', k)
t.throws(() => {
JWE.decrypt(jwe, ks)
}, { instanceOf: errors.JWEDecryptionFailed, code: 'ERR_JWE_DECRYPTION_FAILED' })
})
test('JWE general fails with decryption error', t => {
const k = generateSync('oct')
const k2 = generateSync('oct')
const k3 = generateSync('oct')
const encrypt = new JWE.Encrypt('foo')
encrypt.recipient(k)
encrypt.recipient(k2)
const jwe = encrypt.encrypt('general')
t.throws(() => {
JWE.decrypt(jwe, k3)
}, { instanceOf: errors.JWEDecryptionFailed, code: 'ERR_JWE_DECRYPTION_FAILED' })
})