@sphereon/ssi-sdk-ext.jwt-service 0.24.1-unstable.130 → 0.24.1-unstable.133

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,55 +1,111 @@
1
- import { IAgentPlugin } from '@veramo/core'
1
+ import {IAgentPlugin} from '@veramo/core'
2
2
  import {
3
- createJwsCompact,
4
- CreateJwsCompactArgs,
5
- CreateJwsFlattenedArgs,
6
- CreateJwsJsonArgs,
7
- createJwsJsonFlattened,
8
- createJwsJsonGeneral,
9
- IJwsValidationResult,
10
- IJwtService,
11
- IRequiredContext,
12
- JwsCompactResult,
13
- JwsJsonFlattened,
14
- JwsJsonGeneral,
15
- PreparedJwsObject,
16
- prepareJwsObject,
17
- schema,
18
- verifyJws,
19
- VerifyJwsArgs,
3
+ createJwsCompact,
4
+ CreateJwsCompactArgs,
5
+ CreateJwsFlattenedArgs,
6
+ CreateJwsJsonArgs,
7
+ createJwsJsonFlattened,
8
+ createJwsJsonGeneral,
9
+ DecryptJweCompactJwtArgs,
10
+ EncryptJweCompactJwtArgs,
11
+ IJwsValidationResult,
12
+ IJwtService,
13
+ IRequiredContext,
14
+ jweAlg,
15
+ jweEnc,
16
+ JwsJsonFlattened,
17
+ JwsJsonGeneral,
18
+ JwtCompactResult,
19
+ JwtLogger,
20
+ PreparedJwsObject,
21
+ prepareJwsObject,
22
+ schema,
23
+ verifyJws,
24
+ VerifyJwsArgs,
20
25
  } from '..'
26
+ import {CompactJwtEncrypter} from "../functions/JWE";
27
+
28
+ import * as u8a from 'uint8arrays'
21
29
 
22
30
  /**
23
31
  * @public
24
32
  */
