@interop/did-web-resolver 2.1.1 → 2.2.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
@@ -58,9 +58,40 @@ resolver.use(didWebDriver)
58
58
 
59
59
  ### Generating a new DID
60
60
 
61
+ #### Generating from seed
62
+
63
+ If you have a deterministic secret seed (created with [`did-cli`](https://github.com/digitalcredentials/did-cli),
64
+ for example) and would like to generate a `did:web` document from it:
65
+
61
66
  ```js
62
- const { didDocument, keyPairs, methodFor } = await didWebDriver.generate()
67
+ const url = 'https://example.com'
68
+ const seed = 'z1AhV1bADy7RepJ64mvH7Kk7htFNGc7EA1WA5nGzLSTWc6o'
63
69
 
70
+ const { didDocument, keyPairs, methodFor } = await didWebDriver.generate({ url, seed })
71
+ // didDocument
72
+ {
73
+ '@context': [
74
+ 'https://www.w3.org/ns/did/v1',
75
+ 'https://w3id.org/security/suites/ed25519-2020/v1',
76
+ 'https://w3id.org/security/suites/x25519-2020/v1'
77
+ ],
78
+ id: 'did:web:example.com',
79
+ assertionMethod: [{
80
+ id: 'did:web:example.com#z6MkmDMjfkjs9XPCN1LfoQQRHz1mJ8PEdiVYC66XKhj3wGyB',
81
+ type: 'Ed25519VerificationKey2020',
82
+ controller: 'did:web:example.com',
83
+ publicKeyMultibase: 'z6MkmDMjfkjs9XPCN1LfoQQRHz1mJ8PEdiVYC66XKhj3wGyB'
84
+ }]
85
+ }
86
+ ```
87
+
88
+ #### Generating new random keys
89
+
90
+ Invoking `generate()` by itself will create new keypairs for each proof purpose.
91
+
92
+ ```js
93
+ const { didDocument, keyPairs, methodFor } = await didWebDriver.generate()
94
+ // didDocument
64
95
  {
65
96
  '@context': [
66
97
  'https://www.w3.org/ns/did/v1',
@@ -7,6 +7,7 @@ var didIo = require('@digitalcredentials/did-io');
7
7
  var ed25519Context = require('ed25519-signature-2020-context');
8
8
  var x25519Context = require('x25519-key-agreement-2020-context');
9
9
  var didContext = require('did-context');
10
+ var bnid = require('@digitalcredentials/bnid');
10
11
 
11
12
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
12
13
 
@@ -132,7 +133,7 @@ function urlFromDid ({ did } = {}) {
132
133
  * DID Document initialized with keys, as well as the map of the corresponding
133
134
  * key pairs (by key id).
134
135
  */
135
- async function initKeys ({ didDocument, cryptoLd, keyMap = {} } = {}) {
136
+ async function initKeys ({ didDocument, cryptoLd, keyMap } = {}) {
136
137
  const doc = { ...didDocument };
137
138
  if (!doc.id) {
138
139
  throw new TypeError(
@@ -196,7 +197,7 @@ class DidWebResolver {
196
197
  * @param [id] {string} - A did:web DID. If absent, will be converted from url
197
198
  * @param [url] {string}
198
199
  *
199
- * @param [keyMap=DEFAULT_KEY_MAP] {object} A hashmap of key types by purpose.
200
+ * @param [keyMap] {object} A hashmap of key types by purpose.
200
201
  *
201
202
  * @parma [cryptoLd] {object} CryptoLD instance with support for supported
202
203
  * crypto suites installed.
@@ -206,9 +207,27 @@ class DidWebResolver {
206
207
  * with the corresponding key pairs used to generate it (for storage in a
207
208
  * KMS).
208
209
  */
209
- async generate ({ id, url, keyMap = this.keyMap, cryptoLd = this.cryptoLd } = {}) {
210
+ async generate ({ id, url, seed, keyMap, cryptoLd = this.cryptoLd } = {}) {
211
+ if (!id && !url) {
212
+ throw new TypeError('A "url" or an "id" parameter is required.')
213
+ }
214
+ if (seed && keyMap) {
215
+ throw new TypeError(
216
+ 'Either a "seed" or a "keyMap" param must be provided, but not both.'
217
+ )
218
+ }
219
+
210
220
  const did = id || didFromUrl({ url });
211
221
 
222
+ if (seed) {
223
+ const keyPair = await _keyPairFromSecretSeed({
224
+ seed, controller: did, cryptoLd
225
+ });
226
+ keyMap = { assertionMethod: keyPair };
227
+ } else {
228
+ keyMap = keyMap || this.keyMap;
229
+ }
230
+
212
231
  // Compose the DID Document
213
232
  let didDocument = {
214
233
  '@context': [
@@ -330,6 +349,30 @@ class DidWebResolver {
330
349
  }
331
350
  }
332
351
 
352
+ /**
353
+ * @param options {object}
354
+ * @param options.seed {string|Uint8Array}
355
+ * @param controller {string}
356
+ * @param cryptoLd {object}
357
+ *
358
+ * @return {Promise<LDKeyPair>}
359
+ */
360
+ async function _keyPairFromSecretSeed ({ seed, controller, cryptoLd } = {}) {
361
+ let seedBytes;
362
+ if (typeof seed === 'string') {
363
+ // Currently only supports base58 multibase / identity multihash encoding.
364
+ if (!seed.startsWith('z1A')) {
365
+ throw new TypeError('"seed" parameter must be a multibase/multihash encoded string, or a Uint8Array.')
366
+ }
367
+ seedBytes = bnid.decodeSecretKeySeed({ secretKeySeed: seed });
368
+ } else {
369
+ seedBytes = new Uint8Array(seed);
370
+ }
371
+ return cryptoLd.generate({
372
+ controller, seed: seedBytes, type: 'Ed25519VerificationKey2020'
373
+ })
374
+ }
375
+
333
376
  exports.DidWebResolver = DidWebResolver;
334
377
  exports.didFromUrl = didFromUrl;
335
378
  exports.initKeys = initKeys;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@interop/did-web-resolver",
3
3
  "description": "A did:web method Decentralized Identifier (DID) resolver for the did-io library.",
4
- "version": "2.1.1",
4
+ "version": "2.2.0",
5
5
  "author": {
6
6
  "name": "Dmitri Zagidulin",
7
7
  "url": "https://github.com/dmitrizagidulin/"
@@ -43,6 +43,7 @@
43
43
  "./package.json": "./package.json"
44
44
  },
45
45
  "dependencies": {
46
+ "@digitalcredentials/bnid": "^2.1.1",
46
47
  "@digitalcredentials/did-io": "^1.0.2",
47
48
  "@digitalcredentials/http-client": "^1.2.2",
48
49
  "did-context": "^3.1.1",
@@ -61,8 +62,8 @@
61
62
  "chai": "^4.3.4",
62
63
  "cross-env": "^7.0.3",
63
64
  "crypto-ld": "^6.0.0",
64
- "esm": "^3.2.25",
65
65
  "dirty-chai": "^2.0.1",
66
+ "esm": "^3.2.25",
66
67
  "karma": "^6.3.9",
67
68
  "karma-babel-preprocessor": "^8.0.1",
68
69
  "karma-chai": "^0.1.0",
@@ -73,10 +74,10 @@
73
74
  "karma-webpack": "^5.0.0",
74
75
  "mocha": "^8.4.0",
75
76
  "nyc": "^15.1.0",
76
- "sinon": "^12.0.1",
77
- "standard": "^16.0.4",
78
77
  "rimraf": "^3.0.2",
79
78
  "rollup": "^2.62.0",
79
+ "sinon": "^12.0.1",
80
+ "standard": "^16.0.4",
80
81
  "webpack": "^5.65.0"
81
82
  },
82
83
  "nyc": {
@@ -3,6 +3,7 @@ import * as didIo from '@digitalcredentials/did-io'
3
3
  import ed25519Context from 'ed25519-signature-2020-context'
4
4
  import x25519Context from 'x25519-key-agreement-2020-context'
5
5
  import didContext from 'did-context'
6
+ import { decodeSecretKeySeed } from '@digitalcredentials/bnid'
6
7
 
7
8
  const { VERIFICATION_RELATIONSHIPS } = didIo
8
9
 
@@ -103,7 +104,7 @@ export function urlFromDid ({ did } = {}) {
103
104
  * DID Document initialized with keys, as well as the map of the corresponding
104
105
  * key pairs (by key id).
105
106
  */
106
- export async function initKeys ({ didDocument, cryptoLd, keyMap = {} } = {}) {
107
+ export async function initKeys ({ didDocument, cryptoLd, keyMap } = {}) {
107
108
  const doc = { ...didDocument }
108
109
  if (!doc.id) {
109
110
  throw new TypeError(
@@ -167,7 +168,7 @@ export class DidWebResolver {
167
168
  * @param [id] {string} - A did:web DID. If absent, will be converted from url
168
169
  * @param [url] {string}
169
170
  *
170
- * @param [keyMap=DEFAULT_KEY_MAP] {object} A hashmap of key types by purpose.
171
+ * @param [keyMap] {object} A hashmap of key types by purpose.
171
172
  *
172
173
  * @parma [cryptoLd] {object} CryptoLD instance with support for supported
173
174
  * crypto suites installed.
@@ -177,9 +178,27 @@ export class DidWebResolver {
177
178
  * with the corresponding key pairs used to generate it (for storage in a
178
179
  * KMS).
179
180
  */
180
- async generate ({ id, url, keyMap = this.keyMap, cryptoLd = this.cryptoLd } = {}) {
181
+ async generate ({ id, url, seed, keyMap, cryptoLd = this.cryptoLd } = {}) {
182
+ if (!id && !url) {
183
+ throw new TypeError('A "url" or an "id" parameter is required.')
184
+ }
185
+ if (seed && keyMap) {
186
+ throw new TypeError(
187
+ 'Either a "seed" or a "keyMap" param must be provided, but not both.'
188
+ )
189
+ }
190
+
181
191
  const did = id || didFromUrl({ url })
182
192
 
193
+ if (seed) {
194
+ const keyPair = await _keyPairFromSecretSeed({
195
+ seed, controller: did, cryptoLd
196
+ })
197
+ keyMap = { assertionMethod: keyPair }
198
+ } else {
199
+ keyMap = keyMap || this.keyMap
200
+ }
201
+
183
202
  // Compose the DID Document
184
203
  let didDocument = {
185
204
  '@context': [
@@ -300,3 +319,27 @@ export class DidWebResolver {
300
319
  return method
301
320
  }
302
321
  }
322
+
323
+ /**
324
+ * @param options {object}
325
+ * @param options.seed {string|Uint8Array}
326
+ * @param controller {string}
327
+ * @param cryptoLd {object}
328
+ *
329
+ * @return {Promise<LDKeyPair>}
330
+ */
331
+ async function _keyPairFromSecretSeed ({ seed, controller, cryptoLd } = {}) {
332
+ let seedBytes
333
+ if (typeof seed === 'string') {
334
+ // Currently only supports base58 multibase / identity multihash encoding.
335
+ if (!seed.startsWith('z1A')) {
336
+ throw new TypeError('"seed" parameter must be a multibase/multihash encoded string, or a Uint8Array.')
337
+ }
338
+ seedBytes = decodeSecretKeySeed({ secretKeySeed: seed })
339
+ } else {
340
+ seedBytes = new Uint8Array(seed)
341
+ }
342
+ return cryptoLd.generate({
343
+ controller, seed: seedBytes, type: 'Ed25519VerificationKey2020'
344
+ })
345
+ }