@sphereon/ssi-sdk.credential-vcdm 0.33.1-feature.jose.vcdm.55

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,250 @@
1
+ import { beforeAll, describe, expect, it, test, vitest } from 'vitest'
2
+ import {
3
+ CredentialPayload,
4
+ ICredentialPlugin,
5
+ IDIDManager,
6
+ IIdentifier,
7
+ IKeyManager,
8
+ IResolver,
9
+ TAgent,
10
+ VerifiableCredential,
11
+ } from '@veramo/core'
12
+ import { createAgent } from '@sphereon/ssi-sdk.agent-config'
13
+ import { CredentialIssuer } from '..'
14
+ import { DIDManager, MemoryDIDStore } from '@veramo/did-manager'
15
+ import { SphereonKeyManager, MemoryKeyStore, MemoryPrivateKeyStore } from '@sphereon/ssi-sdk-ext.key-manager'
16
+ import { SphereonKeyManagementSystem } from '@sphereon/ssi-sdk-ext.kms-local'
17
+ import { getDidKeyResolver, SphereonKeyDidProvider } from '@sphereon/ssi-sdk-ext.did-provider-key'
18
+ import { DIDResolverPlugin } from '@veramo/did-resolver'
19
+ import { EthrDIDProvider } from '@veramo/did-provider-ethr'
20
+ import {
21
+ ContextDoc,
22
+ CredentialProviderLD,
23
+ LdDefaultContexts,
24
+ VeramoEcdsaSecp256k1RecoverySignature2020,
25
+ VeramoEd25519Signature2018,
26
+ } from '../../../credential-jsonld/src'
27
+ import { Resolver } from 'did-resolver'
28
+ import { getResolver as ethrDidResolver } from 'ethr-did-resolver'
29
+
30
+ import { CredentialProviderJWT } from '../../../credential-jwt/src'
31
+
32
+ const customContext: Record<string, ContextDoc> = {
33
+ 'custom:example.context': {
34
+ '@context': {
35
+ nothing: 'custom:example.context#blank',
36
+ },
37
+ },
38
+ }
39
+
40
+ const infuraProjectId = '3586660d179141e3801c3895de1c2eba'
41
+
42
+ describe('credential-w3c full flow', () => {
43
+ let didKeyIdentifier: IIdentifier
44
+ let didEthrIdentifier: IIdentifier
45
+ let agent: TAgent<IResolver & IKeyManager & IDIDManager & ICredentialPlugin>
46
+ let credential: CredentialPayload
47
+
48
+ beforeAll(async () => {
49
+ const jwt = new CredentialProviderJWT()
50
+ const ld = new CredentialProviderLD({
51
+ contextMaps: [LdDefaultContexts, customContext],
52
+ suites: [new VeramoEd25519Signature2018(), new VeramoEcdsaSecp256k1RecoverySignature2020()],
53
+ })
54
+ agent = createAgent<IResolver & IKeyManager & IDIDManager & ICredentialPlugin>({
55
+ plugins: [
56
+ new SphereonKeyManager({
57
+ store: new MemoryKeyStore(),
58
+ kms: {
59
+ local: new SphereonKeyManagementSystem(new MemoryPrivateKeyStore()),
60
+ },
61
+ }),
62
+ new DIDManager({
63
+ providers: {
64
+ 'did:key': new SphereonKeyDidProvider({ defaultKms: 'local' }),
65
+ 'did:ethr': new EthrDIDProvider({
66
+ defaultKms: 'local',
67
+ network: 'sepolia',
68
+ }),
69
+ },
70
+ store: new MemoryDIDStore(),
71
+ defaultProvider: 'did:key',
72
+ }),
73
+ new DIDResolverPlugin({
74
+ resolver: new Resolver({
75
+ ...getDidKeyResolver(),
76
+ ...ethrDidResolver({ infuraProjectId }),
77
+ }),
78
+ }),
79
+ new CredentialIssuer({ issuers: [jwt, ld] }),
80
+ ],
81
+ })
82
+ didKeyIdentifier = await agent.didManagerCreate()
83
+ didEthrIdentifier = await agent.didManagerCreate({ provider: 'did:ethr' })
84
+ credential = {
85
+ issuer: didKeyIdentifier.did,
86
+ '@context': ['custom:example.context'],
87
+ credentialSubject: {
88
+ nothing: 'else matters',
89
+ },
90
+ }
91
+ })
92
+
93
+ it(`verifies a credential created with jwt proofType`, async () => {
94
+ const verifiableCredential1 = await agent.createVerifiableCredential({
95
+ credential,
96
+ proofFormat: 'jwt',
97
+ })
98
+ const verifyResult = await agent.verifyCredential({ credential: verifiableCredential1 })
99
+ expect(verifyResult.verified).toBeTruthy()
100
+ })
101
+
102
+ it(`verifies a credential created with lds proofType`, async () => {
103
+ const verifiableCredential1 = await agent.createVerifiableCredential({
104
+ credential,
105
+ proofFormat: 'lds',
106
+ })
107
+ const verifyResult = await agent.verifyCredential({ credential: verifiableCredential1 })
108
+ expect(verifyResult.verified).toBeTruthy()
109
+ })
110
+
111
+ it(`fails to verify a credential created with lds proofType with modified values`, async () => {
112
+ const verifiableCredential1 = await agent.createVerifiableCredential({
113
+ credential,
114
+ proofFormat: 'lds',
115
+ })
116
+ const modifiedCredential: VerifiableCredential = { ...verifiableCredential1, issuer: { id: 'did:fake:wrong' } }
117
+ const verifyResult = await agent.verifyCredential({ credential: modifiedCredential })
118
+ expect(verifyResult.verified).toBeFalsy()
119
+ })
120
+
121
+
122
+ it('fails the verification of a jwt credential with false value outside of proof', async () => {
123
+ const verifiableCredential1 = await agent.createVerifiableCredential({
124
+ credential,
125
+ proofFormat: 'jwt',
126
+ })
127
+
128
+ const modifiedCredential: VerifiableCredential = { ...verifiableCredential1, issuer: { id: 'did:fake:wrong' } }
129
+ const verifyResult = await agent.verifyCredential({ credential: modifiedCredential })
130
+
131
+ expect(verifyResult.verified).toBeFalsy()
132
+ })
133
+
134
+ // example credential found at: https://learn.mattr.global/tutorials/web-credentials/issue/issue-basic
135
+ it(`verifies a credential created with lds proofType via Mattr`, async () => {
136
+ const verifiableCredential1 = {
137
+ '@context': [
138
+ 'https://www.w3.org/2018/credentials/v1',
139
+ {
140
+ '@vocab': 'https://w3id.org/security/undefinedTerm#',
141
+ },
142
+ 'https://schema.org',
143
+ ],
144
+ type: ['VerifiableCredential', 'CourseCredential'],
145
+ issuer: {
146
+ id: 'did:key:z6MkndAHigYrXNpape7jgaC7jHiWwxzB3chuKUGXJg2b5RSj',
147
+ name: 'tenant',
148
+ },
149
+ issuanceDate: '2021-07-26T01:05:05.152Z',
150
+ credentialSubject: {
151
+ id: 'did:key:z6MkfxQU7dy8eKxyHpG267FV23agZQu9zmokd8BprepfHALi',
152
+ givenName: 'Chris',
153
+ familyName: 'Shin',
154
+ educationalCredentialAwarded: 'Certificate Name',
155
+ },
156
+ proof: {
157
+ type: 'Ed25519Signature2018',
158
+ created: '2021-07-26T01:05:06Z',
159
+ jws: 'eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..o6hnrrWpArG8LQz2Ex_u66_BtuPdp3Hkz18nhNdNhJ7J1k_2lmCCwsNdmo-kNFirZdSIMzqO-V3wEjMDphVEAA',
160
+ proofPurpose: 'assertionMethod',
161
+ verificationMethod:
162
+ 'did:key:z6MkndAHigYrXNpape7jgaC7jHiWwxzB3chuKUGXJg2b5RSj#z6MkndAHigYrXNpape7jgaC7jHiWwxzB3chuKUGXJg2b5RSj',
163
+ },
164
+ }
165
+ const verifyResult = await agent.verifyCredential({ credential: verifiableCredential1 })
166
+ expect(verifyResult.verified).toBeTruthy()
167
+ })
168
+
169
+ it('verify a verifiablePresentation', async () => {
170
+ const verifiableCredential1 = await agent.createVerifiableCredential({
171
+ credential,
172
+ proofFormat: 'jwt',
173
+ })
174
+
175
+ const verifiablePresentation = await agent.createVerifiablePresentation({
176
+ presentation: {
177
+ verifiableCredential: [verifiableCredential1],
178
+ holder: didKeyIdentifier.did,
179
+ },
180
+ challenge: 'VERAMO',
181
+ proofFormat: 'jwt',
182
+ })
183
+
184
+ expect(verifiablePresentation).toBeDefined()
185
+
186
+ const response = await agent.verifyPresentation({
187
+ presentation: verifiablePresentation,
188
+ challenge: 'VERAMO',
189
+ })
190
+
191
+ expect(response.verified).toBe(true)
192
+ })
193
+
194
+
195
+ it('fails the verification of an expired credential', async () => {
196
+ const presentationJWT =
197
+ 'eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjAyOTcyMTAsInZwIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIl0sInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiJdLCJ2ZXJpZmlhYmxlQ3JlZGVudGlhbCI6WyJleUpoYkdjaU9pSkZaRVJUUVNJc0luUjVjQ0k2SWtwWFZDSjkuZXlKbGVIQWlPakUyTmpBeU9UY3lNVEFzSW5aaklqcDdJa0JqYjI1MFpYaDBJanBiSW1oMGRIQnpPaTh2ZDNkM0xuY3pMbTl5Wnk4eU1ERTRMMk55WldSbGJuUnBZV3h6TDNZeElpd2lZM1Z6ZEc5dE9tVjRZVzF3YkdVdVkyOXVkR1Y0ZENKZExDSjBlWEJsSWpwYklsWmxjbWxtYVdGaWJHVkRjbVZrWlc1MGFXRnNJbDBzSW1OeVpXUmxiblJwWVd4VGRXSnFaV04wSWpwN0ltNXZkR2hwYm1jaU9pSmxiSE5sSUcxaGRIUmxjbk1pZlgwc0ltNWlaaUk2TVRZMk1ESTVOekl4TUN3aWFYTnpJam9pWkdsa09tdGxlVHA2TmsxcmFWVTNVbk5hVnpOeWFXVmxRMjg1U25OMVVEUnpRWEZYZFdGRE0zbGhjbWwxWVZCMlVXcHRZVzVsWTFBaWZRLkZhdzBEUWNNdXpacEVkcy1LR3dOalMyM2IzbUEzZFhQWXBQcGJzNmRVSnhIOVBrZzVieGF3UDVwMlNPajdQM25IdEpCR3lwTjJ3NzRfZjc3SjF5dUJ3Il19LCJuYmYiOjE2NjAyOTcyMTAsImlzcyI6ImRpZDprZXk6ejZNa2lVN1JzWlczcmllZUNvOUpzdVA0c0FxV3VhQzN5YXJpdWFQdlFqbWFuZWNQIn0.YcYbyqVlD8YsTjVw0kCEs0P_ie6SFMakf_ncPntEjsmS9C4cKyiS50ZhNkOv0R3Roy1NrzX7h93WBU55KeJlCw'
198
+
199
+ const response = await agent.verifyPresentation({
200
+ presentation: presentationJWT,
201
+ })
202
+
203
+ expect(response.verified).toBe(false)
204
+ expect(response.error).toBeDefined()
205
+ expect(response.error?.message).toContain('JWT has expired')
206
+ })
207
+
208
+ it('fails the verification with nbf in the future', async () => {
209
+ const presentationJWT =
210
+ 'eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2cCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVQcmVzZW50YXRpb24iXSwidmVyaWZpYWJsZUNyZWRlbnRpYWwiOlsiZXlKaGJHY2lPaUpGWkVSVFFTSXNJblI1Y0NJNklrcFhWQ0o5LmV5SjJZeUk2ZXlKQVkyOXVkR1Y0ZENJNld5Sm9kSFJ3Y3pvdkwzZDNkeTUzTXk1dmNtY3ZNakF4T0M5amNtVmtaVzUwYVdGc2N5OTJNU0lzSW1OMWMzUnZiVHBsZUdGdGNHeGxMbU52Ym5SbGVIUWlYU3dpZEhsd1pTSTZXeUpXWlhKcFptbGhZbXhsUTNKbFpHVnVkR2xoYkNKZExDSmpjbVZrWlc1MGFXRnNVM1ZpYW1WamRDSTZleUp1YjNSb2FXNW5Jam9pWld4elpTQnRZWFIwWlhKekluMTlMQ0p1WW1ZaU9qRXhOall3TWprNE5UZzRMQ0pwYzNNaU9pSmthV1E2YTJWNU9ubzJUV3QyYlhCeFRXbDFOM2h1U25kVE9YQkVSR0ZSYW1oQ1dUWndlbU00V1RKQ2FWRnhSWFUwZW1GRldFMVdUQ0o5LnA4Y2FTS1pTcGdISm1TRzhMekpnSWlWMzFRU3NjOEJ2anZuQ1JrOEM3X1UxLXV5cS11MHlQcDdjRWlSOUtXTnprN2RDQlBiR2pBRGRiNC0tV3V5LUNRIl19LCJuYmYiOjI2NjAyOTg1ODgsImlzcyI6ImRpZDprZXk6ejZNa3ZtcHFNaXU3eG5Kd1M5cEREYVFqaEJZNnB6YzhZMkJpUXFFdTR6YUVYTVZMIiwibm9uY2UiOiJWRVJBTU8ifQ.F-uiI2iVMcdm1VFzkXgtZqq8QGw5XnyEI36vGblBluHnklnNYNmE5eluQ23dbcduGWSe3ZJJ65C7HrPTUoXvDA'
211
+
212
+ const response = await agent.verifyPresentation({
213
+ presentation: presentationJWT,
214
+ })
215
+
216
+ expect(response.verified).toBe(false)
217
+ expect(response.error).toBeDefined()
218
+ expect(response.error?.message).toContain('JWT not valid before nbf')
219
+ })
220
+
221
+ /**
222
+ * These tests can be uncommented out when the did-jwt starts to support the policies merge request
223
+ */
224
+
225
+ // it('passes the verification of an expired credential with policy exp false',async () => {
226
+ // const presentationJWT = 'eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2cCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVQcmVzZW50YXRpb24iXSwidmVyaWZpYWJsZUNyZWRlbnRpYWwiOlsiZXlKaGJHY2lPaUpGWkVSVFFTSXNJblI1Y0NJNklrcFhWQ0o5LmV5SjJZeUk2ZXlKQVkyOXVkR1Y0ZENJNld5Sm9kSFJ3Y3pvdkwzZDNkeTUzTXk1dmNtY3ZNakF4T0M5amNtVmtaVzUwYVdGc2N5OTJNU0lzSW1OMWMzUnZiVHBsZUdGdGNHeGxMbU52Ym5SbGVIUWlYU3dpZEhsd1pTSTZXeUpXWlhKcFptbGhZbXhsUTNKbFpHVnVkR2xoYkNKZExDSmpjbVZrWlc1MGFXRnNVM1ZpYW1WamRDSTZleUp1YjNSb2FXNW5Jam9pWld4elpTQnRZWFIwWlhKekluMTlMQ0p1WW1ZaU9qRXhOall3TWprNE5UZzRMQ0pwYzNNaU9pSmthV1E2YTJWNU9ubzJUV3QyYlhCeFRXbDFOM2h1U25kVE9YQkVSR0ZSYW1oQ1dUWndlbU00V1RKQ2FWRnhSWFUwZW1GRldFMVdUQ0o5LnA4Y2FTS1pTcGdISm1TRzhMekpnSWlWMzFRU3NjOEJ2anZuQ1JrOEM3X1UxLXV5cS11MHlQcDdjRWlSOUtXTnprN2RDQlBiR2pBRGRiNC0tV3V5LUNRIl19LCJuYmYiOjI2NjAyOTg1ODgsImlzcyI6ImRpZDprZXk6ejZNa3ZtcHFNaXU3eG5Kd1M5cEREYVFqaEJZNnB6YzhZMkJpUXFFdTR6YUVYTVZMIiwibm9uY2UiOiJWRVJBTU8ifQ.F-uiI2iVMcdm1VFzkXgtZqq8QGw5XnyEI36vGblBluHnklnNYNmE5eluQ23dbcduGWSe3ZJJ65C7HrPTUoXvDA'
227
+ //
228
+ // const response = await agent.verifyPresentation({
229
+ // presentation: presentationJWT,
230
+ // policies: {
231
+ // exp: false
232
+ // }
233
+ // })
234
+ //
235
+ // expect(response.verified).toBe(true)
236
+ // })
237
+ //
238
+ // it('passes the verification with nbf in the future with policy nbf false',async () => {
239
+ // const presentationJWT = 'eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2cCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVQcmVzZW50YXRpb24iXSwidmVyaWZpYWJsZUNyZWRlbnRpYWwiOlsiZXlKaGJHY2lPaUpGWkVSVFFTSXNJblI1Y0NJNklrcFhWQ0o5LmV5SjJZeUk2ZXlKQVkyOXVkR1Y0ZENJNld5Sm9kSFJ3Y3pvdkwzZDNkeTUzTXk1dmNtY3ZNakF4T0M5amNtVmtaVzUwYVdGc2N5OTJNU0lzSW1OMWMzUnZiVHBsZUdGdGNHeGxMbU52Ym5SbGVIUWlYU3dpZEhsd1pTSTZXeUpXWlhKcFptbGhZbXhsUTNKbFpHVnVkR2xoYkNKZExDSmpjbVZrWlc1MGFXRnNVM1ZpYW1WamRDSTZleUp1YjNSb2FXNW5Jam9pWld4elpTQnRZWFIwWlhKekluMTlMQ0p1WW1ZaU9qRXhOall3TWprNE5UZzRMQ0pwYzNNaU9pSmthV1E2YTJWNU9ubzJUV3QyYlhCeFRXbDFOM2h1U25kVE9YQkVSR0ZSYW1oQ1dUWndlbU00V1RKQ2FWRnhSWFUwZW1GRldFMVdUQ0o5LnA4Y2FTS1pTcGdISm1TRzhMekpnSWlWMzFRU3NjOEJ2anZuQ1JrOEM3X1UxLXV5cS11MHlQcDdjRWlSOUtXTnprN2RDQlBiR2pBRGRiNC0tV3V5LUNRIl19LCJuYmYiOjI2NjAyOTg1ODgsImlzcyI6ImRpZDprZXk6ejZNa3ZtcHFNaXU3eG5Kd1M5cEREYVFqaEJZNnB6YzhZMkJpUXFFdTR6YUVYTVZMIiwibm9uY2UiOiJWRVJBTU8ifQ.F-uiI2iVMcdm1VFzkXgtZqq8QGw5XnyEI36vGblBluHnklnNYNmE5eluQ23dbcduGWSe3ZJJ65C7HrPTUoXvDA'
240
+ //
241
+ // const response = await agent.verifyPresentation({
242
+ // presentation: presentationJWT,
243
+ // policies: {
244
+ // nbf: false
245
+ // }
246
+ // })
247
+ //
248
+ // expect(response.verified).toBe(true)
249
+ // })
250
+ })
@@ -0,0 +1,281 @@
1
+ import { DIDResolutionResult, IAgentContext, ICredentialVerifier, IResolver } from '@veramo/core'
2
+ import { Message } from '@veramo/message-handler'
3
+ import { IContext, MessageTypes, W3cMessageHandler } from '../message-handler'
4
+ import { computeEntryHash } from '@veramo/utils'
5
+ import { describe, expect, it, vitest } from 'vitest'
6
+
7
+ describe('@sphereon/credential-vcdm', () => {
8
+ const handler = new W3cMessageHandler()
9
+ // don't need to replace rinkeby since test has mock resolver
10
+ const didEthr = 'did:ethr:rinkeby:0x3c357ba458933a19c1df1c7f6b473b3302bbbe61'
11
+ const didKey = 'did:key:z6Mkqjn1SMUbR88S7BZFAZnr7sfzPXmm3DfRdMy3Z5CdMqnd'
12
+
13
+ const context: IContext = {
14
+ agent: {
15
+ getSchema: vitest.fn(),
16
+ execute: vitest.fn(),
17
+ availableMethods: vitest.fn(),
18
+ emit: vitest.fn(),
19
+ resolveDid: async (args?): Promise<DIDResolutionResult> => {
20
+ if (!args?.didUrl) throw Error('DID required')
21
+
22
+ if (args?.didUrl === didEthr) {
23
+ return {
24
+ didResolutionMetadata: {},
25
+ didDocumentMetadata: {},
26
+ didDocument: {
27
+ '@context': 'https://www.w3.org/ns/did/v1',
28
+ id: args?.didUrl,
29
+ verificationMethod: [
30
+ {
31
+ id: `${didEthr}#owner`,
32
+ type: 'EcdsaSecp256k1RecoveryMethod2020',
33
+ controller: args?.didUrl,
34
+ blockchainAccountId: `eip155:1:${didEthr.slice(-42)}`,
35
+ },
36
+ ],
37
+ authentication: [`${didEthr}#owner`],
38
+ },
39
+ }
40
+ } else {
41
+ return {
42
+ didResolutionMetadata: {},
43
+ didDocumentMetadata: {},
44
+ didDocument: {
45
+ '@context': 'https://www.w3.org/ns/did/v1',
46
+ id: didKey,
47
+ verificationMethod: [
48
+ {
49
+ id: '#z6Mkqjn1SMUbR88S7BZFAZnr7sfzPXmm3DfRdMy3Z5CdMqnd',
50
+ type: 'Ed25519VerificationKey2018',
51
+ controller: didKey,
52
+ publicKeyBase58: 'CHWxr7EA5adxzgiYUzq1Gn7zZxVudLR4wM47ioEcSd1F',
53
+ },
54
+ {
55
+ id: '#z6LSkpCZ3cLP76M3Q26rhZe6q98vMdcSPTt4iML4r9UT7LVt',
56
+ type: 'X25519KeyAgreementKey2019',
57
+ controller: didKey,
58
+ publicKeyBase58: 'A92PXJXX1ddJJdj6Av89WYvSWV5KgrhuqNcPMgpvPxj8',
59
+ },
60
+ ],
61
+ authentication: ['#z6Mkqjn1SMUbR88S7BZFAZnr7sfzPXmm3DfRdMy3Z5CdMqnd'],
62
+ assertionMethod: ['#z6Mkqjn1SMUbR88S7BZFAZnr7sfzPXmm3DfRdMy3Z5CdMqnd'],
63
+ },
64
+ }
65
+ }
66
+ },
67
+ canVerifyDocumentType: vitest.fn(),
68
+ verifyCredential: vitest.fn(),
69
+ verifyPresentation: vitest.fn(),
70
+ getDIDComponentById: vitest.fn(),
71
+ },
72
+ } as IAgentContext<IResolver & ICredentialVerifier>
73
+
74
+ it('should reject unknown message type', async () => {
75
+ expect.assertions(1)
76
+ const message = new Message({ raw: 'test', metaData: [{ type: 'test' }] })
77
+ await expect(handler.handle(message, context)).rejects.toThrow('Unsupported message type')
78
+ })
79
+
80
+ const vcJwtSecp256k1 =
81
+ 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NkstUiJ9.eyJpYXQiOjE1ODI2MTk2NzYsInN1YiI6ImRpZDpldGhyOnJpbmtlYnk6MHgzYzM1N2JhNDU4OTMzYTE5YzFkZjFjN2Y2YjQ3M2IzMzAyYmJiZTYxIiwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJuYW1lIjoiQWxpY2UifX0sImlzcyI6ImRpZDpldGhyOnJpbmtlYnk6MHgzYzM1N2JhNDU4OTMzYTE5YzFkZjFjN2Y2YjQ3M2IzMzAyYmJiZTYxIn0.IGF1LFOc4_PcGVeq7Yw7OGz4Gj7xXZK6p8bP9CSEIXz7mNFPM0v0nuevTZ47a0I8XgLfCFNkUrIIscjH8MFx_wE'
82
+
83
+ const vcPayloadSecp256k1 = {
84
+ iat: 1582619676,
85
+ sub: didEthr,
86
+ vc: {
87
+ '@context': ['https://www.w3.org/2018/credentials/v1'],
88
+ type: ['VerifiableCredential'],
89
+ credentialSubject: {
90
+ name: 'Alice',
91
+ },
92
+ },
93
+ iss: didEthr,
94
+ }
95
+
96
+ const vpJwtSecp256k1 =
97
+ 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NkstUiJ9.eyJpYXQiOjE1ODI2MTk4NzUsImF1ZCI6ImRpZDpldGhyOnJpbmtlYnk6MHgzYzM1N2JhNDU4OTMzYTE5YzFkZjFjN2Y2YjQ3M2IzMzAyYmJiZTYxIiwidGFnIjoieHl6LTEyMyIsInZwIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIl0sInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiJdLCJ2ZXJpZmlhYmxlQ3JlZGVudGlhbCI6WyJleUowZVhBaU9pSktWMVFpTENKaGJHY2lPaUpGVXpJMU5rc3RVaUo5LmV5SnBZWFFpT2pFMU9ESTJNVGsyTnpZc0luTjFZaUk2SW1ScFpEcGxkR2h5T25KcGJtdGxZbms2TUhnell6TTFOMkpoTkRVNE9UTXpZVEU1WXpGa1pqRmpOMlkyWWpRM00ySXpNekF5WW1KaVpUWXhJaXdpZG1NaU9uc2lRR052Ym5SbGVIUWlPbHNpYUhSMGNITTZMeTkzZDNjdWR6TXViM0puTHpJd01UZ3ZZM0psWkdWdWRHbGhiSE12ZGpFaVhTd2lkSGx3WlNJNld5SldaWEpwWm1saFlteGxRM0psWkdWdWRHbGhiQ0pkTENKamNtVmtaVzUwYVdGc1UzVmlhbVZqZENJNmV5SnVZVzFsSWpvaVFXeHBZMlVpZlgwc0ltbHpjeUk2SW1ScFpEcGxkR2h5T25KcGJtdGxZbms2TUhnell6TTFOMkpoTkRVNE9UTXpZVEU1WXpGa1pqRmpOMlkyWWpRM00ySXpNekF5WW1KaVpUWXhJbjAuSUdGMUxGT2M0X1BjR1ZlcTdZdzdPR3o0R2o3eFhaSzZwOGJQOUNTRUlYejdtTkZQTTB2MG51ZXZUWjQ3YTBJOFhnTGZDRk5rVXJJSXNjakg4TUZ4X3dFIl19LCJpc3MiOiJkaWQ6ZXRocjpyaW5rZWJ5OjB4M2MzNTdiYTQ1ODkzM2ExOWMxZGYxYzdmNmI0NzNiMzMwMmJiYmU2MSJ9.7gIGq437moBKMwF3PUrycjCP4Op6dL6IJV6GygSq1KGV7QU0II16YzETsr412AlHl_kaYgUJjRav7unJdyJL0wA'
98
+
99
+ const vpPayloadSecp256k1 = {
100
+ iat: 1582619875,
101
+ aud: didEthr,
102
+ tag: 'xyz-123',
103
+ vp: {
104
+ '@context': ['https://www.w3.org/2018/credentials/v1'],
105
+ type: ['VerifiablePresentation'],
106
+ verifiableCredential: [
107
+ 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NkstUiJ9.eyJpYXQiOjE1ODI2MTk2NzYsInN1YiI6ImRpZDpldGhyOnJpbmtlYnk6MHgzYzM1N2JhNDU4OTMzYTE5YzFkZjFjN2Y2YjQ3M2IzMzAyYmJiZTYxIiwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJuYW1lIjoiQWxpY2UifX0sImlzcyI6ImRpZDpldGhyOnJpbmtlYnk6MHgzYzM1N2JhNDU4OTMzYTE5YzFkZjFjN2Y2YjQ3M2IzMzAyYmJiZTYxIn0.IGF1LFOc4_PcGVeq7Yw7OGz4Gj7xXZK6p8bP9CSEIXz7mNFPM0v0nuevTZ47a0I8XgLfCFNkUrIIscjH8MFx_wE',
108
+ ],
109
+ },
110
+ iss: didEthr,
111
+ }
112
+
113
+ it('should return handled VC message (ES256K-R)', async () => {
114
+ expect.assertions(6)
115
+ const message = new Message({ raw: vcJwtSecp256k1, metaData: [{ type: 'test' }] })
116
+ // This would be done by '@veramo/did-jwt':
117
+ message.data = vcPayloadSecp256k1
118
+ message.addMetaData({ type: 'JWT', value: 'ES256K-R' })
119
+ const handled = await handler.handle(message, context)
120
+ expect(handled.isValid()).toEqual(true)
121
+ expect(handled.id).toEqual(computeEntryHash(vcJwtSecp256k1))
122
+ expect(handled.raw).toEqual(vcJwtSecp256k1)
123
+ expect(handled.type).toEqual(MessageTypes.vc)
124
+ expect(handled.from).toEqual(vcPayloadSecp256k1.iss)
125
+ expect(handled.to).toEqual(vcPayloadSecp256k1.sub)
126
+ // expect(handled.timestamp).toEqual(vcPayload.iat)
127
+ })
128
+
129
+ it('should return handled VP message (ES256K-R)', async () => {
130
+ expect.assertions(7)
131
+ const message = new Message({ raw: vpJwtSecp256k1, metaData: [{ type: 'test' }] })
132
+ // This would be done by '@veramo/did-jwt':
133
+ message.data = vpPayloadSecp256k1
134
+ message.addMetaData({ type: 'JWT', value: 'ES256K-R' })
135
+
136
+ const handled = await handler.handle(message, context)
137
+ expect(handled.isValid()).toEqual(true)
138
+ expect(handled.id).toEqual(computeEntryHash(vpJwtSecp256k1))
139
+ expect(handled.raw).toEqual(vpJwtSecp256k1)
140
+ expect(handled.type).toEqual(MessageTypes.vp)
141
+ expect(handled.from).toEqual(vpPayloadSecp256k1.iss)
142
+ expect(handled.to).toEqual(vpPayloadSecp256k1.aud)
143
+ expect(handled.threadId).toEqual(vpPayloadSecp256k1.tag)
144
+ // expect(handled.timestamp).toEqual(vpPayload.iat)
145
+ })
146
+
147
+ const vcJwtEd25519 =
148
+ 'eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJjcmVkZW50aWFsU3ViamVjdCI6eyJuYW1lIjoiQWxpY2UifSwiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIlByb2ZpbGUiXX0sInN1YiI6ImRpZDprZXk6ejZNa3FqbjFTTVViUjg4UzdCWkZBWm5yN3NmelBYbW0zRGZSZE15M1o1Q2RNcW5kIiwibmJmIjoxNjIxOTczOTU0LCJpc3MiOiJkaWQ6a2V5Ono2TWtxam4xU01VYlI4OFM3QlpGQVpucjdzZnpQWG1tM0RmUmRNeTNaNUNkTXFuZCJ9.xFUvm49vS4dNoSURJwrCMwdePgrAyBRzs7GqvcUyD6KjfNM8eSgFeF8CEUHC21WcwrmbTNrzpQtgFQTFP_9HAA'
149
+
150
+ const vcPayloadEd25519 = {
151
+ vc: {
152
+ credentialSubject: {
153
+ name: 'Alice',
154
+ },
155
+ '@context': ['https://www.w3.org/2018/credentials/v1'],
156
+ type: ['VerifiableCredential', 'Profile'],
157
+ },
158
+ sub: didKey,
159
+ nbf: 1621973954,
160
+ iss: didKey,
161
+ }
162
+
163
+ const vpJwtEd25519 =
164
+ 'eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2cCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVQcmVzZW50YXRpb24iLCJQcm9maWxlIl0sInZlcmlmaWFibGVDcmVkZW50aWFsIjpbImV5SmhiR2NpT2lKRlpFUlRRU0lzSW5SNWNDSTZJa3BYVkNKOS5leUoyWXlJNmV5SmpjbVZrWlc1MGFXRnNVM1ZpYW1WamRDSTZleUp1WVcxbElqb2lRV3hwWTJVaWZTd2lRR052Ym5SbGVIUWlPbHNpYUhSMGNITTZMeTkzZDNjdWR6TXViM0puTHpJd01UZ3ZZM0psWkdWdWRHbGhiSE12ZGpFaVhTd2lkSGx3WlNJNld5SldaWEpwWm1saFlteGxRM0psWkdWdWRHbGhiQ0lzSWxCeWIyWnBiR1VpWFgwc0luTjFZaUk2SW1ScFpEcHJaWGs2ZWpaTmEzRnFiakZUVFZWaVVqZzRVemRDV2taQldtNXlOM05tZWxCWWJXMHpSR1pTWkUxNU0xbzFRMlJOY1c1a0lpd2libUptSWpveE5qSXhPVGN6T1RVMExDSnBjM01pT2lKa2FXUTZhMlY1T25vMlRXdHhhbTR4VTAxVllsSTRPRk0zUWxwR1FWcHVjamR6Wm5wUVdHMXRNMFJtVW1STmVUTmFOVU5rVFhGdVpDSjkueEZVdm00OXZTNGROb1NVUkp3ckNNd2RlUGdyQXlCUnpzN0dxdmNVeUQ2S2pmTk04ZVNnRmVGOENFVUhDMjFXY3dybWJUTnJ6cFF0Z0ZRVEZQXzlIQUEiXX0sInRhZyI6Inh5ejEyMyIsIm5iZiI6MTYyMTk3NDM4MiwiaXNzIjoiZGlkOmtleTp6Nk1rcWpuMVNNVWJSODhTN0JaRkFabnI3c2Z6UFhtbTNEZlJkTXkzWjVDZE1xbmQiLCJhdWQiOlsiZGlkOmtleTp6Nk1rcWpuMVNNVWJSODhTN0JaRkFabnI3c2Z6UFhtbTNEZlJkTXkzWjVDZE1xbmQiXX0.Lju6nUthZXnCi3RyX-6IRowzWQMp5FpcHLHqL9J9AvVWlNa40eWTdhhXPkshLoxjY9sorIO39G_1fc09MWWlAQ'
165
+
166
+ const vpPayloadEd25519 = {
167
+ vp: {
168
+ '@context': ['https://www.w3.org/2018/credentials/v1'],
169
+ type: ['VerifiablePresentation', 'Profile'],
170
+ verifiableCredential: [
171
+ 'eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJjcmVkZW50aWFsU3ViamVjdCI6eyJuYW1lIjoiQWxpY2UifSwiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIlByb2ZpbGUiXX0sInN1YiI6ImRpZDprZXk6ejZNa3FqbjFTTVViUjg4UzdCWkZBWm5yN3NmelBYbW0zRGZSZE15M1o1Q2RNcW5kIiwibmJmIjoxNjIxOTczOTU0LCJpc3MiOiJkaWQ6a2V5Ono2TWtxam4xU01VYlI4OFM3QlpGQVpucjdzZnpQWG1tM0RmUmRNeTNaNUNkTXFuZCJ9.xFUvm49vS4dNoSURJwrCMwdePgrAyBRzs7GqvcUyD6KjfNM8eSgFeF8CEUHC21WcwrmbTNrzpQtgFQTFP_9HAA',
172
+ ],
173
+ },
174
+ tag: 'xyz123',
175
+ nbf: 1621974382,
176
+ iss: didKey,
177
+ aud: didKey,
178
+ }
179
+
180
+ it('should return handled VC message (Ed25519)', async () => {
181
+ expect.assertions(6)
182
+ const message = new Message({ raw: vcJwtEd25519, metaData: [{ type: 'test' }] })
183
+ // This would be done by '@veramo/did-jwt':
184
+ message.data = vcPayloadEd25519
185
+ message.addMetaData({ type: 'JWT', value: 'Ed25519' })
186
+ const handled = await handler.handle(message, context)
187
+ expect(handled.isValid()).toEqual(true)
188
+ expect(handled.id).toEqual(computeEntryHash(vcJwtEd25519))
189
+ expect(handled.raw).toEqual(vcJwtEd25519)
190
+ expect(handled.type).toEqual(MessageTypes.vc)
191
+ expect(handled.from).toEqual(vcPayloadEd25519.iss)
192
+ expect(handled.to).toEqual(vcPayloadEd25519.sub)
193
+ })
194
+
195
+ it('should return handled VP message (Ed25519)', async () => {
196
+ expect.assertions(7)
197
+ const message = new Message({ raw: vpJwtEd25519, metaData: [{ type: 'test' }] })
198
+ // This would be done by '@veramo/did-jwt':
199
+ message.data = vpPayloadEd25519
200
+ message.addMetaData({ type: 'JWT', value: 'Ed25519' })
201
+
202
+ const handled = await handler.handle(message, context)
203
+ expect(handled.isValid()).toEqual(true)
204
+ expect(handled.id).toEqual(computeEntryHash(vpJwtEd25519))
205
+ expect(handled.raw).toEqual(vpJwtEd25519)
206
+ expect(handled.type).toEqual(MessageTypes.vp)
207
+ expect(handled.from).toEqual(vpPayloadEd25519.iss)
208
+ expect(handled.to).toEqual(vpPayloadEd25519.aud)
209
+ expect(handled.threadId).toEqual(vpPayloadEd25519.tag)
210
+ })
211
+
212
+ const vpMultiAudJwt =
213
+ 'eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1QifQ.eyJ2cCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVQcmVzZW50YXRpb24iXSwidmVyaWZpYWJsZUNyZWRlbnRpYWwiOlsiZXlKaGJHY2lPaUpGVXpJMU5rc2lMQ0owZVhBaU9pSktWMVFpZlEuZXlKMll5STZleUpBWTI5dWRHVjRkQ0k2V3lKb2RIUndjem92TDNkM2R5NTNNeTV2Y21jdk1qQXhPQzlqY21Wa1pXNTBhV0ZzY3k5Mk1TSXNJbWgwZEhCek9pOHZkbVZ5WVcxdkxtbHZMMk52Ym5SbGVIUnpMM0J5YjJacGJHVXZkakVpWFN3aWRIbHdaU0k2V3lKV1pYSnBabWxoWW14bFEzSmxaR1Z1ZEdsaGJDSmRMQ0pqY21Wa1pXNTBhV0ZzVTNWaWFtVmpkQ0k2ZXlKdVlXMWxJam9pUVd4cFkyVWlmWDBzSW5OMVlpSTZJbVJwWkRwbGRHaHlPbWR2WlhKc2FUb3dlREF5WkdJMllqZ3pZVE00WlRNeFpHVmtabU5rTURBeE4yRTBPRE5qT0dJd01EY3pZV1EwTURRNU5UZG1OV1l6TXpjNFpEVmtPR1l6WkRneU5USXhNRFE0T1NJc0ltNWlaaUk2TVRZMk5UUTFNalUwT0N3aWFYTnpJam9pWkdsa09tVjBhSEk2WjI5bGNteHBPakI0TURKa1lqWmlPRE5oTXpobE16RmtaV1JtWTJRd01ERTNZVFE0TTJNNFlqQXdOek5oWkRRd05EazFOMlkxWmpNek56aGtOV1E0WmpOa09ESTFNakV3TkRnNUluMC56ZXRBSXVTVWtxNGlmbmxhelg3c1RodTlpd3VzNjZDVHBfaDVObW0xc2RyZXZ4ck02WklSZGJEVExrZlZ6MmxGR3BxeU1aLW9tMVBtUHNOOFluY2ZSZyJdfSwidGFnIjoidGFnMTIzIiwibmJmIjoxNjY1NDUzMDYwLCJpc3MiOiJkaWQ6ZXRocjpnb2VybGk6MHgwMmRiNmI4M2EzOGUzMWRlZGZjZDAwMTdhNDgzYzhiMDA3M2FkNDA0OTU3ZjVmMzM3OGQ1ZDhmM2Q4MjUyMTA0ODkiLCJhdWQiOlsiZGlkOmV4YW1wbGU6MzQ1NiIsImRpZDp3ZWI6dXBvcnQubWUiXX0.NfQjQb3_mo956o5guLTV5iKF9mna-Yy70MBZQlNDu9OujpDhbsaQ5MHFw5GGG1M47_74ZAaMTOx9Wc7iY7eLZw'
214
+
215
+ const vpMultiAudPayload = {
216
+ iat: 1588676739,
217
+ vp: {
218
+ '@context': ['https://www.w3.org/2018/credentials/v1'],
219
+ type: ['VerifiablePresentation'],
220
+ verifiableCredential: [vpMultiAudJwt],
221
+ },
222
+ tag: 'tag123',
223
+ aud: ['did:example:3456', 'did:web:uport.me'],
224
+ iss: 'did:ethr:goerli:0x02db6b83a38e31dedfcd0017a483c8b0073ad404957f5f3378d5d8f3d825210489',
225
+ }
226
+
227
+ it('should use the first audience did as a message.to field', async () => {
228
+ expect.assertions(7)
229
+ const message = new Message({ raw: vpMultiAudJwt, metaData: [{ type: 'test' }] })
230
+ // This would be done by '@veramo/did-jwt':
231
+ message.data = vpMultiAudPayload
232
+ message.addMetaData({ type: 'JWT', value: 'ES256K-R' })
233
+
234
+ const handled = await handler.handle(message, context)
235
+ expect(handled.isValid()).toEqual(true)
236
+ expect(handled.id).toEqual(computeEntryHash(vpMultiAudJwt))
237
+ expect(handled.raw).toEqual(vpMultiAudJwt)
238
+ expect(handled.type).toEqual(MessageTypes.vp)
239
+ expect(handled.from).toEqual(vpMultiAudPayload.iss)
240
+ expect(handled.to).toEqual(vpMultiAudPayload.aud[0])
241
+ expect(handled.threadId).toEqual(vpMultiAudPayload.tag)
242
+ })
243
+
244
+ it('should return handled VC message with credentialStatus', async () => {
245
+ expect.assertions(6)
246
+ const token =
247
+ 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE1ODgyNDkyNTgsInN1YiI6ImRpZDp3ZWI6dXBvcnQubWUiLCJub25jZSI6IjM4NzE4Njc0NTMiLCJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiQXdlc29tZW5lc3NDcmVkZW50aWFsIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7Iml0IjoicmVhbGx5IHdoaXBzIHRoZSBsbGFtbWEncyBhc3MhIn19LCJjcmVkZW50aWFsU3RhdHVzIjp7InR5cGUiOiJFdGhyU3RhdHVzUmVnaXN0cnkyMDE5IiwiaWQiOiJyaW5rZWJ5OjB4OTdmZDI3ODkyY2RjRDAzNWRBZTFmZTcxMjM1YzYzNjA0NEI1OTM0OCJ9LCJpc3MiOiJkaWQ6ZXRocjoweDU0ZDU5ZTNmZmQ3NjkxN2Y2MmRiNzAyYWMzNTRiMTdmMzg0Mjk1NWUifQ.mtMt6-sJdaKH_sPUFPan1FzvWPtlrdKLRCHrh1aOS_zSVyTGHynA0-5AHcEujB1Rz1SuzuM3rkhHRO8eX2IAYg'
248
+ const message = new Message({
249
+ raw: token,
250
+ metaData: [{ type: 'test' }],
251
+ })
252
+ // This would be done by '@veramo/did-jwt':
253
+ message.data = {
254
+ iat: 1588249258,
255
+ sub: 'did:web:uport.me',
256
+ vc: {
257
+ '@context': ['https://www.w3.org/2018/credentials/v1'],
258
+ type: ['VerifiableCredential', 'AwesomenessCredential'],
259
+ credentialSubject: {
260
+ it: "really whips the llamma's ass!",
261
+ },
262
+ },
263
+ credentialStatus: {
264
+ type: 'EthrStatusRegistry2019',
265
+ // TODO(nickreynolds): deploy
266
+ id: 'sepolia:0x97fd27892cdcD035dAe1fe71235c636044B59348',
267
+ },
268
+ iss: 'did:ethr:0x54d59e3ffd76917f62db702ac354b17f3842955e',
269
+ }
270
+ message.addMetaData({ type: 'JWT', value: 'ES256K' })
271
+
272
+ const handled = await handler.handle(message, context)
273
+
274
+ expect(handled.isValid()).toEqual(true)
275
+ expect(handled.id).toEqual(computeEntryHash(token))
276
+ expect(handled.raw).toEqual(token)
277
+ expect(handled.type).toEqual(MessageTypes.vc)
278
+ expect(handled.from).toEqual('did:ethr:0x54d59e3ffd76917f62db702ac354b17f3842955e')
279
+ expect(handled.to).toEqual('did:web:uport.me')
280
+ })
281
+ })