@bedrock/vc-verifier 9.0.0 → 12.0.0

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,390 +0,0 @@
1
- /*!
2
- * Copyright (c) 2020-2022 Digital Bazaar, Inc. All rights reserved.
3
- */
4
- import * as helpers from './helpers.js';
5
- import {agent} from '@bedrock/https-agent';
6
- import {createRequire} from 'node:module';
7
- import {documentLoader as brDocLoader} from '@bedrock/jsonld-document-loader';
8
- import {httpClient} from '@digitalbazaar/http-client';
9
- import {klona} from 'klona';
10
- import {mockData} from './mock.data.js';
11
- const require = createRequire(import.meta.url);
12
- const {CapabilityAgent} = require('@digitalbazaar/webkms-client');
13
- const didKeyDriver = require('@digitalbazaar/did-method-key').driver();
14
- const {Ed25519Signature2020} = require('@digitalbazaar/ed25519-signature-2020');
15
- const vc = require('@digitalbazaar/vc');
16
-
17
- const {baseUrl} = mockData;
18
- const serviceType = 'vc-verifier';
19
-
20
- // NOTE: using embedded context in mockCredential:
21
- // https://www.w3.org/2018/credentials/examples/v1
22
- const mockCredential = require('./mock-credential');
23
-
24
- describe('verify APIs', () => {
25
- let capabilityAgent;
26
- let verifierConfig;
27
- let verifierId;
28
- let rootZcap;
29
- const zcaps = {};
30
- beforeEach(async () => {
31
- const secret = '53ad64ce-8e1d-11ec-bb12-10bf48838a41';
32
- const handle = 'test';
33
- capabilityAgent = await CapabilityAgent.fromSecret({secret, handle});
34
-
35
- // create keystore for capability agent
36
- const keystoreAgent = await helpers.createKeystoreAgent(
37
- {capabilityAgent});
38
-
39
- // create EDV for storage (creating hmac and kak in the process)
40
- const {
41
- edvConfig,
42
- hmac,
43
- keyAgreementKey
44
- } = await helpers.createEdv({capabilityAgent, keystoreAgent});
45
-
46
- // get service agent to delegate to
47
- const serviceAgentUrl =
48
- `${baseUrl}/service-agents/${encodeURIComponent(serviceType)}`;
49
- const {data: serviceAgent} = await httpClient.get(serviceAgentUrl, {
50
- agent
51
- });
52
-
53
- // delegate edv, hmac, and key agreement key zcaps to service agent
54
- const {id: edvId} = edvConfig;
55
- zcaps.edv = await helpers.delegate({
56
- controller: serviceAgent.id,
57
- delegator: capabilityAgent,
58
- invocationTarget: edvId
59
- });
60
- const {keystoreId} = keystoreAgent;
61
- zcaps.hmac = await helpers.delegate({
62
- capability: `urn:zcap:root:${encodeURIComponent(keystoreId)}`,
63
- controller: serviceAgent.id,
64
- invocationTarget: hmac.id,
65
- delegator: capabilityAgent
66
- });
67
- zcaps.keyAgreementKey = await helpers.delegate({
68
- capability: `urn:zcap:root:${encodeURIComponent(keystoreId)}`,
69
- controller: serviceAgent.id,
70
- invocationTarget: keyAgreementKey.kmsId,
71
- delegator: capabilityAgent
72
- });
73
-
74
- // create verifier instance
75
- verifierConfig = await helpers.createConfig({capabilityAgent, zcaps});
76
- verifierId = verifierConfig.id;
77
- rootZcap = `urn:zcap:root:${encodeURIComponent(verifierId)}`;
78
- });
79
- describe('/challenges', () => {
80
- it('create a challenge', async () => {
81
- let err;
82
- let result;
83
- try {
84
- result = await helpers.createChallenge({capabilityAgent, verifierId});
85
- } catch(e) {
86
- err = e;
87
- }
88
- assertNoError(err);
89
- should.exist(result.data);
90
- result.status.should.equal(200);
91
- result.data.should.have.keys(['challenge']);
92
- result.data.challenge.should.be.a('string');
93
- });
94
- });
95
- describe('/credentials/verify', () => {
96
- it('verifies a valid credential', async () => {
97
- const verifiableCredential = klona(mockCredential);
98
- let error;
99
- let result;
100
- try {
101
- const zcapClient = helpers.createZcapClient({capabilityAgent});
102
- result = await zcapClient.write({
103
- url: `${verifierId}/credentials/verify`,
104
- capability: rootZcap,
105
- json: {
106
- options: {
107
- checks: ['proof'],
108
- },
109
- verifiableCredential
110
- }
111
- });
112
- } catch(e) {
113
- error = e;
114
- }
115
- assertNoError(error);
116
- should.exist(result.data.verified);
117
- result.data.verified.should.be.a('boolean');
118
- result.data.verified.should.equal(true);
119
- const {checks} = result.data;
120
- checks.should.be.an('array');
121
- checks.should.have.length(1);
122
- const [check] = checks;
123
- check.should.be.a('string');
124
- check.should.equal('proof');
125
- should.exist(result.data.results);
126
- result.data.results.should.be.an('array');
127
- result.data.results.should.have.length(1);
128
- const [r] = result.data.results;
129
- r.verified.should.be.a('boolean');
130
- r.verified.should.equal(true);
131
- });
132
- it('does not verify an invalid credential', async () => {
133
- const badCredential = klona(mockCredential);
134
- // change the degree name
135
- badCredential.credentialSubject.degree.name =
136
- 'Bachelor of Science in Nursing';
137
-
138
- let error;
139
- let result;
140
- try {
141
- const zcapClient = helpers.createZcapClient({capabilityAgent});
142
- result = await zcapClient.write({
143
- url: `${verifierId}/credentials/verify`,
144
- capability: rootZcap,
145
- json: {
146
- options: {
147
- checks: ['proof'],
148
- },
149
- verifiableCredential: badCredential
150
- }
151
- });
152
- } catch(e) {
153
- error = e;
154
- }
155
- should.exist(error);
156
- should.not.exist(result);
157
- should.exist(error.data);
158
- error.data.should.be.an('object');
159
- error.data.verified.should.be.a('boolean');
160
- error.data.verified.should.equal(false);
161
- error.data.error.name.should.equal('VerificationError');
162
- error.data.error.errors[0].message.should.equal('Invalid signature.');
163
- });
164
- });
165
-
166
- describe('/presentations/verify', () => {
167
- it('verifies a valid presentation', async () => {
168
- // get signing key
169
- const {methodFor} = await didKeyDriver.generate();
170
- const signingKey = methodFor({purpose: 'assertionMethod'});
171
- const suite = new Ed25519Signature2020({key: signingKey});
172
-
173
- const verifiableCredential = klona(mockCredential);
174
- const presentation = vc.createPresentation({
175
- holder: 'did:test:foo',
176
- id: 'urn:uuid:3e793029-d699-4096-8e74-5ebd956c3137',
177
- verifiableCredential
178
- });
179
-
180
- // get challenge from verifier
181
- const {data: {challenge}} = await helpers.createChallenge(
182
- {capabilityAgent, verifierId});
183
-
184
- await vc.signPresentation({
185
- presentation,
186
- suite,
187
- challenge,
188
- documentLoader: brDocLoader
189
- });
190
-
191
- let error;
192
- let result;
193
- try {
194
- const zcapClient = helpers.createZcapClient({capabilityAgent});
195
- result = await zcapClient.write({
196
- url: `${verifierId}/presentations/verify`,
197
- capability: rootZcap,
198
- json: {
199
- options: {
200
- challenge,
201
- checks: ['proof'],
202
- },
203
- verifiablePresentation: presentation
204
- }
205
- });
206
- } catch(e) {
207
- error = e;
208
- }
209
- assertNoError(error);
210
- should.exist(result.data.checks);
211
- const {checks} = result.data;
212
- checks.should.be.an('array');
213
- checks.should.have.length(1);
214
- checks[0].should.be.a('string');
215
- checks[0].should.equal('proof');
216
- should.exist(result.data.verified);
217
- result.data.verified.should.be.a('boolean');
218
- result.data.verified.should.equal(true);
219
- should.exist(result.data.presentationResult);
220
- result.data.presentationResult.should.be.an('object');
221
- should.exist(result.data.presentationResult.verified);
222
- result.data.presentationResult.verified.should.be.a('boolean');
223
- result.data.presentationResult.verified.should.equal(true);
224
- should.exist(result.data.credentialResults);
225
- const {data: {credentialResults}} = result;
226
- credentialResults.should.be.an('array');
227
- credentialResults.should.have.length(1);
228
- const [credentialResult] = credentialResults;
229
- should.exist(credentialResult.verified);
230
- credentialResult.verified.should.be.a('boolean');
231
- credentialResult.verified.should.equal(true);
232
- });
233
- it('returns an error if bad challenge is specified', async () => {
234
- // get signing key
235
- const {methodFor} = await didKeyDriver.generate();
236
- const signingKey = methodFor({purpose: 'assertionMethod'});
237
- const suite = new Ed25519Signature2020({key: signingKey});
238
-
239
- const verifiableCredential = klona(mockCredential);
240
- const presentation = vc.createPresentation({
241
- holder: 'foo',
242
- id: 'urn:uuid:3e793029-d699-4096-8e74-5ebd956c3137',
243
- verifiableCredential
244
- });
245
-
246
- // expired / bad challenge
247
- const challenge = 'z1A9b6RjuUzVWC3VcvsFX5fPb';
248
-
249
- await vc.signPresentation({
250
- presentation, suite, challenge, documentLoader: brDocLoader
251
- });
252
-
253
- let error;
254
- let result;
255
- try {
256
- const zcapClient = helpers.createZcapClient({capabilityAgent});
257
- result = await zcapClient.write({
258
- url: `${verifierId}/presentations/verify`,
259
- capability: rootZcap,
260
- json: {
261
- options: {
262
- challenge,
263
- checks: ['proof'],
264
- },
265
- verifiablePresentation: presentation
266
- }
267
- });
268
- } catch(e) {
269
- error = e;
270
- }
271
- should.exist(error);
272
- should.exist(error.data);
273
- should.not.exist(result);
274
- error.data.should.be.an('object');
275
- error.data.verified.should.be.a('boolean');
276
- error.data.verified.should.equal(false);
277
- error.data.error.message.should.equal('Invalid or expired challenge.');
278
- error.data.error.name.should.equal('DataError');
279
- });
280
- it('returns an error if challenge is not specified', async () => {
281
- // get signing key
282
- const {methodFor} = await didKeyDriver.generate();
283
- const signingKey = methodFor({purpose: 'assertionMethod'});
284
- const suite = new Ed25519Signature2020({key: signingKey});
285
-
286
- const verifiableCredential = klona(mockCredential);
287
- const presentation = vc.createPresentation({
288
- holder: 'foo',
289
- id: 'urn:uuid:3e793029-d699-4096-8e74-5ebd956c3137',
290
- verifiableCredential
291
- });
292
-
293
- // get challenge from verifier
294
- const {data: {challenge}} = await helpers.createChallenge(
295
- {capabilityAgent, verifierId});
296
-
297
- await vc.signPresentation({
298
- presentation, suite, challenge, documentLoader: brDocLoader
299
- });
300
-
301
- let error;
302
- let result;
303
- try {
304
- const zcapClient = helpers.createZcapClient({capabilityAgent});
305
- result = await zcapClient.write({
306
- url: `${verifierId}/presentations/verify`,
307
- capability: rootZcap,
308
- json: {
309
- options: {
310
- // intentionally omit challenge
311
- checks: ['proof'],
312
- },
313
- verifiablePresentation: presentation
314
- }
315
- });
316
- } catch(e) {
317
- error = e;
318
- }
319
- should.exist(error);
320
- should.exist(error.data);
321
- should.not.exist(result);
322
- error.data.should.be.an('object');
323
- error.data.verified.should.be.a('boolean');
324
- error.data.verified.should.equal(false);
325
- error.data.error.message.should.equal('"options.challenge" is required.');
326
- error.data.error.name.should.equal('TypeError');
327
- });
328
- it('does not verify a presentation with a bad credential', async () => {
329
- // get signing key
330
- const {methodFor} = await didKeyDriver.generate();
331
- const signingKey = methodFor({purpose: 'assertionMethod'});
332
- const suite = new Ed25519Signature2020({key: signingKey});
333
-
334
- const badCredential = klona(mockCredential);
335
- // change the degree name
336
- badCredential.credentialSubject.degree.name =
337
- 'Bachelor of Science in Nursing';
338
- const presentation = vc.createPresentation({
339
- id: 'urn:uuid:3e793029-d699-4096-8e74-5ebd956c3137',
340
- verifiableCredential: badCredential
341
- });
342
-
343
- // get challenge from verifier
344
- const {data: {challenge}} = await helpers.createChallenge(
345
- {capabilityAgent, verifierId});
346
-
347
- await vc.signPresentation({
348
- presentation, suite, challenge, documentLoader: brDocLoader
349
- });
350
-
351
- let error;
352
- let result;
353
- try {
354
- const zcapClient = helpers.createZcapClient({capabilityAgent});
355
- result = await zcapClient.write({
356
- url: `${verifierId}/presentations/verify`,
357
- capability: rootZcap,
358
- json: {
359
- options: {
360
- challenge,
361
- checks: ['proof'],
362
- },
363
- verifiablePresentation: presentation
364
- }
365
- });
366
- } catch(e) {
367
- error = e;
368
- }
369
- should.exist(error);
370
- should.not.exist(result);
371
- should.exist(error.data.checks);
372
- const {checks} = error.data;
373
- checks.should.be.an('array');
374
- checks.should.have.length(1);
375
- checks[0].should.be.an('object');
376
- checks[0].check.should.eql(['proof']);
377
- should.exist(error.data.verified);
378
- error.data.verified.should.be.a('boolean');
379
- error.data.verified.should.equal(false);
380
- should.exist(error.data.error);
381
- error.data.error.errors.should.be.an('array');
382
- error.data.error.errors.should.have.length(1);
383
- error.data.error.name.should.equal('VerificationError');
384
- const e = error.data.error.errors[0];
385
- e.should.be.an('object');
386
- should.exist(e.name);
387
- e.message.should.equal('Invalid signature.');
388
- });
389
- });
390
- });