@sphereon/ssi-sdk.sd-jwt 0.34.1-next.3 → 0.34.1-next.323

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,23 @@
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
12
  import {
13
+ assertValidTypeMetadata,
14
+ fetchUrlWithErrorHandling,
15
+ getIssuerFromSdJwt,
16
+ isSdjwtVcPayload,
17
+ isVcdm2SdJwtPayload,
18
+ validateIntegrity,
19
+ } from './utils'
20
+ import type {
14
21
  Claims,
15
22
  FetchSdJwtTypeMetadataFromVctUrlArgs,
16
23
  GetSignerForIdentifierArgs,
@@ -30,6 +37,10 @@ import {
30
37
  SignKeyArgs,
31
38
  SignKeyResult,
32
39
  } from './types'
40
+ import { SDJwtVcdm2Instance, SDJwtVcdmInstanceFactory } from './sdJwtVcdm2Instance'
41
+
42
+ // @ts-ignore
43
+ import * as u8a from 'uint8arrays'
33
44
 
34
45
  const debug = Debug('@sphereon/ssi-sdk.sd-jwt')
35
46
 
@@ -101,27 +112,47 @@ export class SDJwtPlugin implements IAgentPlugin {
101
112
  * @returns A signed SD-JWT credential.
102
113
  */
103
114
  async createSdJwtVc(args: ICreateSdJwtVcArgs, context: IRequiredContext): Promise<ICreateSdJwtVcResult> {
104
- const issuer = args.credentialPayload.iss
115
+ const payload = args.credentialPayload
116
+ const isVcdm2 = isVcdm2SdJwtPayload(payload)
117
+ const isSdJwtVc = isSdjwtVcPayload(payload)
118
+ const type = args.type ?? (isVcdm2 ? 'vc+sd-jwt' : 'dc+sd-jwt')
119
+
120
+ const issuer = getIssuerFromSdJwt(args.credentialPayload)
105
121
  if (!issuer) {
106
122
  throw new Error('credential.issuer must not be empty')
107
123
  }
108
124
  const { alg, signer, signingKey } = await this.getSignerForIdentifier({ identifier: issuer, resolution: args.resolution }, context)
109
- const sdjwt = new SDJwtVcInstance({
125
+ const signAlg = alg ?? signingKey?.alg ?? 'ES256'
126
+ const hashAlg: HashAlgorithm = /(\d{3})$/.test(signAlg) ? (`sha-${signAlg.slice(-3)}` as HashAlgorithm) : 'sha-256'
127
+ const sdjwt = SDJwtVcdmInstanceFactory.create(type, {
128
+ omitTyp: true,
110
129
  signer,
111
130
  hasher: this.registeredImplementations.hasher,
112
131
  saltGenerator: this.registeredImplementations.saltGenerator,
113
- signAlg: alg ?? 'ES256',
114
- hashAlg: 'sha-256',
132
+ signAlg,
133
+ hashAlg,
115
134
  })
116
135
 
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
- })
136
+ const header = {
137
+ ...(signingKey?.key.kid !== undefined && { kid: signingKey.key.kid }),
138
+ ...(signingKey?.key.x5c !== undefined && { x5c: signingKey.key.x5c }),
139
+ ...(type && { typ: type }),
140
+ }
141
+ let credential: string
142
+ if (isVcdm2) {
143
+ credential = await (sdjwt as SDJwtVcdm2Instance).issue(
144
+ payload,
145
+ // @ts-ignore
146
+ args.disclosureFrame as DisclosureFrame<typeof payload>,
147
+ { header },
148
+ )
149
+ } else if (isSdJwtVc) {
150
+ credential = await (sdjwt as SDJwtVcInstance).issue(payload, args.disclosureFrame as DisclosureFrame<typeof payload>, { header })
151
+ } else {
152
+ return Promise.reject(new Error(`invalid_argument: credential '${type}' type is not supported`))
153
+ }
123
154
 
124
- return { credential }
155
+ return { type, credential }
125
156
  }
126
157
 
127
158
  /**
@@ -183,10 +214,13 @@ export class SDJwtPlugin implements IAgentPlugin {
183
214
  * @returns A signed SD-JWT presentation.
184
215
  */
185
216
  async createSdJwtPresentation(args: ICreateSdJwtPresentationArgs, context: IRequiredContext): Promise<ICreateSdJwtPresentationResult> {
217
+ const type = args.type ?? 'dc+sd-jwt'
218
+
186
219
  const cred = await SDJwt.fromEncode(args.presentation, this.registeredImplementations.hasher!)
220
+
187
221
  const claims = await cred.getClaims<Claims>(this.registeredImplementations.hasher!)
188
222
  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.
223
+ // 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
224
  if (args.holder) {
191
225
  holder = args.holder
192
226
  } else if (claims.cnf?.jwk) {
@@ -201,15 +235,17 @@ export class SDJwtPlugin implements IAgentPlugin {
201
235
  }
202
236
  const { alg, signer } = await this.getSignerForIdentifier({ identifier: holder }, context)
203
237
 
204
- const sdjwt = new SDJwtVcInstance({
205
- hasher: this.registeredImplementations.hasher ?? defaultGenerateDigest,
238
+ const sdjwt = SDJwtVcdmInstanceFactory.create(type, {
239
+ omitTyp: true,
240
+ hasher: this.registeredImplementations.hasher,
206
241
  saltGenerator: this.registeredImplementations.saltGenerator,
207
242
  kbSigner: signer,
208
243
  kbSignAlg: alg ?? 'ES256',
209
244
  })
245
+
210
246
  const presentation = await sdjwt.present(args.presentation, args.presentationFrame as PresentationFrame<SdJwtVcPayload>, { kb: args.kb })
211
247
 
212
- return { presentation }
248
+ return { type, presentation }
213
249
  }
214
250
 
215
251
  /**
@@ -220,11 +256,17 @@ export class SDJwtPlugin implements IAgentPlugin {
220
256
  */
221
257
  async verifySdJwtVc(args: IVerifySdJwtVcArgs, context: IRequiredContext): Promise<IVerifySdJwtVcResult> {
222
258
  // 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)
259
+ const verifier: Verifier = async (data: string, signature: string) => this.verifyCallbackImpl(sdjwt, context, data, signature)
260
+
261
+ const cred = await SDJwt.fromEncode(args.credential, this.registeredImplementations.hasher!)
262
+ const type = isVcdm2SdJwtPayload(cred.jwt?.payload as SdJwtPayload) ? 'vc+sd-jwt' : 'dc+sd-jwt'
263
+
264
+ const sdjwt = SDJwtVcdmInstanceFactory.create(type, { verifier, hasher: this.registeredImplementations.hasher ?? defaultGenerateDigest })
265
+ // 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
266
+ // For now a workaround is to ad 5 days of skew seconds, yuck
267
+ const { header = {}, payload, kb } = await sdjwt.verify(args.credential, { skewSeconds: 60 * 60 * 24 * 5 })
226
268
 
227
- return { header, payload: payload as SdJwtVcPayload, kb }
269
+ return { type, header, payload, kb }
228
270
  }
229
271
 
230
272
  /**
@@ -236,10 +278,13 @@ export class SDJwtPlugin implements IAgentPlugin {
236
278
  * @param payload - The payload of the SD-JWT
237
279
  * @returns
238
280
  */
239
- private verifyKb(sdjwt: SDJwtVcInstance, context: IRequiredContext, data: string, signature: string, payload: JwtPayload): Promise<boolean> {
281
+ private verifyKb(context: IRequiredContext, data: string, signature: string, payload: JwtPayload): Promise<boolean> {
240
282
  if (!payload.cnf) {
241
283
  throw Error('other method than cnf is not supported yet')
242
284
  }
285
+
286
+ // TODO add aud verification
287
+
243
288
  return this.verifySignatureCallback(context)(data, signature, this.getJwk(payload))
244
289
  }
245
290
 
@@ -251,15 +296,16 @@ export class SDJwtPlugin implements IAgentPlugin {
251
296
  * @param signature - The signature
252
297
  * @returns
253
298
  */
254
- async verify(
255
- sdjwt: SDJwtVcInstance,
299
+ async verifyCallbackImpl(
300
+ sdjwt: SDJwtVcInstance | SDJwtVcdm2Instance,
256
301
  context: IRequiredContext,
257
302
  data: string,
258
303
  signature: string,
259
304
  opts?: { x5cValidation?: X509CertificateChainValidationOpts },
260
305
  ): Promise<boolean> {
261
306
  const decodedVC = await sdjwt.decode(`${data}.${signature}`)
262
- const issuer: string = ((decodedVC.jwt as Jwt).payload as Record<string, unknown>).iss as string
307
+ const payload: SdJwtPayload = (decodedVC.jwt as Jwt).payload as SdJwtPayload
308
+ const issuer: string = getIssuerFromSdJwt(payload)
263
309
  const header = (decodedVC.jwt as Jwt).header as Record<string, any>
264
310
  const x5c: string[] | undefined = header?.x5c as string[]
265
311
  let jwk: JWK | JsonWebKey | undefined = header.jwk
@@ -329,16 +375,20 @@ export class SDJwtPlugin implements IAgentPlugin {
329
375
  */
330
376
  async verifySdJwtPresentation(args: IVerifySdJwtPresentationArgs, context: IRequiredContext): Promise<IVerifySdJwtPresentationResult> {
331
377
  let sdjwt: SDJwtVcInstance
332
- const verifier: Verifier = async (data: string, signature: string) => this.verify(sdjwt, context, data, signature)
333
- const verifierKb: KbVerifier = async (data: string, signature: string, payload: JwtPayload) =>
334
- this.verifyKb(sdjwt, context, data, signature, payload)
378
+ const verifier: Verifier = async (data: string, signature: string) => this.verifyCallbackImpl(sdjwt, context, data, signature)
379
+ const verifierKb: KbVerifier = async (data: string, signature: string, payload: JwtPayload) => this.verifyKb(context, data, signature, payload)
335
380
  sdjwt = new SDJwtVcInstance({
336
381
  verifier,
337
382
  hasher: this.registeredImplementations.hasher,
338
383
  kbVerifier: verifierKb,
339
384
  })
340
385
 
341
- return sdjwt.verify(args.presentation, args.requiredClaimKeys, args.kb)
386
+ const verifierOpts: VerifierOptions = {
387
+ requiredClaimKeys: args.requiredClaimKeys,
388
+ keyBindingNonce: args.keyBindingNonce,
389
+ }
390
+
391
+ return sdjwt.verify(args.presentation, verifierOpts)
342
392
  }
343
393
 
344
394
  /**
@@ -411,7 +461,7 @@ export class SDJwtPlugin implements IAgentPlugin {
411
461
  // extract JWK from kid FIXME isn't there a did function for this already? Otherwise create one
412
462
  // FIXME this is a quick-fix to make verification but we need a real solution
413
463
  const encoded = this.extractBase64FromDIDJwk(payload.cnf.kid)
414
- const decoded = decodeBase64url(encoded)
464
+ const decoded = u8a.toString(u8a.fromString(encoded, 'base64url'), 'utf-8')
415
465
  const jwt = JSON.parse(decoded)
416
466
  return jwt as JsonWebKey
417
467
  }
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'