@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 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
- const vc = require('@digitalbazaar/vc');
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
- if(now > new Date(credential.expirationDate)) {
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 < issuanceDate) {
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 > validUntil) {
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 < validFrom) {
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}).`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitalbazaar/vc",
3
- "version": "7.0.0",
3
+ "version": "7.1.0",
4
4
  "description": "Verifiable Credentials JavaScript library.",
5
5
  "homepage": "https://github.com/digitalbazaar/vc",
6
6
  "author": {