25
33
  export class JwtService implements IAgentPlugin {
26
- readonly schema = schema.IJwtService
27
- readonly methods: IJwtService = {
28
- jwtPrepareJws: this.jwtPrepareJws.bind(this),
29
- jwtCreateJwsJsonGeneralSignature: this.jwtCreateJwsJsonGeneralSignature.bind(this),
30
- jwtCreateJwsJsonFlattenedSignature: this.jwtCreateJwsJsonFlattenedSignature.bind(this),
31
- jwtCreateJwsCompactSignature: this.jwtCreateJwsCompactSignature.bind(this),
32
- jwtVerifyJwsSignature: this.jwtVerifyJwsSignature.bind(this),
33
- }
34
-
35
- private async jwtPrepareJws(args: CreateJwsJsonArgs, context: IRequiredContext): Promise<PreparedJwsObject> {
36
- return await prepareJwsObject(args, context)
37
- }
38
-
39
- private async jwtCreateJwsJsonGeneralSignature(args: CreateJwsJsonArgs, context: IRequiredContext): Promise<JwsJsonGeneral> {
40
- return await createJwsJsonGeneral(args, context)
41
- }
42
-
43
- private async jwtCreateJwsJsonFlattenedSignature(args: CreateJwsFlattenedArgs, context: IRequiredContext): Promise<JwsJsonFlattened> {
44
- return await createJwsJsonFlattened(args, context)
45
- }
46
-
47
- private async jwtCreateJwsCompactSignature(args: CreateJwsCompactArgs, context: IRequiredContext): Promise<JwsCompactResult> {
48
- // We wrap it in a json object for remote REST calls
49
- return { jwt: await createJwsCompact(args, context) }
50
- }
51
-
52
- private async jwtVerifyJwsSignature(args: VerifyJwsArgs, context: IRequiredContext): Promise<IJwsValidationResult> {
53
- return await verifyJws(args, context)
54
- }
34
+ readonly schema = schema.IJwtService
35
+ readonly methods: IJwtService = {
36
+ jwtPrepareJws: this.jwtPrepareJws.bind(this),
37
+ jwtCreateJwsJsonGeneralSignature: this.jwtCreateJwsJsonGeneralSignature.bind(this),
38
+ jwtCreateJwsJsonFlattenedSignature: this.jwtCreateJwsJsonFlattenedSignature.bind(this),
39
+ jwtCreateJwsCompactSignature: this.jwtCreateJwsCompactSignature.bind(this),
40
+ jwtVerifyJwsSignature: this.jwtVerifyJwsSignature.bind(this),
41
+ jwtEncryptJweCompactJwt: this.jwtEncryptJweCompactJwt.bind(this),
42
+ jwtDecryptJweCompactJwt: this.jwtDecryptJweCompactJwt.bind(this)
43
+ }
44
+
45
+ private async jwtPrepareJws(args: CreateJwsJsonArgs, context: IRequiredContext): Promise<PreparedJwsObject> {
46
+ return await prepareJwsObject(args, context)
47
+ }
48
+
49
+ private async jwtCreateJwsJsonGeneralSignature(args: CreateJwsJsonArgs, context: IRequiredContext): Promise<JwsJsonGeneral> {
50
+ return await createJwsJsonGeneral(args, context)
51
+ }
52
+
53
+ private async jwtCreateJwsJsonFlattenedSignature(args: CreateJwsFlattenedArgs, context: IRequiredContext): Promise<JwsJsonFlattened> {
54
+ return await createJwsJsonFlattened(args, context)
55
+ }
56
+
57
+ private async jwtCreateJwsCompactSignature(args: CreateJwsCompactArgs, context: IRequiredContext): Promise<JwtCompactResult> {
58
+ // We wrap it in a json object for remote REST calls
59
+ return {jwt: await createJwsCompact(args, context)}
60
+ }
61
+
62
+ private async jwtVerifyJwsSignature(args: VerifyJwsArgs, context: IRequiredContext): Promise<IJwsValidationResult> {
63
+ return await verifyJws(args, context)
64
+ }
65
+
66
+ private async jwtEncryptJweCompactJwt(args: EncryptJweCompactJwtArgs, context: IRequiredContext): Promise<JwtCompactResult> {
67
+ const {payload, protectedHeader = {alg: args.alg, enc: args.enc}, recipientKey, issuer, expirationTime, audience} = args
68
+
69
+ console.log(JSON.stringify(args, null, 2))
70
+
71
+ const alg = jweAlg(args.alg) ?? jweAlg(protectedHeader.alg) ?? 'ECDH-ES'
72
+ const enc = jweEnc(args.enc) ?? jweEnc(protectedHeader.enc) ?? 'A256GCM'
73
+ const encJwks = recipientKey.jwks.length === 1 ? [recipientKey.jwks[0]] : recipientKey.jwks.filter(jwk => (jwk.kid && (jwk.kid === jwk.jwk.kid || jwk.kid === jwk.jwkThumbprint)) || jwk.jwk.use === 'enc')
74
+ if (encJwks.length === 0) {
75
+ return Promise.reject(Error(`No public JWK found that can be used to encrypt against`))
76
+ }
77
+ const jwkInfo = encJwks[0]
78
+ if (encJwks.length > 0) {
79
+ JwtLogger.warning(`More than one JWK with 'enc' usage found. Selected the first one as no 'kid' was provided`, encJwks)
80
+ }
81
+ if (jwkInfo.jwk.kty?.startsWith('EC') !== true || !alg.startsWith('ECDH')) {
82
+ return Promise.reject(Error(`Currently only ECDH-ES is supported for encryption. JWK alg ${jwkInfo.jwk.kty}, header alg ${alg}`)) // TODO: Probably we support way more already
83
+ }
84
+ const apuVal = protectedHeader.apu ?? args.apu
85
+ const apu = apuVal ? u8a.fromString(apuVal, 'base64url') : undefined
86
+ const apvVal = protectedHeader.apv ?? args.apv
87
+ const apv = apvVal ? u8a.fromString(apvVal, 'base64url') : undefined
88
+
89
+ const pubKey = await crypto.subtle.importKey('jwk', jwkInfo.jwk, {
90
+ name: 'ECDH',
91
+ namedCurve: 'P-256',
92
+ }, true, [])
93
+ const encrypter = new CompactJwtEncrypter({
94
+ enc,
95
+ alg,
96
+ keyManagementParams: {apu, apv},
97
+ key: pubKey,
98
+ issuer,
99
+ expirationTime,
100
+ audience
101
+ })
102
+
103
+ const jwe = await encrypter.encryptCompactJWT(payload, {})
104
+ return {jwt: jwe}
105
+ }
106
+
107
+ private async jwtDecryptJweCompactJwt(args: DecryptJweCompactJwtArgs, context: IRequiredContext): Promise<JwtCompactResult> {
108
+
109
+ return {jwt: "FIXME"}
110
+ }
55
111
  }
