@digitalbazaar/vc 7.0.0 → 7.1.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.
- package/README.md +9 -3
- package/lib/helpers.js +18 -0
- package/lib/index.js +42 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,7 +72,7 @@ For signing, when setting up a signature suite, you will need to pass in
|
|
|
72
72
|
a key pair containing a private key.
|
|
73
73
|
|
|
74
74
|
```js
|
|
75
|
-
import vc from '@digitalbazaar/vc';
|
|
75
|
+
import * as vc from '@digitalbazaar/vc';
|
|
76
76
|
|
|
77
77
|
// Required to set up a suite instance with private key
|
|
78
78
|
import {Ed25519VerificationKey2020} from
|
|
@@ -94,7 +94,7 @@ Pre-requisites:
|
|
|
94
94
|
Document and Public Key
|
|
95
95
|
|
|
96
96
|
```js
|
|
97
|
-
|
|
97
|
+
import * as vc from '@digitalbazaar/vc';
|
|
98
98
|
|
|
99
99
|
// Sample unsigned credential
|
|
100
100
|
const credential = {
|
|
@@ -477,8 +477,8 @@ Pre-requisites:
|
|
|
477
477
|
// by requiring this first you ensure security
|
|
478
478
|
// contexts are loaded from jsonld-signatures
|
|
479
479
|
// and not an insecure source.
|
|
480
|
+
import * as vc from '@digitalbazaar/vc';
|
|
480
481
|
const {extendContextLoader} = require('jsonld-signatures');
|
|
481
|
-
const vc = require('@digitalbazaar/vc');
|
|
482
482
|
// @digitalbazaar/vc exports its own secure documentLoader.
|
|
483
483
|
const {defaultDocumentLoader} = vc;
|
|
484
484
|
// a valid json-ld @context.
|
|
@@ -516,6 +516,8 @@ Once you've created the presentation (either via `createPresentation()` or
|
|
|
516
516
|
manually), you can sign it using `signPresentation()`:
|
|
517
517
|
|
|
518
518
|
```js
|
|
519
|
+
import * as vc from '@digitalbazaar/vc';
|
|
520
|
+
|
|
519
521
|
const vp = await vc.signPresentation({
|
|
520
522
|
presentation, suite, challenge, documentLoader
|
|
521
523
|
});
|
|
@@ -578,6 +580,8 @@ Pre-requisites:
|
|
|
578
580
|
To verify a verifiable presentation:
|
|
579
581
|
|
|
580
582
|
```js
|
|
583
|
+
import * as vc from '@digitalbazaar/vc';
|
|
584
|
+
|
|
581
585
|
// challenge has been received from the requesting party - see 'challenge'
|
|
582
586
|
// section below
|
|
583
587
|
|
|
@@ -590,6 +594,8 @@ To verify an unsigned presentation, you must set the `unsignedPresentation`
|
|
|
590
594
|
flag:
|
|
591
595
|
|
|
592
596
|
```js
|
|
597
|
+
import * as vc from '@digitalbazaar/vc';
|
|
598
|
+
|
|
593
599
|
const result = await vc.verify({
|
|
594
600
|
presentation, suite, documentLoader, unsignedPresentation: true
|
|
595
601
|
});
|
package/lib/helpers.js
CHANGED
|
@@ -101,3 +101,21 @@ export function getContextForVersion({version}) {
|
|
|
101
101
|
export function checkContextVersion({credential, version}) {
|
|
102
102
|
return getContextVersion({credential}) === version;
|
|
103
103
|
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Compares two times with consideration of max clock skew
|
|
107
|
+
*
|
|
108
|
+
* @param {object} options - Options.
|
|
109
|
+
* @param {number} options.t1 - time 1
|
|
110
|
+
* @param {number} options.t2 - time 2
|
|
111
|
+
* @param {number} options.maxClockSkew - number of seconds
|
|
112
|
+
* @returns {number} - A number greater or less than zero
|
|
113
|
+
*/
|
|
114
|
+
export function compareTime({t1, t2, maxClockSkew}) {
|
|
115
|
+
// `maxClockSkew` is in seconds, so transform to milliseconds
|
|
116
|
+
if(Math.abs(t1 - t2) < (maxClockSkew * 1000)) {
|
|
117
|
+
// times are equal within the max clock skew
|
|
118
|
+
return 0;
|
|
119
|
+
}
|
|
120
|
+
return t1 < t2 ? -1 : 1;
|
|
121
|
+
}
|
package/lib/index.js
CHANGED
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
assertCredentialContext,
|
|
39
39
|
assertDateString,
|
|
40
40
|
checkContextVersion,
|
|
41
|
+
compareTime,
|
|
41
42
|
getContextForVersion
|
|
42
43
|
} from './helpers.js';
|
|
43
44
|
import {documentLoader as _documentLoader} from './documentLoader.js';
|
|
@@ -103,6 +104,10 @@ export {CredentialIssuancePurpose};
|
|
|
103
104
|
* @param {object} [options.documentLoader] - A document loader.
|
|
104
105
|
* @param {string|Date} [options.now] - A string representing date time in
|
|
105
106
|
* ISO 8601 format or an instance of Date. Defaults to current date time.
|
|
107
|
+
* @param {number} [options.maxClockSkew=300] - A maximum number of seconds
|
|
108
|
+
* that clocks may be skewed when checking capability expiration date-times
|
|
109
|
+
* against `date` and when comparing invocation proof creation time against
|
|
110
|
+
* delegation proof creation time.
|
|
106
111
|
*
|
|
107
112
|
* @throws {Error} If missing required properties.
|
|
108
113
|
*
|
|
@@ -112,7 +117,8 @@ export async function issue({
|
|
|
112
117
|
credential, suite,
|
|
113
118
|
purpose = new CredentialIssuancePurpose(),
|
|
114
119
|
documentLoader = defaultDocumentLoader,
|
|
115
|
-
now
|
|
120
|
+
now,
|
|
121
|
+
maxClockSkew = 300
|
|
116
122
|
} = {}) {
|
|
117
123
|
// check to make sure the `suite` has required params
|
|
118
124
|
// Note: verificationMethod defaults to publicKey.id, in suite constructor
|
|
@@ -135,7 +141,7 @@ export async function issue({
|
|
|
135
141
|
}
|
|
136
142
|
|
|
137
143
|
// run common credential checks
|
|
138
|
-
_checkCredential({credential, now, mode: 'issue'});
|
|
144
|
+
_checkCredential({credential, now, mode: 'issue', maxClockSkew});
|
|
139
145
|
|
|
140
146
|
return jsigs.sign(credential, {purpose, documentLoader, suite});
|
|
141
147
|
}
|
|
@@ -219,6 +225,10 @@ export async function derive({
|
|
|
219
225
|
* credential status if `credentialStatus` is present on the credential.
|
|
220
226
|
* @param {string|Date} [options.now] - A string representing date time in
|
|
221
227
|
* ISO 8601 format or an instance of Date. Defaults to current date time.
|
|
228
|
+
* @param {number} [options.maxClockSkew=300] - A maximum number of seconds
|
|
229
|
+
* that clocks may be skewed when checking capability expiration date-times
|
|
230
|
+
* against `date` and when comparing invocation proof creation time against
|
|
231
|
+
* delegation proof creation time.
|
|
222
232
|
*
|
|
223
233
|
* @returns {Promise<VerifyPresentationResult>} The verification result.
|
|
224
234
|
*/
|
|
@@ -264,6 +274,10 @@ export async function verify(options = {}) {
|
|
|
264
274
|
* credential status if `credentialStatus` is present on the credential.
|
|
265
275
|
* @param {string|Date} [options.now] - A string representing date time in
|
|
266
276
|
* ISO 8601 format or an instance of Date. Defaults to current date time.
|
|
277
|
+
* @param {number} [options.maxClockSkew=300] - A maximum number of seconds
|
|
278
|
+
* that clocks may be skewed when checking capability expiration date-times
|
|
279
|
+
* against `date` and when comparing invocation proof creation time against
|
|
280
|
+
* delegation proof creation time.
|
|
267
281
|
*
|
|
268
282
|
* @returns {Promise<VerifyCredentialResult>} The verification result.
|
|
269
283
|
*/
|
|
@@ -295,6 +309,10 @@ export async function verifyCredential(options = {}) {
|
|
|
295
309
|
* definition in the `verify()` docstring, for this param.
|
|
296
310
|
* @param {string|Date} [options.now] - A string representing date time in
|
|
297
311
|
* ISO 8601 format or an instance of Date. Defaults to current date time.
|
|
312
|
+
* @param {number} [options.maxClockSkew=300] - A maximum number of seconds
|
|
313
|
+
* that clocks may be skewed when checking capability expiration date-times
|
|
314
|
+
* against `date` and when comparing invocation proof creation time against
|
|
315
|
+
* delegation proof creation time.
|
|
298
316
|
*
|
|
299
317
|
* @throws {Error} If required parameters are missing (in `_checkCredential`).
|
|
300
318
|
*
|
|
@@ -306,10 +324,10 @@ export async function verifyCredential(options = {}) {
|
|
|
306
324
|
* @returns {Promise<VerifyCredentialResult>} The verification result.
|
|
307
325
|
*/
|
|
308
326
|
async function _verifyCredential(options = {}) {
|
|
309
|
-
const {credential, checkStatus, now} = options;
|
|
327
|
+
const {credential, checkStatus, now, maxClockSkew} = options;
|
|
310
328
|
|
|
311
329
|
// run common credential checks
|
|
312
|
-
_checkCredential({credential, now});
|
|
330
|
+
_checkCredential({credential, now, maxClockSkew});
|
|
313
331
|
|
|
314
332
|
// if credential status is provided, a `checkStatus` function must be given
|
|
315
333
|
if(credential.credentialStatus && typeof options.checkStatus !== 'function') {
|
|
@@ -352,6 +370,10 @@ async function _verifyCredential(options = {}) {
|
|
|
352
370
|
* @param {string} [options.holder] - Optional presentation holder url.
|
|
353
371
|
* @param {string|Date} [options.now] - A string representing date time in
|
|
354
372
|
* ISO 8601 format or an instance of Date. Defaults to current date time.
|
|
373
|
+
* @param {number} [options.maxClockSkew=300] - A maximum number of seconds
|
|
374
|
+
* that clocks may be skewed when checking capability expiration date-times
|
|
375
|
+
* against `date` and when comparing invocation proof creation time against
|
|
376
|
+
* delegation proof creation time.
|
|
355
377
|
* @param {number} [options.version = 2.0] - The VC context version to use.
|
|
356
378
|
*
|
|
357
379
|
* @throws {TypeError} If verifiableCredential param is missing.
|
|
@@ -362,7 +384,7 @@ async function _verifyCredential(options = {}) {
|
|
|
362
384
|
* VerifiablePresentation.
|
|
363
385
|
*/
|
|
364
386
|
export function createPresentation({
|
|
365
|
-
verifiableCredential, id, holder, now, version = 2.0
|
|
387
|
+
verifiableCredential, id, holder, now, version = 2.0, maxClockSkew = 300
|
|
366
388
|
} = {}) {
|
|
367
389
|
const initialContext = getContextForVersion({version});
|
|
368
390
|
const presentation = {
|
|
@@ -373,7 +395,7 @@ export function createPresentation({
|
|
|
373
395
|
const credentials = [].concat(verifiableCredential);
|
|
374
396
|
// ensure all credentials are valid
|
|
375
397
|
for(const credential of credentials) {
|
|
376
|
-
_checkCredential({credential, now});
|
|
398
|
+
_checkCredential({credential, now, maxClockSkew});
|
|
377
399
|
}
|
|
378
400
|
presentation.verifiableCredential = credentials;
|
|
379
401
|
}
|
|
@@ -456,6 +478,10 @@ export async function signPresentation(options = {}) {
|
|
|
456
478
|
* credential status if `credentialStatus` is present on the credential.
|
|
457
479
|
* @param {string|Date} [options.now] - A string representing date time in
|
|
458
480
|
* ISO 8601 format or an instance of Date. Defaults to current date time.
|
|
481
|
+
* @param {number} [options.maxClockSkew=300] - A maximum number of seconds
|
|
482
|
+
* that clocks may be skewed when checking capability expiration date-times
|
|
483
|
+
* against `date` and when comparing invocation proof creation time against
|
|
484
|
+
* delegation proof creation time.
|
|
459
485
|
*
|
|
460
486
|
* @throws {Error} If presentation is missing required params.
|
|
461
487
|
*
|
|
@@ -571,6 +597,10 @@ const mustHaveType = [
|
|
|
571
597
|
* VerifiableCredential.
|
|
572
598
|
* @param {string|Date} [options.now] - A string representing date time in
|
|
573
599
|
* ISO 8601 format or an instance of Date. Defaults to current date time.
|
|
600
|
+
* @param {number} [options.maxClockSkew=300] - A maximum number of seconds
|
|
601
|
+
* that clocks may be skewed when checking capability expiration date-times
|
|
602
|
+
* against `date` and when comparing invocation proof creation time against
|
|
603
|
+
* delegation proof creation time.
|
|
574
604
|
* @param {string} [options.mode] - The mode of operation for this
|
|
575
605
|
* validation function, either `issue` or `verify`.
|
|
576
606
|
*
|
|
@@ -578,7 +608,7 @@ const mustHaveType = [
|
|
|
578
608
|
* @private
|
|
579
609
|
*/
|
|
580
610
|
export function _checkCredential({
|
|
581
|
-
credential, now = new Date(), mode = 'verify'
|
|
611
|
+
credential, now = new Date(), mode = 'verify', maxClockSkew = 300
|
|
582
612
|
} = {}) {
|
|
583
613
|
if(typeof now === 'string') {
|
|
584
614
|
now = new Date(now);
|
|
@@ -617,7 +647,8 @@ export function _checkCredential({
|
|
|
617
647
|
assertDateString({credential, prop: 'expirationDate'});
|
|
618
648
|
if(mode === 'verify') {
|
|
619
649
|
// check if `now` is after `expirationDate`
|
|
620
|
-
|
|
650
|
+
const expirationDate = new Date(credential.expirationDate);
|
|
651
|
+
if(compareTime({t1: now, t2: expirationDate, maxClockSkew}) > 0) {
|
|
621
652
|
throw new Error('Credential has expired.');
|
|
622
653
|
}
|
|
623
654
|
}
|
|
@@ -625,7 +656,7 @@ export function _checkCredential({
|
|
|
625
656
|
// check if `now` is before `issuanceDate` on verification
|
|
626
657
|
if(mode === 'verify') {
|
|
627
658
|
const issuanceDate = new Date(credential.issuanceDate);
|
|
628
|
-
if(now
|
|
659
|
+
if(compareTime({t1: issuanceDate, t2: now, maxClockSkew}) > 0) {
|
|
629
660
|
throw new Error(
|
|
630
661
|
`The current date time (${now.toISOString()}) is before the ` +
|
|
631
662
|
`"issuanceDate" (${credential.issuanceDate}).`);
|
|
@@ -639,7 +670,7 @@ export function _checkCredential({
|
|
|
639
670
|
assertDateString({credential, prop: 'validUntil'});
|
|
640
671
|
if(mode === 'verify') {
|
|
641
672
|
validUntil = new Date(credential.validUntil);
|
|
642
|
-
if(now
|
|
673
|
+
if(compareTime({t1: now, t2: validUntil, maxClockSkew}) > 0) {
|
|
643
674
|
throw new Error(
|
|
644
675
|
`The current date time (${now.toISOString()}) is after ` +
|
|
645
676
|
`"validUntil" (${credential.validUntil}).`);
|
|
@@ -651,7 +682,7 @@ export function _checkCredential({
|
|
|
651
682
|
if(mode === 'verify') {
|
|
652
683
|
// check if `now` is before `validFrom`
|
|
653
684
|
validFrom = new Date(credential.validFrom);
|
|
654
|
-
if(now
|
|
685
|
+
if(compareTime({t1: validFrom, t2: now, maxClockSkew}) > 0) {
|
|
655
686
|
throw new Error(
|
|
656
687
|
`The current date time (${now.toISOString()}) is before ` +
|
|
657
688
|
`"validFrom" (${credential.validFrom}).`);
|