@sphereon/ssi-sdk.sd-jwt 0.34.1-fix.79 → 0.34.1-next.278

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.
@@ -0,0 +1,316 @@
1
+ import { beforeAll, describe, expect, it } from 'vitest'
2
+ import { KBJwt } from '@sd-jwt/core'
3
+ import { decodeSdJwt } from '@sd-jwt/decode'
4
+ import { SdJwtVcPayload } from '@sd-jwt/sd-jwt-vc'
5
+ import { DisclosureFrame, kbPayload } from '@sd-jwt/types'
6
+ import { JwkDIDProvider } from '@sphereon/ssi-sdk-ext.did-provider-jwk'
7
+ import { getDidJwkResolver } from '@sphereon/ssi-sdk-ext.did-resolver-jwk'
8
+ import { IdentifierResolution, IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
9
+ import { IJwtService, JwtService } from '@sphereon/ssi-sdk-ext.jwt-service'
10
+ import { MemoryKeyStore, MemoryPrivateKeyStore, SphereonKeyManager } from '@sphereon/ssi-sdk-ext.key-manager'
11
+ import { SphereonKeyManagementSystem } from '@sphereon/ssi-sdk-ext.kms-local'
12
+ import { ImDLMdoc, MDLMdoc } from '@sphereon/ssi-sdk.mdl-mdoc'
13
+ import { createAgent, IDIDManager, IKeyManager, IResolver, TAgent } from '@veramo/core'
14
+ import { DIDManager, MemoryDIDStore } from '@veramo/did-manager'
15
+ import { DIDResolverPlugin } from '@veramo/did-resolver'
16
+ import { DIDDocument, Resolver, VerificationMethod } from 'did-resolver'
17
+ import { defaultGenerateDigest } from '../defaultCallbacks'
18
+ import { ISDJwtPlugin, SDJwtPlugin } from '../index'
19
+ import { SdJwtVcdm2Payload } from '@sphereon/ssi-types'
20
+
21
+ type AgentType = IDIDManager & IKeyManager & IIdentifierResolution & IJwtService & IResolver & ISDJwtPlugin & ImDLMdoc
22
+
23
+ describe('Agent plugin', () => {
24
+ let agent: TAgent<AgentType>
25
+
26
+ let issuer: string
27
+
28
+ let holder: string
29
+
30
+ // Issuer Define the claims object with the user's information
31
+ const claims = {
32
+ sub: '',
33
+ credentialSubject: {
34
+ given_name: 'John',
35
+ family_name: 'Deo',
36
+ email: 'johndeo@example.com',
37
+ phone: '+1-202-555-0101',
38
+ address: {
39
+ street_address: '123 Main St',
40
+ locality: 'Anytown',
41
+ region: 'Anystate',
42
+ country: 'US',
43
+ },
44
+ birthdate: '1940-01-01',
45
+ },
46
+ }
47
+
48
+ // Issuer Define the disclosure frame to specify which claims can be disclosed
49
+ const disclosureFrame: DisclosureFrame<typeof claims> = {
50
+ credentialSubject: {
51
+ _sd: ['given_name', 'family_name', 'email', 'phone', 'address', 'birthdate'],
52
+ },
53
+ }
54
+ let testVcdm2SdJwtCredentialPayload: SdJwtVcdm2Payload
55
+
56
+ beforeAll(async () => {
57
+ agent = createAgent<AgentType>({
58
+ plugins: [
59
+ new SDJwtPlugin(),
60
+ new IdentifierResolution(),
61
+ new JwtService(),
62
+ new SphereonKeyManager({
63
+ store: new MemoryKeyStore(),
64
+ kms: {
65
+ local: new SphereonKeyManagementSystem(new MemoryPrivateKeyStore()),
66
+ },
67
+ }),
68
+ new DIDResolverPlugin({
69
+ resolver: new Resolver({
70
+ ...getDidJwkResolver(),
71
+ }),
72
+ }),
73
+ new DIDManager({
74
+ store: new MemoryDIDStore(),
75
+ defaultProvider: 'did:jwk',
76
+ providers: {
77
+ 'did:jwk': new JwkDIDProvider({
78
+ defaultKms: 'local',
79
+ }),
80
+ },
81
+ }),
82
+ ],
83
+ })
84
+ issuer = await agent
85
+ .didManagerCreate({
86
+ kms: 'local',
87
+ provider: 'did:jwk',
88
+ alias: 'issuer',
89
+ //we use this curve since nodejs does not support ES256k which is the default one.
90
+ options: { keyType: 'Secp256r1' },
91
+ })
92
+ .then((did) => {
93
+ // we add a key reference
94
+ return `${did.did}#0`
95
+ })
96
+ holder = await agent
97
+ .didManagerCreate({
98
+ kms: 'local',
99
+ provider: 'did:jwk',
100
+ alias: 'holder',
101
+ //we use this curve since nodejs does not support ES256k which is the default one.
102
+ options: { keyType: 'Secp256r1' },
103
+ })
104
+ .then((did) => `${did.did}#0`)
105
+ claims.sub = holder
106
+
107
+ testVcdm2SdJwtCredentialPayload = {
108
+ ...claims,
109
+ '@context': ['https://www.w3.org/ns/credentials/v2'],
110
+ type: ['VerifiableCredential'],
111
+ issuer,
112
+ validFrom: '2021-01-01T00:00:00Z',
113
+ // iat: Math.floor(new Date().getTime() / 1000),
114
+ }
115
+ })
116
+
117
+ it('create a sd-jwt vcdm2', async () => {
118
+ const credentialPayload: SdJwtVcdm2Payload = {
119
+ ...claims,
120
+ '@context': ['https://www.w3.org/ns/credentials/v2'],
121
+ type: ['VerifiableCredential'],
122
+ issuer,
123
+ validFrom: '2021-01-01T00:00:00Z',
124
+ iat: Math.floor(new Date().getTime() / 1000),
125
+ }
126
+ const credential = await agent.createSdJwtVc({
127
+ credentialPayload,
128
+ disclosureFrame,
129
+ })
130
+ expect(credential).toBeDefined()
131
+ })
132
+
133
+ it('create sd-jwt vcdm2 without an issuer', async () => {
134
+ const credentialPayload = {
135
+ ...claims,
136
+ '@context': ['https://www.w3.org/ns/credentials/v2'],
137
+ type: ['VerifiableCredential'],
138
+ validFrom: '2021-01-01T00:00:00Z',
139
+ // iat: Math.floor(new Date().getTime() / 1000),
140
+ }
141
+ await expect(
142
+ agent.createSdJwtVc({
143
+ credentialPayload: credentialPayload as unknown as SdJwtVcPayload,
144
+ disclosureFrame,
145
+ }),
146
+ ).rejects.toThrow('No issuer (iss or VCDM 2 issuer) found in SD-JWT or no VCDM2 SD-JWT or SD-JWT VC')
147
+ })
148
+
149
+ it('verify a sd-jwt vcdm2', async () => {
150
+ const credential = await agent.createSdJwtVc({
151
+ credentialPayload: testVcdm2SdJwtCredentialPayload,
152
+ disclosureFrame: disclosureFrame,
153
+ })
154
+ const result = await agent.verifySdJwtVc({
155
+ credential: credential.credential,
156
+ })
157
+ expect(result.payload).toBeDefined()
158
+ }, 5000)
159
+
160
+ it('create a presentation', async () => {
161
+ const credentialPayload = testVcdm2SdJwtCredentialPayload
162
+ const credential = await agent.createSdJwtVc({
163
+ credentialPayload,
164
+ disclosureFrame,
165
+ })
166
+ const presentation = await agent.createSdJwtPresentation({
167
+ presentation: credential.credential,
168
+ presentationFrame: { given_name: true },
169
+ kb: {
170
+ payload: {
171
+ aud: '1',
172
+ iat: 1,
173
+ nonce: '342',
174
+ },
175
+ },
176
+ })
177
+ expect(presentation).toBeDefined()
178
+ const decoded = await decodeSdJwt(presentation.presentation, defaultGenerateDigest)
179
+ expect(decoded.kbJwt).toBeDefined()
180
+ expect(((decoded.kbJwt as KBJwt).payload as kbPayload).aud).toBe('1')
181
+ })
182
+
183
+ it('create presentation with cnf', async () => {
184
+ const did = await agent.didManagerFind({ alias: 'holder' }).then((dids) => dids[0])
185
+ const resolvedDid = await agent.resolveDid({ didUrl: `${did.did}#0` })
186
+ const jwk: JsonWebKey = ((resolvedDid.didDocument as DIDDocument).verificationMethod as VerificationMethod[])[0].publicKeyJwk as JsonWebKey
187
+ const credentialPayload = {
188
+ ...testVcdm2SdJwtCredentialPayload,
189
+ cnf: {
190
+ jwk,
191
+ },
192
+ }
193
+ const credential = await agent.createSdJwtVc({
194
+ credentialPayload,
195
+ disclosureFrame,
196
+ })
197
+ const presentation = await agent.createSdJwtPresentation({
198
+ presentation: credential.credential,
199
+ presentationFrame: { given_name: true },
200
+ kb: {
201
+ payload: {
202
+ aud: '1',
203
+ iat: 1,
204
+ nonce: '342',
205
+ },
206
+ },
207
+ })
208
+ expect(presentation).toBeDefined()
209
+ const decoded = await decodeSdJwt(presentation.presentation, defaultGenerateDigest)
210
+ expect(decoded.kbJwt).toBeDefined()
211
+ expect(((decoded.kbJwt as KBJwt).payload as kbPayload).aud).toBe('1')
212
+ })
213
+
214
+ it('includes no holder reference', async () => {
215
+ const newClaims = JSON.parse(JSON.stringify(claims))
216
+ newClaims.sub = undefined
217
+ const credentialPayload: SdJwtVcPayload = {
218
+ ...newClaims,
219
+ iss: issuer,
220
+ iat: Math.floor(new Date().getTime() / 1000),
221
+ vct: '',
222
+ }
223
+ const credential = await agent.createSdJwtVc({
224
+ credentialPayload,
225
+ disclosureFrame,
226
+ })
227
+ const presentation = agent.createSdJwtPresentation({
228
+ presentation: credential.credential,
229
+ presentationFrame: { given_name: true },
230
+ kb: {
231
+ payload: {
232
+ aud: '1',
233
+ iat: 1,
234
+ nonce: '342',
235
+ },
236
+ },
237
+ })
238
+ await expect(presentation).rejects.toThrow('credential does not include a holder reference')
239
+ })
240
+
241
+ it('verify a presentation', async () => {
242
+ const holderDId = await agent.resolveDid({ didUrl: holder })
243
+ const jwk: JsonWebKey = ((holderDId.didDocument as DIDDocument).verificationMethod as VerificationMethod[])[0].publicKeyJwk as JsonWebKey
244
+ const credentialPayload: SdJwtVcPayload = {
245
+ ...claims,
246
+ iss: issuer,
247
+ iat: Math.floor(new Date().getTime() / 1000),
248
+ vct: '',
249
+ cnf: {
250
+ jwk,
251
+ },
252
+ }
253
+ const credential = await agent.createSdJwtVc({
254
+ credentialPayload,
255
+ disclosureFrame,
256
+ })
257
+ const presentation = await agent.createSdJwtPresentation({
258
+ presentation: credential.credential,
259
+ presentationFrame: { credentialSubject: {given_name: true} },
260
+ kb: {
261
+ payload: {
262
+ aud: '1',
263
+ iat: 1,
264
+ nonce: '342',
265
+ },
266
+ },
267
+ })
268
+ const result = await agent.verifySdJwtPresentation({
269
+ presentation: presentation.presentation,
270
+ requiredClaimKeys: ['credentialSubject.given_name'],
271
+ // we are not able to verify the kb yet since we have no reference to the public key of the holder.
272
+ keyBindingAud: '1',
273
+ keyBindingNonce: '342',
274
+ })
275
+ expect(result).toBeDefined()
276
+ expect((result.payload as typeof claims).credentialSubject.given_name).toBe('John')
277
+ })
278
+
279
+ it('verify a presentation with sub set', async () => {
280
+ const holderDId = await agent.resolveDid({ didUrl: holder })
281
+ const jwk: JsonWebKey = ((holderDId.didDocument as DIDDocument).verificationMethod as VerificationMethod[])[0].publicKeyJwk as JsonWebKey
282
+ const credentialPayload: SdJwtVcPayload = {
283
+ ...claims,
284
+ iss: issuer,
285
+ iat: Math.floor(new Date().getTime() / 1000),
286
+ vct: '',
287
+ cnf: {
288
+ jwk,
289
+ },
290
+ }
291
+ const credential = await agent.createSdJwtVc({
292
+ credentialPayload,
293
+ disclosureFrame,
294
+ })
295
+ const presentation = await agent.createSdJwtPresentation({
296
+ presentation: credential.credential,
297
+ presentationFrame: { credentialSubject: {given_name: true} },
298
+ kb: {
299
+ payload: {
300
+ aud: '1',
301
+ iat: 1,
302
+ nonce: '342',
303
+ },
304
+ },
305
+ })
306
+ const result = await agent.verifySdJwtPresentation({
307
+ presentation: presentation.presentation,
308
+ requiredClaimKeys: ['credentialSubject.given_name'],
309
+ // we are not able to verify the kb yet since we have no reference to the public key of the holder.
310
+ keyBindingAud: '1',
311
+ keyBindingNonce: '342',
312
+ })
313
+ expect(result).toBeDefined()
314
+ expect((result.payload as typeof claims).credentialSubject.given_name).toBe('John')
315
+ })
316
+ })
@@ -1,16 +1,16 @@
1
- import { Jwt, SDJwt } from '@sd-jwt/core'
2
- import { SDJwtVcInstance, SdJwtVcPayload } from '@sd-jwt/sd-jwt-vc'
3
- import { DisclosureFrame, Hasher, JwtPayload, KbVerifier, PresentationFrame, Signer, Verifier } from '@sd-jwt/types'
1
+ import { Jwt, SDJwt, type SdJwtPayload, type VerifierOptions } from '@sd-jwt/core'
2
+ import { SDJwtVcInstance, type SdJwtVcPayload } from '@sd-jwt/sd-jwt-vc'
3
+ import type { DisclosureFrame, HashAlgorithm, Hasher, JwtPayload, KbVerifier, PresentationFrame, Signer, Verifier } from '@sd-jwt/types'
4
4
  import { calculateJwkThumbprint, signatureAlgorithmFromKey } from '@sphereon/ssi-sdk-ext.key-utils'
5
- import { X509CertificateChainValidationOpts } from '@sphereon/ssi-sdk-ext.x509-utils'
6
- import { HasherSync, JsonWebKey, JWK, SdJwtTypeMetadata } from '@sphereon/ssi-types'
7
- import { IAgentPlugin } from '@veramo/core'
8
- import { decodeBase64url } from '@veramo/utils'
5
+ import type { X509CertificateChainValidationOpts } from '@sphereon/ssi-sdk-ext.x509-utils'
6
+ import type { HasherSync, JsonWebKey, JWK, SdJwtTypeMetadata } from '@sphereon/ssi-types'
7
+ import type { IAgentPlugin } from '@veramo/core'
8
+ // import { decodeBase64url } from '@veramo/utils'
9
9
  import Debug from 'debug'
10
10
  import { defaultGenerateDigest, defaultGenerateSalt, defaultVerifySignature } from './defaultCallbacks'
11
11
  import { funkeTestCA, sphereonCA } from './trustAnchors'
12
- import { assertValidTypeMetadata, fetchUrlWithErrorHandling, validateIntegrity } from './utils'
13
- import {
12
+ import { assertValidTypeMetadata, fetchUrlWithErrorHandling, getIssuerFromSdJwt, isSdjwtVcPayload, isVcdm2SdJwtPayload, validateIntegrity } from './utils'
13
+ import type {
14
14
  Claims,
15
15
  FetchSdJwtTypeMetadataFromVctUrlArgs,
16
16
  GetSignerForIdentifierArgs,
@@ -30,6 +30,10 @@ import {
30
30
  SignKeyArgs,
31
31
  SignKeyResult,
32
32
  } from './types'
33
+ import { SDJwtVcdm2Instance, SDJwtVcdmInstanceFactory } from './sdJwtVcdm2Instance'
34
+
35
+ // @ts-ignore
36
+ import * as u8a from 'uint8arrays'
33
37
 
34
38
  const debug = Debug('@sphereon/ssi-sdk.sd-jwt')
35
39
 
@@ -101,27 +105,47 @@ export class SDJwtPlugin implements IAgentPlugin {
101
105
  * @returns A signed SD-JWT credential.
102
106
  */
103
107
  async createSdJwtVc(args: ICreateSdJwtVcArgs, context: IRequiredContext): Promise<ICreateSdJwtVcResult> {
104
- const issuer = args.credentialPayload.iss
108
+ const payload = args.credentialPayload
109
+ const isVcdm2 = isVcdm2SdJwtPayload(payload)
110
+ const isSdJwtVc = isSdjwtVcPayload(payload)
111
+ const type = args.type ?? (isVcdm2 ? 'vc+sd-jwt' : 'dc+sd-jwt')
112
+
113
+ const issuer = getIssuerFromSdJwt(args.credentialPayload)
105
114
  if (!issuer) {
106
115
  throw new Error('credential.issuer must not be empty')
107
116
  }
108
117
  const { alg, signer, signingKey } = await this.getSignerForIdentifier({ identifier: issuer, resolution: args.resolution }, context)
109
- const sdjwt = new SDJwtVcInstance({
118
+ const signAlg = alg ?? signingKey?.alg ?? 'ES256'
119
+ const hashAlg: HashAlgorithm = /(\d{3})$/.test(signAlg) ? (`sha-${signAlg.slice(-3)}` as HashAlgorithm) : 'sha-256'
120
+ const sdjwt = SDJwtVcdmInstanceFactory.create(type, {
121
+ omitTyp: true,
110
122
  signer,
111
123
  hasher: this.registeredImplementations.hasher,
112
124
  saltGenerator: this.registeredImplementations.saltGenerator,
113
- signAlg: alg ?? 'ES256',
114
- hashAlg: 'sha-256',
125
+ signAlg,
126
+ hashAlg,
115
127
  })
116
128
 
117
- const credential = await sdjwt.issue(args.credentialPayload, args.disclosureFrame as DisclosureFrame<typeof args.credentialPayload>, {
118
- header: {
119
- ...(signingKey?.key.kid !== undefined && { kid: signingKey.key.kid }),
120
- ...(signingKey?.key.x5c !== undefined && { x5c: signingKey.key.x5c }),
121
- },
122
- })
129
+ const header = {
130
+ ...(signingKey?.key.kid !== undefined && { kid: signingKey.key.kid }),
131
+ ...(signingKey?.key.x5c !== undefined && { x5c: signingKey.key.x5c }),
132
+ ...(type && { typ: type }),
133
+ }
134
+ let credential: string
135
+ if (isVcdm2) {
136
+ credential = await (sdjwt as SDJwtVcdm2Instance).issue(
137
+ payload,
138
+ // @ts-ignore
139
+ args.disclosureFrame as DisclosureFrame<typeof payload>,
140
+ { header },
141
+ )
142
+ } else if (isSdJwtVc) {
143
+ credential = await (sdjwt as SDJwtVcInstance).issue(payload, args.disclosureFrame as DisclosureFrame<typeof payload>, { header })
144
+ } else {
145
+ return Promise.reject(new Error(`invalid_argument: credential '${type}' type is not supported`))
146
+ }
123
147
 
124
- return { credential }
148
+ return { type, credential }
125
149
  }
126
150
 
127
151
  /**
@@ -183,10 +207,13 @@ export class SDJwtPlugin implements IAgentPlugin {
183
207
  * @returns A signed SD-JWT presentation.
184
208
  */
185
209
  async createSdJwtPresentation(args: ICreateSdJwtPresentationArgs, context: IRequiredContext): Promise<ICreateSdJwtPresentationResult> {
210
+ const type = args.type ?? 'dc+sd-jwt'
211
+
186
212
  const cred = await SDJwt.fromEncode(args.presentation, this.registeredImplementations.hasher!)
213
+
187
214
  const claims = await cred.getClaims<Claims>(this.registeredImplementations.hasher!)
188
215
  let holder: string
189
- // we primarly look for a cnf field, if it's not there we look for a sub field. If this is also not given, we throw an error since we can not sign it.
216
+ // we primarily look for a cnf field, if it's not there, we look for a sub field. If this is also not given, we throw an error since we can not sign it.
190
217
  if (args.holder) {
191
218
  holder = args.holder
192
219
  } else if (claims.cnf?.jwk) {
@@ -201,15 +228,17 @@ export class SDJwtPlugin implements IAgentPlugin {
201
228
  }
202
229
  const { alg, signer } = await this.getSignerForIdentifier({ identifier: holder }, context)
203
230
 
204
- const sdjwt = new SDJwtVcInstance({
205
- hasher: this.registeredImplementations.hasher ?? defaultGenerateDigest,
231
+ const sdjwt = SDJwtVcdmInstanceFactory.create(type, {
232
+ omitTyp: true,
233
+ hasher: this.registeredImplementations.hasher,
206
234
  saltGenerator: this.registeredImplementations.saltGenerator,
207
235
  kbSigner: signer,
208
236
  kbSignAlg: alg ?? 'ES256',
209
237
  })
238
+
210
239
  const presentation = await sdjwt.present(args.presentation, args.presentationFrame as PresentationFrame<SdJwtVcPayload>, { kb: args.kb })
211
240
 
212
- return { presentation }
241
+ return { type, presentation }
213
242
  }
214
243
 
215
244
  /**
@@ -220,11 +249,19 @@ export class SDJwtPlugin implements IAgentPlugin {
220
249
  */
221
250
  async verifySdJwtVc(args: IVerifySdJwtVcArgs, context: IRequiredContext): Promise<IVerifySdJwtVcResult> {
222
251
  // callback
223
- const verifier: Verifier = async (data: string, signature: string) => this.verify(sdjwt, context, data, signature)
224
- const sdjwt = new SDJwtVcInstance({ verifier, hasher: this.registeredImplementations.hasher ?? defaultGenerateDigest })
225
- const { header = {}, payload, kb } = await sdjwt.verify(args.credential)
252
+ const verifier: Verifier = async (data: string, signature: string) => this.verifyCallbackImpl(sdjwt, context, data, signature)
226
253
 
227
- return { header, payload: payload as SdJwtVcPayload, kb }
254
+ const cred = await SDJwt.fromEncode(args.credential, this.registeredImplementations.hasher!)
255
+ const type = isVcdm2SdJwtPayload(cred.jwt?.payload as SdJwtPayload) ? 'vc+sd-jwt' : 'dc+sd-jwt'
256
+
257
+
258
+ const sdjwt = SDJwtVcdmInstanceFactory.create(type, {verifier, hasher: this.registeredImplementations.hasher ?? defaultGenerateDigest })
259
+ // FIXME: Findynet. Issuer returns expired status lists, and low level lib throws errors on these. We need to fix this in our implementation by wrapping the verification function
260
+ // For now a workaround is to ad 5 days of skew seconds, yuck
261
+ const { header = {}, payload, kb } = await sdjwt.verify(args.credential, {skewSeconds: 60*60*24*5})
262
+
263
+
264
+ return { type, header, payload, kb }
228
265
  }
229
266
 
230
267
  /**
@@ -236,10 +273,14 @@ export class SDJwtPlugin implements IAgentPlugin {
236
273
  * @param payload - The payload of the SD-JWT
237
274
  * @returns
238
275
  */
239
- private verifyKb(sdjwt: SDJwtVcInstance, context: IRequiredContext, data: string, signature: string, payload: JwtPayload): Promise<boolean> {
276
+ private verifyKb(context: IRequiredContext, data: string, signature: string, payload: JwtPayload): Promise<boolean> {
240
277
  if (!payload.cnf) {
241
278
  throw Error('other method than cnf is not supported yet')
242
279
  }
280
+
281
+ // TODO add aud verification
282
+
283
+
243
284
  return this.verifySignatureCallback(context)(data, signature, this.getJwk(payload))
244
285
  }
245
286
 
@@ -251,15 +292,16 @@ export class SDJwtPlugin implements IAgentPlugin {
251
292
  * @param signature - The signature
252
293
  * @returns
253
294
  */
254
- async verify(
255
- sdjwt: SDJwtVcInstance,
295
+ async verifyCallbackImpl(
296
+ sdjwt: SDJwtVcInstance | SDJwtVcdm2Instance,
256
297
  context: IRequiredContext,
257
298
  data: string,
258
299
  signature: string,
259
300
  opts?: { x5cValidation?: X509CertificateChainValidationOpts },
260
301
  ): Promise<boolean> {
261
302
  const decodedVC = await sdjwt.decode(`${data}.${signature}`)
262
- const issuer: string = ((decodedVC.jwt as Jwt).payload as Record<string, unknown>).iss as string
303
+ const payload: SdJwtPayload = (decodedVC.jwt as Jwt).payload as SdJwtPayload
304
+ const issuer: string = getIssuerFromSdJwt(payload)
263
305
  const header = (decodedVC.jwt as Jwt).header as Record<string, any>
264
306
  const x5c: string[] | undefined = header?.x5c as string[]
265
307
  let jwk: JWK | JsonWebKey | undefined = header.jwk
@@ -329,16 +371,21 @@ export class SDJwtPlugin implements IAgentPlugin {
329
371
  */
330
372
  async verifySdJwtPresentation(args: IVerifySdJwtPresentationArgs, context: IRequiredContext): Promise<IVerifySdJwtPresentationResult> {
331
373
  let sdjwt: SDJwtVcInstance
332
- const verifier: Verifier = async (data: string, signature: string) => this.verify(sdjwt, context, data, signature)
374
+ const verifier: Verifier = async (data: string, signature: string) => this.verifyCallbackImpl(sdjwt, context, data, signature)
333
375
  const verifierKb: KbVerifier = async (data: string, signature: string, payload: JwtPayload) =>
334
- this.verifyKb(sdjwt, context, data, signature, payload)
376
+ this.verifyKb(context, data, signature, payload)
335
377
  sdjwt = new SDJwtVcInstance({
336
378
  verifier,
337
379
  hasher: this.registeredImplementations.hasher,
338
380
  kbVerifier: verifierKb,
339
381
  })
340
382
 
341
- return sdjwt.verify(args.presentation, args.requiredClaimKeys, args.kb)
383
+ const verifierOpts: VerifierOptions = {
384
+ requiredClaimKeys: args.requiredClaimKeys,
385
+ keyBindingNonce: args.keyBindingNonce,
386
+ }
387
+
388
+ return sdjwt.verify(args.presentation, verifierOpts)
342
389
  }
343
390
 
344
391
  /**
@@ -411,7 +458,7 @@ export class SDJwtPlugin implements IAgentPlugin {
411
458
  // extract JWK from kid FIXME isn't there a did function for this already? Otherwise create one
412
459
  // FIXME this is a quick-fix to make verification but we need a real solution
413
460
  const encoded = this.extractBase64FromDIDJwk(payload.cnf.kid)
414
- const decoded = decodeBase64url(encoded)
461
+ const decoded = u8a.toString(u8a.fromString(encoded, 'base64url'), 'utf-8')
415
462
  const jwt = JSON.parse(decoded)
416
463
  return jwt as JsonWebKey
417
464
  }
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { SDJwtPlugin } from './action-handler'
2
+ export { defaultGenerateDigest } from './defaultCallbacks'
2
3
  export * from './utils'
3
4
  export * from './types'