@@ -0,0 +1,358 @@
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
+ import * as u8a from 'uint8arrays'
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
+
20
+
21
+ export interface EncryptionResult {
22
+ ciphertext: Uint8Array
23
+ tag: Uint8Array
24
+ iv: Uint8Array
25
+ protectedHeader?: string
26
+ recipients?: JweRecipient[]
27
+ cek?: Uint8Array
28
+ }
29
+
30
+
31
+ export const generateContentEncryptionKey = async ({alg, randomSource = defaultRandomSource}: {
32
+ alg: JweEnc,
33
+ randomSource?: RandomSource
34
+ }): 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)
57
+ }
58
+
59
+ /*
60
+ export const generateContentEncryptionKeyfdsdf = async ({type = 'Secp256r1', ...rest}: {
61
+ type?: Extract<TKeyType, 'Secp256r1' | 'RSA'>,
62
+ kms?: string
63
+ }, context: IAgentContext<ISphereonKeyManager>): Promise<EphemeralPublicKey> => {
64
+
65
+ const kms = rest.kms ?? await context.agent.keyManagerGetDefaultKeyManagementSystem()
66
+ const key = await context.agent.keyManagerCreate({kms, type, opts: {ephemeral: true}})
67
+ const jwk = toJwkFromKey(key, {use: JwkKeyUse.Encryption, noKidThumbprint: true})
68
+ }
69
+ */
70
+ 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>
75
+ }
76
+
77
+
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>
83
+ }
84
+
85
+ export interface JweDecrypter {
86
+ alg: string
87
+ enc: string
88
+ decrypt: (sealed: Uint8Array, iv: Uint8Array, aad?: Uint8Array, recipient?: JweRecipient) => Promise<Uint8Array | null>
89
+ }
90
+
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
+ }
102
+ }
103
+
104
+ function jweEncode({ciphertext, tag, iv, protectedHeader, recipients, aad, unprotected}: EncryptionResult & {
105
+ aad?: Uint8Array,
106
+ unprotected?: JweHeader
107
+ }): 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
120
+ }
121
+
122
+ 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 ?? '10 minutes'
149
+ this.issuer = args.issuer
150
+ this.audience = args.audience
151
+ }
152
+
153
+ get enc(): string {
154
+ if (!this._enc) {
155
+ throw Error(`enc not set`)
156
+ }
157
+ return this._enc;
158
+ }
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;
166
+ }
167
+
168
+ get alg(): string {
169
+ if (!this._alg) {
170
+ throw Error(`alg not set`)
171
+ }
172
+ return this._alg;
173
+ }
174
+
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;
181
+ }
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
+ // We always set the expiration time for encrypted JWTs (values are set above)
219
+ encrypt.setExpirationTime(this.expirationTime)
220
+ if (this.issuer) {
221
+ encrypt.setIssuer(this.issuer)
222
+ }
223
+ if (this.audience) {
224
+ encrypt.setAudience(this.audience)
225
+ }
226
+ return await encrypt.encrypt(this.recipientKey)
227
+ }
228
+
229
+ public static async decryptCompactJWT(jwt: string, key: KeyLike | Uint8Array, options?: JWTDecryptOptions) {
230
+ return await jose.jwtDecrypt(jwt, key, options)
231
+ }
232
+
233
+ async encrypt(
234
+ payload: Uint8Array,
235
+ jweProtectedHeader: JweProtectedHeader,
236
+ aad?: Uint8Array | undefined
237
+ ): Promise<EncryptionResult> {
238
+ const jwt = await this.encryptCompactJWT(JSON.parse(u8a.toString(payload)), jweProtectedHeader, aad)
239
+ const [protectedHeader, encryptedKey, ivB64, payloadB64, tagB64,] = jwt.split('.')
240
+ //[jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join('.');
241
+ console.log(`FIXME: TO EncryptionResult`)
242
+
243
+ return {
244
+ protectedHeader,
245
+ tag: base64ToBytes(tagB64),
246
+ ciphertext: base64ToBytes(payloadB64),
247
+ iv: base64ToBytes(ivB64),
248
+ recipients: [
249
+
250
+ {
251
+ //fixme
252
+ // header: protectedHeader,
253
+ ...(encryptedKey && { encrypted_key: encryptedKey})
254
+
255
+ }
256
+ ]
257
+ }
258
+
259
+ }
260
+
261
+ // encryptCek?: ((cek: Uint8Array) => Promise<JweRecipient>) | undefined;
262
+
263
+ }
264
+
265
+ export async function createJwe(
266
+ cleartext: Uint8Array,
267
+ encrypters: JweEncrypter[],
268
+ protectedHeader: JweProtectedHeader,
269
+ aad?: Uint8Array
270
+ ): Promise<JweJsonGeneral> {
271
+ if (encrypters.length === 0) {
272
+ throw Error('JWE needs at least 1 encryptor')
273
+ }
274
+ if (encrypters.find(enc => enc.alg === 'dir' || enc.alg === 'ECDH-ES')) {
275
+ if (encrypters.length !== 1) {
276
+ throw Error(`JWE can only do "dir" or "ECDH-ES" encryption with one key. ${encrypters.length} supplied`)
277
+ }
278
+ const encryptionResult = await encrypters[0].encrypt(cleartext, protectedHeader, aad)
279
+ return jweEncode({...encryptionResult, aad})
280
+ } else {
281
+ const tmpEnc = encrypters[0].enc
282
+ if (!encrypters.reduce((acc, encrypter) => acc && encrypter.enc === tmpEnc, true)) {
283
+ throw new Error('invalid_argument: Incompatible encrypters passed')
284
+ }
285
+ let cek: Uint8Array | undefined = undefined
286
+ let jwe: JweJsonGeneral | undefined = undefined
287
+ for (const encrypter of encrypters) {
288
+ if (!cek) {
289
+ const encryptionResult = await encrypter.encrypt(cleartext, protectedHeader, aad)
290
+ cek = encryptionResult.cek
291
+ jwe = jweEncode({...encryptionResult, aad})
292
+ } else {
293
+ const recipient = await encrypter.encryptCek?.(cek)
294
+ if (recipient) {
295
+ jwe?.recipients?.push(recipient)
296
+ }
297
+ }
298
+ }
299
+ if (!jwe) {
300
+ throw Error(`No JWE constructed`)
301
+ }
302
+ return jwe
303
+ }
304
+ }
305
+
306
+ /**
307
+ * Merges all headers, so we get a unified header.
308
+ *
309
+ * @param protectedHeader
310
+ * @param unprotectedHeader
311
+ * @param recipientUnprotectedHeader
312
+ */
313
+ export function jweMergeHeaders({protectedHeader, unprotectedHeader, recipientUnprotectedHeader}: {
314
+ protectedHeader?: JweProtectedHeader,
315
+ unprotectedHeader?: JweHeader,
316
+ recipientUnprotectedHeader?: JweRecipientUnprotectedHeader
317
+ }): JweHeader {
318
+ // TODO: Check that all headers/params are disjoint!
319
+ const header = {...protectedHeader, ...unprotectedHeader, ...recipientUnprotectedHeader}
320
+
321
+ if (!header.alg || !header.enc) {
322
+ throw Error(`Either 'alg' or 'enc' are missing from the headers`)
323
+ }
324
+ return header as JweHeader
325
+ }
326
+
327
+ export async function decryptJwe(jwe: JweJsonGeneral, decrypter: JweDecrypter): Promise<Uint8Array> {
328
+ jweAssertValid(jwe)
329
+ const protectedHeader: JweProtectedHeader = JSON.parse(decodeBase64url(jwe.protected))
330
+ if (protectedHeader?.enc !== decrypter.enc) {
331
+ return Promise.reject(Error(`Decrypter enc '${decrypter.enc}' does not support header enc '${protectedHeader.enc}'`))
332
+ } else if (!jwe.tag) {
333
+ return Promise.reject(Error(`Decrypter enc '${decrypter.enc}' does not support header enc '${protectedHeader.enc}'`))
334
+ }
335
+ const sealed = toWebCryptoCiphertext(jwe.ciphertext, jwe.tag)
336
+ const aad = u8a.fromString(jwe.aad ? `${jwe.protected}.${jwe.aad}` : jwe.protected)
337
+ let cleartext = null
338
+ if (protectedHeader.alg === 'dir' && decrypter.alg === 'dir') {
339
+ cleartext = await decrypter.decrypt(sealed, base64ToBytes(jwe.iv), aad)
340
+ } else if (!jwe.recipients || jwe.recipients.length === 0) {
341
+ throw Error('missing recipients for JWE')
342
+ } else {
343
+ for (let i = 0; !cleartext && i < jwe.recipients.length; i++) {
344
+ const recipient: JweRecipient = jwe.recipients[i]
345
+ recipient.header = {...recipient.header, ...protectedHeader} as JweRecipientUnprotectedHeader
346
+ if (recipient.header.alg === decrypter.alg) {
347
+ cleartext = await decrypter.decrypt(sealed, base64ToBytes(jwe.iv), aad, recipient)
348
+ }
349
+ }
350
+ }
351
+ if (cleartext === null) throw new Error('failure: Failed to decrypt')
352
+ return cleartext
353
+ }
354
+
355
+
356
+ export function toWebCryptoCiphertext(ciphertext: string, tag: string): Uint8Array {
357
+ return u8a.concat([base64ToBytes(ciphertext), base64ToBytes(tag)])
358
+ }
@@ -33,13 +33,13 @@ import {
33
33
  JwsJsonGeneral,
34
34
  JwsJsonGeneralWithIdentifiers,
35
35
  JwsJsonSignature, JwsJsonSignatureWithIdentifier,
36
- JwtHeader,
37
- JwtPayload,
36
+ JwsHeader,
37
+ JwsPayload,
38
38
  PreparedJwsObject,
39
- VerifyJwsArgs,
39
+ VerifyJwsArgs, JweHeader,
40
40
  } from '../types/IJwtService'
