@sphereon/ssi-sdk-ext.jwt-service 0.26.1-feature.SPRIND.116.8 → 0.26.1-feature.SPRIND.124.esim.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,59 +1,60 @@
1
- import {defaultRandomSource, randomBytes, RandomSource} from '@stablelib/random'
2
- import {base64ToBytes, bytesToBase64url, decodeBase64url} from "@veramo/utils";
3
- import * as jose from "jose";
4
- import {JWEKeyManagementHeaderParameters, JWTDecryptOptions} from "jose";
5
- import type {KeyLike} from "jose/dist/types/types";
1
+ import { defaultRandomSource, randomBytes, RandomSource } from '@stablelib/random'
2
+ import { base64ToBytes, bytesToBase64url, decodeBase64url } from '@veramo/utils'
3
+ import * as jose from 'jose'
4
+ import { JWEKeyManagementHeaderParameters, JWTDecryptOptions } from 'jose'
5
+ import type { KeyLike } from 'jose/dist/types/types'
6
6
  import * as u8a from 'uint8arrays'
7
7
  import {
8
- JweAlg,
9
- JweAlgs,
10
- JweEnc,
11
- JweEncs,
12
- JweHeader,
13
- JweJsonGeneral,
14
- JweProtectedHeader,
15
- JweRecipient,
16
- JweRecipientUnprotectedHeader,
17
- JwsPayload
18
- } from "../types/IJwtService";
19
-
8
+ JweAlg,
9
+ JweAlgs,
10
+ JweEnc,
11
+ JweEncs,
12
+ JweHeader,
13
+ JweJsonGeneral,
14
+ JweProtectedHeader,
15
+ JweRecipient,
16
+ JweRecipientUnprotectedHeader,
17
+ JwsPayload,
18
+ } from '../types/IJwtService'
20
19
 
21
20
  export interface EncryptionResult {
22
- ciphertext: Uint8Array
23
- tag: Uint8Array
24
- iv: Uint8Array
25
- protectedHeader?: string
26
- recipients?: JweRecipient[]
27
- cek?: Uint8Array
21
+ ciphertext: Uint8Array
22
+ tag: Uint8Array
23
+ iv: Uint8Array
24
+ protectedHeader?: string
25
+ recipients?: JweRecipient[]
26
+ cek?: Uint8Array
28
27
  }
29
28
 
