1 | const isDisjoint = require('../help/is_disjoint')
|
2 | const base64url = require('../help/base64url')
|
3 | let validateCrit = require('../help/validate_crit')
|
4 | const { JWEInvalid, JOSENotSupported } = require('../errors')
|
5 |
|
6 | validateCrit = validateCrit.bind(undefined, JWEInvalid)
|
7 |
|
8 | module.exports = (prot, unprotected, recipients, checkAlgorithms, crit) => {
|
9 | if (typeof prot === 'string') {
|
10 | try {
|
11 | prot = base64url.JSON.decode(prot)
|
12 | } catch (err) {
|
13 | throw new JWEInvalid('could not parse JWE protected header')
|
14 | }
|
15 | }
|
16 |
|
17 | let alg = []
|
18 | const enc = new Set()
|
19 | if (!isDisjoint(prot, unprotected) || !recipients.every(({ header }) => {
|
20 | if (typeof header === 'object') {
|
21 | alg.push(header.alg)
|
22 | enc.add(header.enc)
|
23 | }
|
24 | const combined = { ...unprotected, ...header }
|
25 | validateCrit(prot, combined, crit)
|
26 | if ('zip' in combined) {
|
27 | throw new JWEInvalid('"zip" Header Parameter MUST be integrity protected')
|
28 | } else if (prot && 'zip' in prot && prot.zip !== 'DEF') {
|
29 | throw new JOSENotSupported('only "DEF" compression algorithm is supported')
|
30 | }
|
31 | return isDisjoint(header, prot) && isDisjoint(header, unprotected)
|
32 | })) {
|
33 | throw new JWEInvalid('JWE Shared Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint')
|
34 | }
|
35 |
|
36 | if (typeof prot === 'object') {
|
37 | alg.push(prot.alg)
|
38 | enc.add(prot.enc)
|
39 | }
|
40 | if (typeof unprotected === 'object') {
|
41 | alg.push(unprotected.alg)
|
42 | enc.add(unprotected.enc)
|
43 | }
|
44 |
|
45 | alg = alg.filter(Boolean)
|
46 | enc.delete(undefined)
|
47 |
|
48 | if (recipients.length !== 1) {
|
49 | if (alg.includes('dir') || alg.includes('ECDH-ES')) {
|
50 | throw new JWEInvalid('dir and ECDH-ES alg may only be used with a single recipient')
|
51 | }
|
52 | }
|
53 |
|
54 | if (checkAlgorithms) {
|
55 | if (alg.length !== recipients.length) {
|
56 | throw new JWEInvalid('missing Key Management algorithm')
|
57 | }
|
58 | if (enc.size === 0) {
|
59 | throw new JWEInvalid('missing Content Encryption algorithm')
|
60 | } else if (enc.size !== 1) {
|
61 | throw new JWEInvalid('there must only be one Content Encryption algorithm')
|
62 | }
|
63 | } else {
|
64 | if (enc.size > 1) {
|
65 | throw new JWEInvalid('there must only be one Content Encryption algorithm')
|
66 | }
|
67 | }
|
68 |
|
69 | return [...enc][0]
|
70 | }
|