41
41
 
42
- const payloadToBytes = (payload: string | JwtPayload | Uint8Array): Uint8Array => {
42
+ const payloadToBytes = (payload: string | JwsPayload | Uint8Array): Uint8Array => {
43
43
  const isBytes = payload instanceof Uint8Array
44
44
  const isString = typeof payload === 'string'
45
45
  return isBytes ? payload : isString ? u8a.fromString(payload, 'base64url') : u8a.fromString(JSON.stringify(payload), 'utf-8')
@@ -50,7 +50,7 @@ export const prepareJwsObject = async (args: CreateJwsJsonArgs, context: IRequir
50
50
 
51
51
  const { noIdentifierInHeader = false } = issuer
52
52
  const identifier = await ensureManagedIdentifierResult(issuer, context)
53
- await checkAndUpdateJwtHeader({ mode, identifier, noIdentifierInHeader, header: protectedHeader }, context)
53
+ await checkAndUpdateJwsHeader({ mode, identifier, noIdentifierInHeader, header: protectedHeader }, context)
54
54
  const isBytes = payload instanceof Uint8Array
55
55
  const isString = typeof payload === 'string'
56
56
  if (!isBytes && !isString) {
@@ -138,7 +138,7 @@ export const createJwsJsonGeneral = async (args: CreateJwsJsonArgs, context: IRe
138
138
  * @param context
139
139
  */
140
140
 
141
- export const checkAndUpdateJwtHeader = async (
141
+ export const checkAndUpdateJwsHeader = async (
142
142
  {
143
143
  mode = 'auto',
144
144
  identifier,
@@ -148,7 +148,7 @@ export const checkAndUpdateJwtHeader = async (
148
148
  mode?: JwsIdentifierMode
149
149
  identifier: ManagedIdentifierResult
150
150
  noIdentifierInHeader?: boolean
151
- header: JwtHeader
151
+ header: JwsHeader
152
152
  },
153
153
  context: IRequiredContext
154
154
  ) => {
@@ -179,7 +179,7 @@ const checkAndUpdateX5cHeader = async (
179
179
  identifier,
180
180
  noIdentifierInHeader = false,
181
181
  }: {
182
- header: JwtHeader
182
+ header: JwsHeader | JweHeader
183
183
  identifier: ManagedIdentifierResult
184
184
  noIdentifierInHeader?: boolean
185
185
  },
@@ -208,7 +208,7 @@ const checkAndUpdateDidHeader = async (
208
208
  identifier,
209
209
  noIdentifierInHeader = false,
210
210
  }: {
211
- header: JwtHeader
211
+ header: JwsHeader | JweHeader
212
212
  identifier: ManagedIdentifierResult
213
213
  noIdentifierInHeader?: boolean
214
214
  },
@@ -237,7 +237,7 @@ const checkAndUpdateJwkHeader = async (
237
237
  identifier,
238
238
  noIdentifierInHeader = false,
239
239
  }: {
240
- header: JwtHeader
240
+ header: JwsHeader | JweHeader
241
241
  identifier: ManagedIdentifierResult
242
242
  noIdentifierInHeader?: boolean
243
243
  },
@@ -246,7 +246,7 @@ const checkAndUpdateJwkHeader = async (
246
246
  const { jwk } = header
247
247
  if (jwk) {
248
248
  // let's resolve the provided x5c to be sure
249
- const jwkIdentifier = await context.agent.identifierManagedGetByJwk({ identifier: jwk })
249
+ const jwkIdentifier = await context.agent.identifierManagedGetByJwk({ identifier: jwk as JWK })
250
250
  if (jwkIdentifier.kmsKeyRef !== identifier.kmsKeyRef) {
251
251
  return Promise.reject(Error(`A jwk header was present, but its value did not match the provided signing jwk or kid!`))
252
252
  }
@@ -265,7 +265,7 @@ const checkAndUpdateKidHeader = async (
265
265
  identifier,
266
266
  noIdentifierInHeader = false,
267
267
  }: {
268
- header: JwtHeader
268
+ header: JwsHeader | JweHeader
269
269
  identifier: ManagedIdentifierResult
270
270
  noIdentifierInHeader?: boolean
271
271
  },
@@ -376,7 +376,7 @@ export const toJwsJsonGeneral = async ({ jws }: { jws: Jws }, context: IAgentCon
376
376
  }
377
377
 
378
378
  async function resolveExternalIdentifierFromJwsHeader(
379
- protectedHeader: JwtHeader,
379
+ protectedHeader: JwsHeader,
380
380
  context: IAgentContext<IIdentifierResolution>,
381
381
  args: {
382
382
  jws: Jws
@@ -422,7 +422,7 @@ export const toJwsJsonGeneralWithIdentifiers = async (
422
422
  const jws = await toJwsJsonGeneral(args, context)
423
423
  const signatures = (await Promise.all(
424
424
  jws.signatures.map(async (signature) => {
425
- const protectedHeader: JwtHeader = decodeJoseBlob(signature.protected)
425
+ const protectedHeader: JwsHeader = decodeJoseBlob(signature.protected)
426
426
  const identifier = args.jwk
427
427
  ? await resolveExternalJwkIdentifier({ identifier: args.jwk }, context)
428
428
  : await resolveExternalIdentifierFromJwsHeader(protectedHeader, context, args)
@@ -432,6 +432,6 @@ export const toJwsJsonGeneralWithIdentifiers = async (
432
432
  return undefined
433
433
  })
434
434
  )).filter(signature => signature !== undefined ) as JwsJsonSignatureWithIdentifier[]
435
-
435
+
436
436
  return { payload: jws.payload, signatures }
437
437
  }
package/src/index.ts CHANGED
@@ -1,8 +1,12 @@
1
+ import {Loggers} from "@sphereon/ssi-types";
2
+
1
3
  /**
2
4
  * @internal
3
5
  */
4
6
  const schema = require('../plugin.schema.json')
5
7
  export { schema }
8
+
9
+ export const JwtLogger = Loggers.DEFAULT.get('sphereon:sdk:jwt')
6
10
  /**
7
11
  * @public
8
12
  */