30
-
31
- export const generateContentEncryptionKey = async ({alg, randomSource = defaultRandomSource}: {
32
- alg: JweEnc,
33
- randomSource?: RandomSource
29
+ export const generateContentEncryptionKey = async ({
30
+ alg,
31
+ randomSource = defaultRandomSource,
32
+ }: {
33
+ alg: JweEnc
34
+ randomSource?: RandomSource
34
35
  }): Promise<Uint8Array> => {
35
- let length: number
36
- switch (alg) {
37
- case "A128GCM":
38
- length = 16
39
- break
40
- case "A192GCM":
41
- length = 24
42
- break
43
- case "A128CBC-HS256":
44
- case "A256GCM":
45
- length = 32
46
- break
47
- case "A192CBC-HS384":
48
- length = 48
49
- break
50
- case "A256CBC-HS512":
51
- length = 64
52
- break
53
- default:
54
- length = 32
55
- }
56
- return randomBytes(length, randomSource)
36
+ let length: number
37
+ switch (alg) {
38
+ case 'A128GCM':
39
+ length = 16
40
+ break
41
+ case 'A192GCM':
42
+ length = 24
43
+ break
44
+ case 'A128CBC-HS256':
45
+ case 'A256GCM':
46
+ length = 32
47
+ break
48
+ case 'A192CBC-HS384':
49
+ length = 48
50
+ break
51
+ case 'A256CBC-HS512':
52
+ length = 64
53
+ break
54
+ default:
55
+ length = 32
56
+ }
57
+ return randomBytes(length, randomSource)
57
58
  }
58
59
 
59
60
  /*
@@ -68,241 +69,236 @@ export const generateContentEncryptionKeyfdsdf = async ({type = 'Secp256r1', ...
68
69
  }
69
70
  */
70
71
  export interface JwtEncrypter {
71
- alg: string
72
- enc: string
73
- encrypt: (payload: JwsPayload, protectedHeader: JweProtectedHeader, aad?: Uint8Array) => Promise<EncryptionResult>
74
- encryptCek?: (cek: Uint8Array) => Promise<JweRecipient>
72
+ alg: string
73
+ enc: string
74
+ encrypt: (payload: JwsPayload, protectedHeader: JweProtectedHeader, aad?: Uint8Array) => Promise<EncryptionResult>
75
+ encryptCek?: (cek: Uint8Array) => Promise<JweRecipient>
75
76
  }
76
77
 
77
-
78
78
  export interface JweEncrypter {
79
- alg: string
80
- enc: string
81
- encrypt: (payload: Uint8Array, protectedHeader: JweProtectedHeader, aad?: Uint8Array) => Promise<EncryptionResult>
82
- encryptCek?: (cek: Uint8Array) => Promise<JweRecipient>
79
+ alg: string
80
+ enc: string
81
+ encrypt: (payload: Uint8Array, protectedHeader: JweProtectedHeader, aad?: Uint8Array) => Promise<EncryptionResult>
82
+ encryptCek?: (cek: Uint8Array) => Promise<JweRecipient>
83
83
  }
84
84
 
85
85
  export interface JweDecrypter {
86
- alg: string
87
- enc: string
88
- decrypt: (sealed: Uint8Array, iv: Uint8Array, aad?: Uint8Array, recipient?: JweRecipient) => Promise<Uint8Array | null>
86
+ alg: string
87
+ enc: string
88
+ decrypt: (sealed: Uint8Array, iv: Uint8Array, aad?: Uint8Array, recipient?: JweRecipient) => Promise<Uint8Array | null>
89
89
  }
90
90
 
91
91
  function jweAssertValid(jwe: JweJsonGeneral) {
92
- if (!(jwe.protected && jwe.iv && jwe.ciphertext && jwe.tag)) {
93
- throw Error('JWE is missing properties: protected, iv, ciphertext and/or tag')
94
- }
95
- if (jwe.recipients) {
96
- jwe.recipients.map((recipient: JweRecipient) => {
97
- if (!(recipient.header && recipient.encrypted_key)) {
98
- throw Error('Malformed JWE recipients; no header and encrypted key present')
99
- }
100
- })
101
- }
92
+ if (!(jwe.protected && jwe.iv && jwe.ciphertext && jwe.tag)) {
93
+ throw Error('JWE is missing properties: protected, iv, ciphertext and/or tag')
94
+ }
95
+ if (jwe.recipients) {
96
+ jwe.recipients.map((recipient: JweRecipient) => {
97
+ if (!(recipient.header && recipient.encrypted_key)) {
98
+ throw Error('Malformed JWE recipients; no header and encrypted key present')
99
+ }
100
+ })
101
+ }
102
102
  }
103
103
 
104
- function jweEncode({ciphertext, tag, iv, protectedHeader, recipients, aad, unprotected}: EncryptionResult & {
105
- aad?: Uint8Array,
106
- unprotected?: JweHeader
104
+ function jweEncode({
105
+ ciphertext,
106
+ tag,
107
+ iv,
108
+ protectedHeader,
109
+ recipients,
110
+ aad,
111
+ unprotected,
112
+ }: EncryptionResult & {
113
+ aad?: Uint8Array
114
+ unprotected?: JweHeader
107
115
  }): JweJsonGeneral {
108
- if (!recipients || recipients.length === 0) {
109
- throw Error(`No recipient found`)
110
- }
111
- return {
112
- ...(unprotected && {unprotected}),
113
- protected: <string>protectedHeader,
114
- iv: bytesToBase64url(iv),
115
- ciphertext: bytesToBase64url(ciphertext),
116
- ...(tag && {tag: bytesToBase64url(tag)}),
117
- ...(aad && {aad: bytesToBase64url(aad)}),
118
- recipients
119
- } satisfies JweJsonGeneral
116
+ if (!recipients || recipients.length === 0) {
117
+ throw Error(`No recipient found`)
118
+ }
119
+ return {
120
+ ...(unprotected && { unprotected }),
121
+ protected: <string>protectedHeader,
122
+ iv: bytesToBase64url(iv),
123
+ ciphertext: bytesToBase64url(ciphertext),
124
+ ...(tag && { tag: bytesToBase64url(tag) }),
125
+ ...(aad && { aad: bytesToBase64url(aad) }),
126
+ recipients,
127
+ } satisfies JweJsonGeneral
120
128
  }
121
129
 
122
130
  export class CompactJwtEncrypter implements JweEncrypter {
123
- private _alg: JweAlg | undefined;
124
- private _enc: JweEnc | undefined;
125
- private _keyManagementParams: JWEKeyManagementHeaderParameters | undefined
126
- private recipientKey: Uint8Array | jose.KeyLike //,EphemeralPublicKey | BaseJWK;
127
- private expirationTime
128
- private issuer: string | undefined
129
- private audience: string | string[] | undefined
130
-
131
- constructor(args: {
132
- key: Uint8Array | jose.KeyLike /*EphemeralPublicKey | BaseJWK*/,
133
- alg?: JweAlg,
134
- enc?: JweEnc,
135
- keyManagementParams?: JWEKeyManagementHeaderParameters,
136
- expirationTime?: number | string | Date
137
- issuer?: string
138
- audience?: string | string[]
139
- }) {
140
- if (args?.alg) {
141
- this._alg = args.alg
142
- }
143
- if (args?.enc) {
144
- this._enc = args.enc
145
- }
146
- this._keyManagementParams = args.keyManagementParams
147
- this.recipientKey = args.key
148
- this.expirationTime = args.expirationTime
149
- this.issuer = args.issuer
150
- this.audience = args.audience
131
+ private _alg: JweAlg | undefined
132
+ private _enc: JweEnc | undefined
133
+ private _keyManagementParams: JWEKeyManagementHeaderParameters | undefined
134
+ private recipientKey: Uint8Array | jose.KeyLike //,EphemeralPublicKey | BaseJWK;
135
+ private expirationTime
136
+ private issuer: string | undefined
137
+ private audience: string | string[] | undefined
138
+
139
+ constructor(args: {
140
+ key: Uint8Array | jose.KeyLike /*EphemeralPublicKey | BaseJWK*/
141
+ alg?: JweAlg
142
+ enc?: JweEnc
143
+ keyManagementParams?: JWEKeyManagementHeaderParameters
144
+ expirationTime?: number | string | Date
145
+ issuer?: string
146
+ audience?: string | string[]
147
+ }) {
148
+ if (args?.alg) {
149
+ this._alg = args.alg
151
150
  }
152
-
153
- get enc(): string {
154
- if (!this._enc) {
155
- throw Error(`enc not set`)
156
- }
157
- return this._enc;
151
+ if (args?.enc) {
152
+ this._enc = args.enc
158
153
  }
159
-
160
- set enc(value: JweEnc | string) {
161
- // @ts-ignore
162
- if (!JweEncs.includes(value)) {
163
- throw Error(`invalid JWE enc value ${value}`)
164
- }
165
- this._enc = value as JweEnc;
154
+ this._keyManagementParams = args.keyManagementParams
155
+ this.recipientKey = args.key
156
+ this.expirationTime = args.expirationTime
157
+ this.issuer = args.issuer
158
+ this.audience = args.audience
159
+ }
160
+
161
+ get enc(): string {
162
+ if (!this._enc) {
163
+ throw Error(`enc not set`)
166
164
  }
165
+ return this._enc
166
+ }
167
167
 
168
- get alg(): string {
169
- if (!this._alg) {
170
- throw Error(`alg not set`)
171
- }
172
- return this._alg;
168
+ set enc(value: JweEnc | string) {
169
+ // @ts-ignore
170
+ if (!JweEncs.includes(value)) {
171
+ throw Error(`invalid JWE enc value ${value}`)
173
172
  }
173
+ this._enc = value as JweEnc
174
+ }
174
175
 
175
- set alg(value: JweAlg | string) {
176
- // @ts-ignore
177
- if (!JweAlgs.includes(value)) {
178
- throw Error(`invalid JWE alg value ${value}`)
179
- }
180
- this._alg = value as JweAlg;
176
+ get alg(): string {
177
+ if (!this._alg) {
178
+ throw Error(`alg not set`)
181
179
  }
180
+ return this._alg
181
+ }
182
182
 
183
- async encryptCompactJWT(
184
- payload: JwsPayload,
185
- jweProtectedHeader: JweProtectedHeader,
186
- aad?: Uint8Array | undefined
187
- ): Promise<string> {
188
- const protectedHeader = {
189
- ...jweProtectedHeader,
190
- alg: jweProtectedHeader.alg ?? this._alg,
191
- enc: jweProtectedHeader.enc ?? this._enc
192
- }
193
- if (!protectedHeader.alg || !protectedHeader.enc) {
194
- return Promise.reject(Error(`no 'alg' or 'enc' value set for the protected JWE header!`))
195
- }
196
- this.enc = protectedHeader.enc
197
- this.alg = protectedHeader.alg
198
- if (payload.exp) {
199
- this.expirationTime = payload.exp
200
- }
201
- if (payload.iss) {
202
- this.issuer = payload.iss
203
- }
204
- if (payload.aud) {
205
- this.audience = payload.aud
206
- }
207
- const encrypt = new jose.EncryptJWT(payload).setProtectedHeader({
208
- ...protectedHeader,
209
- alg: this.alg,
210
- enc: this.enc
211
- })
212
- if (this._alg!.startsWith('ECDH')) {
213
- if (!this._keyManagementParams) {
214
- return Promise.reject(Error(`ECDH requires key management params`))
215
- }
216
- encrypt.setKeyManagementParameters(this._keyManagementParams!)
217
- }
218
- if(this.expirationTime !== undefined) {
219
- encrypt.setExpirationTime(this.expirationTime)
220
- }
221
-
222
- if (this.issuer) {
223
- encrypt.setIssuer(this.issuer)
224
- }
225
- if (this.audience) {
226
- encrypt.setAudience(this.audience)
227
- }
228
- return await encrypt.encrypt(this.recipientKey)
183
+ set alg(value: JweAlg | string) {
184
+ // @ts-ignore
185
+ if (!JweAlgs.includes(value)) {
186
+ throw Error(`invalid JWE alg value ${value}`)
229
187
  }
230
-
231
- public static async decryptCompactJWT(jwt: string, key: KeyLike | Uint8Array, options?: JWTDecryptOptions) {
232
- return await jose.jwtDecrypt(jwt, key, options)
188
+ this._alg = value as JweAlg
189
+ }
190
+
191
+ async encryptCompactJWT(payload: JwsPayload, jweProtectedHeader: JweProtectedHeader, aad?: Uint8Array | undefined): Promise<string> {
192
+ const protectedHeader = {
193
+ ...jweProtectedHeader,
194
+ alg: jweProtectedHeader.alg ?? this._alg,
195
+ enc: jweProtectedHeader.enc ?? this._enc,
196
+ }
197
+ if (!protectedHeader.alg || !protectedHeader.enc) {
198
+ return Promise.reject(Error(`no 'alg' or 'enc' value set for the protected JWE header!`))
199
+ }
200
+ this.enc = protectedHeader.enc
201
+ this.alg = protectedHeader.alg
202
+ if (payload.exp) {
203
+ this.expirationTime = payload.exp
204
+ }
205
+ if (payload.iss) {
206
+ this.issuer = payload.iss
207
+ }
208
+ if (payload.aud) {
209
+ this.audience = payload.aud
210
+ }
211
+ const encrypt = new jose.EncryptJWT(payload).setProtectedHeader({
212
+ ...protectedHeader,
213
+ alg: this.alg,
214
+ enc: this.enc,
215
+ })
216
+ if (this._alg!.startsWith('ECDH')) {
217
+ if (!this._keyManagementParams) {
218
+ return Promise.reject(Error(`ECDH requires key management params`))
219
+ }
220
+ encrypt.setKeyManagementParameters(this._keyManagementParams!)
221
+ }
222
+ if (this.expirationTime !== undefined) {
223
+ encrypt.setExpirationTime(this.expirationTime)
233
224
  }
234
225
 
235
- async encrypt(
236
- payload: Uint8Array,
237
- jweProtectedHeader: JweProtectedHeader,
238
- aad?: Uint8Array | undefined
239
- ): Promise<EncryptionResult> {
240
- const jwt = await this.encryptCompactJWT(JSON.parse(u8a.toString(payload)), jweProtectedHeader, aad)
241
- const [protectedHeader, encryptedKey, ivB64, payloadB64, tagB64,] = jwt.split('.')
242
- //[jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join('.');
243
- console.log(`FIXME: TO EncryptionResult`)
244
-
245
- return {
246
- protectedHeader,
247
- tag: base64ToBytes(tagB64),
248
- ciphertext: base64ToBytes(payloadB64),
249
- iv: base64ToBytes(ivB64),
250
- recipients: [
226
+ if (this.issuer) {
227
+ encrypt.setIssuer(this.issuer)
228
+ }
229
+ if (this.audience) {
230
+ encrypt.setAudience(this.audience)
231
+ }
232
+ return await encrypt.encrypt(this.recipientKey)
233
+ }
251
234
 
252
- {
253
- //fixme
254
- // header: protectedHeader,
255
- ...(encryptedKey && { encrypted_key: encryptedKey})
235
+ public static async decryptCompactJWT(jwt: string, key: KeyLike | Uint8Array, options?: JWTDecryptOptions) {
236
+ return await jose.jwtDecrypt(jwt, key, options)
237
+ }
256
238
 
257
- }
258
- ]
259
- }
239
+ async encrypt(payload: Uint8Array, jweProtectedHeader: JweProtectedHeader, aad?: Uint8Array | undefined): Promise<EncryptionResult> {
240
+ const jwt = await this.encryptCompactJWT(JSON.parse(u8a.toString(payload)), jweProtectedHeader, aad)
241
+ const [protectedHeader, encryptedKey, ivB64, payloadB64, tagB64] = jwt.split('.')
242
+ //[jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join('.');
243
+ console.log(`FIXME: TO EncryptionResult`)
260
244
 
245
+ return {
246
+ protectedHeader,
247
+ tag: base64ToBytes(tagB64),
248
+ ciphertext: base64ToBytes(payloadB64),
249
+ iv: base64ToBytes(ivB64),
250
+ recipients: [
251
+ {
252
+ //fixme
253
+ // header: protectedHeader,
254
+ ...(encryptedKey && { encrypted_key: encryptedKey }),
255
+ },
256
+ ],
261
257
  }
258
+ }
262
259
 
263
- // encryptCek?: ((cek: Uint8Array) => Promise<JweRecipient>) | undefined;
264
-
260
+ // encryptCek?: ((cek: Uint8Array) => Promise<JweRecipient>) | undefined;
265
261
  }
266
262
 
267
263
  export async function createJwe(
268
- cleartext: Uint8Array,
269
- encrypters: JweEncrypter[],
270
- protectedHeader: JweProtectedHeader,
271
- aad?: Uint8Array
264
+ cleartext: Uint8Array,
265
+ encrypters: JweEncrypter[],
266
+ protectedHeader: JweProtectedHeader,
267
+ aad?: Uint8Array
272
268
  ): Promise<JweJsonGeneral> {
273
- if (encrypters.length === 0) {
274
- throw Error('JWE needs at least 1 encryptor')
269
+ if (encrypters.length === 0) {
270
+ throw Error('JWE needs at least 1 encryptor')
271
+ }
272
+ if (encrypters.find((enc) => enc.alg === 'dir' || enc.alg === 'ECDH-ES')) {
273
+ if (encrypters.length !== 1) {
274
+ throw Error(`JWE can only do "dir" or "ECDH-ES" encryption with one key. ${encrypters.length} supplied`)
275
275
  }
276
- if (encrypters.find(enc => enc.alg === 'dir' || enc.alg === 'ECDH-ES')) {
277
- if (encrypters.length !== 1) {
278
- throw Error(`JWE can only do "dir" or "ECDH-ES" encryption with one key. ${encrypters.length} supplied`)
279
- }
280
- const encryptionResult = await encrypters[0].encrypt(cleartext, protectedHeader, aad)
281
- return jweEncode({...encryptionResult, aad})
282
- } else {
283
- const tmpEnc = encrypters[0].enc
284
- if (!encrypters.reduce((acc, encrypter) => acc && encrypter.enc === tmpEnc, true)) {
285
- throw new Error('invalid_argument: Incompatible encrypters passed')
286
- }
287
- let cek: Uint8Array | undefined = undefined
288
- let jwe: JweJsonGeneral | undefined = undefined
289
- for (const encrypter of encrypters) {
290
- if (!cek) {
291
- const encryptionResult = await encrypter.encrypt(cleartext, protectedHeader, aad)
292
- cek = encryptionResult.cek
293
- jwe = jweEncode({...encryptionResult, aad})
294
- } else {
295
- const recipient = await encrypter.encryptCek?.(cek)
296
- if (recipient) {
297
- jwe?.recipients?.push(recipient)
298
- }
299
- }
300
- }
301
- if (!jwe) {
302
- throw Error(`No JWE constructed`)
276
+ const encryptionResult = await encrypters[0].encrypt(cleartext, protectedHeader, aad)
277
+ return jweEncode({ ...encryptionResult, aad })
278
+ } else {
279
+ const tmpEnc = encrypters[0].enc
280
+ if (!encrypters.reduce((acc, encrypter) => acc && encrypter.enc === tmpEnc, true)) {
281
+ throw new Error('invalid_argument: Incompatible encrypters passed')
282
+ }
283
+ let cek: Uint8Array | undefined = undefined
284
+ let jwe: JweJsonGeneral | undefined = undefined
285
+ for (const encrypter of encrypters) {
286
+ if (!cek) {
287
+ const encryptionResult = await encrypter.encrypt(cleartext, protectedHeader, aad)
288
+ cek = encryptionResult.cek
289
+ jwe = jweEncode({ ...encryptionResult, aad })
290
+ } else {
291
+ const recipient = await encrypter.encryptCek?.(cek)
292
+ if (recipient) {
293
+ jwe?.recipients?.push(recipient)
303
294
  }
304
- return jwe
295
+ }
296
+ }
297
+ if (!jwe) {
298
+ throw Error(`No JWE constructed`)
305
299
  }
300
+ return jwe
301
+ }
306
302
  }
307
303
 
308
304
  /**
@@ -312,49 +308,52 @@ export async function createJwe(
312
308
  * @param unprotectedHeader
313
309
  * @param recipientUnprotectedHeader
314
310
  */
315
- export function jweMergeHeaders({protectedHeader, unprotectedHeader, recipientUnprotectedHeader}: {
316
- protectedHeader?: JweProtectedHeader,
317
- unprotectedHeader?: JweHeader,
318
- recipientUnprotectedHeader?: JweRecipientUnprotectedHeader
311
+ export function jweMergeHeaders({
312
+ protectedHeader,
313
+ unprotectedHeader,
314
+ recipientUnprotectedHeader,
315
+ }: {
316
+ protectedHeader?: JweProtectedHeader
317
+ unprotectedHeader?: JweHeader
318
+ recipientUnprotectedHeader?: JweRecipientUnprotectedHeader
319
319
  }): JweHeader {
320
- // TODO: Check that all headers/params are disjoint!
321
- const header = {...protectedHeader, ...unprotectedHeader, ...recipientUnprotectedHeader}
320
+ // TODO: Check that all headers/params are disjoint!
321
+ const header = { ...protectedHeader, ...unprotectedHeader, ...recipientUnprotectedHeader }
322
322
 
323
- if (!header.alg || !header.enc) {
324
- throw Error(`Either 'alg' or 'enc' are missing from the headers`)
325
- }
326
- return header as JweHeader
323
+ if (!header.alg || !header.enc) {
324
+ throw Error(`Either 'alg' or 'enc' are missing from the headers`)
325
+ }
326
+ return header as JweHeader
327
327
  }
328
328
 
329
329
  export async function decryptJwe(jwe: JweJsonGeneral, decrypter: JweDecrypter): Promise<Uint8Array> {
330
- jweAssertValid(jwe)
331
- const protectedHeader: JweProtectedHeader = JSON.parse(decodeBase64url(jwe.protected))
332
- if (protectedHeader?.enc !== decrypter.enc) {
333
- return Promise.reject(Error(`Decrypter enc '${decrypter.enc}' does not support header enc '${protectedHeader.enc}'`))
334
- } else if (!jwe.tag) {
335
- return Promise.reject(Error(`Decrypter enc '${decrypter.enc}' does not support header enc '${protectedHeader.enc}'`))
330
+ jweAssertValid(jwe)
331
+ const protectedHeader: JweProtectedHeader = JSON.parse(decodeBase64url(jwe.protected))
332
+ if (protectedHeader?.enc !== decrypter.enc) {
333
+ return Promise.reject(Error(`Decrypter enc '${decrypter.enc}' does not support header enc '${protectedHeader.enc}'`))
334
+ } else if (!jwe.tag) {
335
+ return Promise.reject(Error(`Decrypter enc '${decrypter.enc}' does not support header enc '${protectedHeader.enc}'`))
336
+ }
337
+ const sealed = toWebCryptoCiphertext(jwe.ciphertext, jwe.tag)
338
+ const aad = u8a.fromString(jwe.aad ? `${jwe.protected}.${jwe.aad}` : jwe.protected)
339
+ let cleartext = null
340
+ if (protectedHeader.alg === 'dir' && decrypter.alg === 'dir') {
341
+ cleartext = await decrypter.decrypt(sealed, base64ToBytes(jwe.iv), aad)
342
+ } else if (!jwe.recipients || jwe.recipients.length === 0) {
343
+ throw Error('missing recipients for JWE')
344
+ } else {
345
+ for (let i = 0; !cleartext && i < jwe.recipients.length; i++) {
346
+ const recipient: JweRecipient = jwe.recipients[i]
347
+ recipient.header = { ...recipient.header, ...protectedHeader } as JweRecipientUnprotectedHeader
348
+ if (recipient.header.alg === decrypter.alg) {
349
+ cleartext = await decrypter.decrypt(sealed, base64ToBytes(jwe.iv), aad, recipient)
350
+ }
336
351
  }
337
- const sealed = toWebCryptoCiphertext(jwe.ciphertext, jwe.tag)
338
- const aad = u8a.fromString(jwe.aad ? `${jwe.protected}.${jwe.aad}` : jwe.protected)
339
- let cleartext = null
340
- if (protectedHeader.alg === 'dir' && decrypter.alg === 'dir') {
341
- cleartext = await decrypter.decrypt(sealed, base64ToBytes(jwe.iv), aad)
342
- } else if (!jwe.recipients || jwe.recipients.length === 0) {
343
- throw Error('missing recipients for JWE')
344
- } else {
345
- for (let i = 0; !cleartext && i < jwe.recipients.length; i++) {
346
- const recipient: JweRecipient = jwe.recipients[i]
347
- recipient.header = {...recipient.header, ...protectedHeader} as JweRecipientUnprotectedHeader
348
- if (recipient.header.alg === decrypter.alg) {
349
- cleartext = await decrypter.decrypt(sealed, base64ToBytes(jwe.iv), aad, recipient)
350
- }
351
- }
352
- }
353
- if (cleartext === null) throw new Error('failure: Failed to decrypt')
354
- return cleartext
352
+ }
353
+ if (cleartext === null) throw new Error('failure: Failed to decrypt')
354
+ return cleartext
355
355
  }
356
356
 
357
-
358
357
  export function toWebCryptoCiphertext(ciphertext: string, tag: string): Uint8Array {
359
- return u8a.concat([base64ToBytes(ciphertext), base64ToBytes(tag)])
358
+ return u8a.concat([base64ToBytes(ciphertext), base64ToBytes(tag)])
360
359
  }