bsv-bap 0.0.1 → 0.0.2

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.
Files changed (68) hide show
  1. package/dist/{src/constants.d.ts → constants.d.ts} +2 -2
  2. package/dist/{src/id.d.ts → id.d.ts} +8 -22
  3. package/dist/index.cjs +2 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/{src/index.d.ts → index.d.ts} +16 -11
  6. package/dist/index.modern.js +2 -0
  7. package/dist/index.modern.js.map +1 -0
  8. package/dist/index.module.js +2 -0
  9. package/dist/index.module.js.map +1 -0
  10. package/dist/index.umd.js +2 -0
  11. package/dist/index.umd.js.map +1 -0
  12. package/dist/{src/interface.d.ts → interface.d.ts} +8 -4
  13. package/dist/{src/poa.d.ts → poa.d.ts} +1 -1
  14. package/dist/{src/utils.d.ts → utils.d.ts} +0 -1
  15. package/package.json +30 -57
  16. package/.babelrc +0 -20
  17. package/.eslintrc +0 -46
  18. package/babel.config.js +0 -6
  19. package/bun.lockb +0 -0
  20. package/coverage/clover.xml +0 -6
  21. package/coverage/coverage-final.json +0 -1
  22. package/coverage/lcov-report/base.css +0 -224
  23. package/coverage/lcov-report/block-navigation.js +0 -87
  24. package/coverage/lcov-report/favicon.png +0 -0
  25. package/coverage/lcov-report/index.html +0 -101
  26. package/coverage/lcov-report/prettify.css +0 -1
  27. package/coverage/lcov-report/prettify.js +0 -2
  28. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  29. package/coverage/lcov-report/sorter.js +0 -196
  30. package/coverage/lcov-report/src/constants.ts.html +0 -113
  31. package/coverage/lcov-report/src/id.ts.html +0 -2207
  32. package/coverage/lcov-report/src/index.html +0 -156
  33. package/coverage/lcov-report/src/index.ts.html +0 -1877
  34. package/coverage/lcov-report/src/utils.ts.html +0 -404
  35. package/coverage/lcov-report/tests/data/index.html +0 -111
  36. package/coverage/lcov-report/tests/data/keys.js.html +0 -86
  37. package/coverage/lcov.info +0 -0
  38. package/dist/jest.config.d.ts +0 -8
  39. package/dist/typescript-npm-package.cjs.d.ts +0 -554
  40. package/dist/typescript-npm-package.cjs.js +0 -1320
  41. package/dist/typescript-npm-package.cjs.js.map +0 -1
  42. package/dist/typescript-npm-package.esm.d.ts +0 -554
  43. package/dist/typescript-npm-package.esm.js +0 -1312
  44. package/dist/typescript-npm-package.esm.js.map +0 -1
  45. package/dist/typescript-npm-package.umd.d.ts +0 -554
  46. package/dist/typescript-npm-package.umd.js +0 -110193
  47. package/dist/typescript-npm-package.umd.js.map +0 -1
  48. package/jest.config.ts +0 -196
  49. package/jsdoc.json +0 -16
  50. package/rollup.config.js +0 -64
  51. package/setup-jest.js +0 -1
  52. package/src/README.md +0 -80
  53. package/src/attributes.json +0 -119
  54. package/src/constants.ts +0 -11
  55. package/src/id.ts +0 -783
  56. package/src/index.ts +0 -631
  57. package/src/interface.ts +0 -26
  58. package/src/poa.ts +0 -9
  59. package/src/utils.ts +0 -111
  60. package/tests/data/ids.json +0 -30
  61. package/tests/data/keys.js +0 -2
  62. package/tests/data/old-ids.json +0 -25
  63. package/tests/data/test-vectors.json +0 -122
  64. package/tests/id.test.js +0 -286
  65. package/tests/index.test.js +0 -335
  66. package/tests/regression.test.js +0 -28
  67. package/tests/utils.test.js +0 -27
  68. package/tsconfig.json +0 -17
@@ -1,1320 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var sdk = require('@bsv/sdk');
6
- require('node-fetch');
7
- var randomBytes = require('randombytes');
8
-
9
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
-
11
- var randomBytes__default = /*#__PURE__*/_interopDefaultLegacy(randomBytes);
12
-
13
- /******************************************************************************
14
- Copyright (c) Microsoft Corporation.
15
-
16
- Permission to use, copy, modify, and/or distribute this software for any
17
- purpose with or without fee is hereby granted.
18
-
19
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
22
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
23
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
24
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
25
- PERFORMANCE OF THIS SOFTWARE.
26
- ***************************************************************************** */
27
-
28
- function __awaiter(thisArg, _arguments, P, generator) {
29
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
30
- return new (P || (P = Promise))(function (resolve, reject) {
31
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
32
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
33
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
34
- step((generator = generator.apply(thisArg, _arguments || [])).next());
35
- });
36
- }
37
-
38
- function __classPrivateFieldGet(receiver, state, kind, f) {
39
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
40
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
41
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
42
- }
43
-
44
- function __classPrivateFieldSet(receiver, state, value, kind, f) {
45
- if (kind === "m") throw new TypeError("Private method is not writable");
46
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
47
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
48
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
49
- }
50
-
51
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
52
- var e = new Error(message);
53
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
54
- };
55
-
56
- const Utils = {
57
- /**
58
- * Helper function for encoding strings to hex
59
- *
60
- * @param string
61
- * @returns {string}
62
- */
63
- hexEncode(string) {
64
- return `0x${Buffer.from(string).toString('hex')}`;
65
- },
66
- /**
67
- * Helper function for encoding strings to hex
68
- *
69
- * @param hexString string
70
- * @param encoding BufferEncoding
71
- * @returns {string}
72
- */
73
- hexDecode(hexString, encoding = 'utf8') {
74
- return Buffer.from(hexString.replace('0x', ''), 'hex').toString(encoding);
75
- },
76
- /**
77
- * Helper function to generate a random nonce
78
- *
79
- * @returns {string}
80
- */
81
- getRandomString(length = 32) {
82
- return randomBytes__default["default"](length).toString('hex');
83
- },
84
- /**
85
- * Test whether the given string is hex
86
- *
87
- * @param value any
88
- * @returns {boolean}
89
- */
90
- isHex(value) {
91
- if (typeof value !== 'string') {
92
- return false;
93
- }
94
- return /^[0-9a-fA-F]+$/.test(value);
95
- },
96
- /**
97
- * Get a signing path from a hex number
98
- *
99
- * @param hexString {string}
100
- * @param hardened {boolean} Whether to return a hardened path
101
- * @returns {string}
102
- */
103
- getSigningPathFromHex(hexString, hardened = true) {
104
- // "m/0/0/1"
105
- let signingPath = 'm';
106
- const signingHex = hexString.match(/.{1,8}/g);
107
- if (!signingHex) {
108
- throw new Error('Invalid hex string');
109
- }
110
- const maxNumber = 2147483648 - 1; // 0x80000000
111
- for (const hexNumber of signingHex) {
112
- let number = Number(`0x${hexNumber}`);
113
- if (number > maxNumber)
114
- number -= maxNumber;
115
- signingPath += `/${number}${(hardened ? "'" : '')}`;
116
- }
117
- return signingPath;
118
- },
119
- /**
120
- * Increment that second to last part from the given part, set the last part to 0
121
- *
122
- * @param path string
123
- * @returns {*}
124
- */
125
- getNextIdentityPath(path) {
126
- const pathValues = path.split('/');
127
- const secondToLastPart = pathValues[pathValues.length - 2];
128
- let hardened = false;
129
- if (secondToLastPart.match('\'')) {
130
- hardened = true;
131
- }
132
- const nextPath = (Number(secondToLastPart.replace(/[^0-9]/g, '')) + 1).toString();
133
- pathValues[pathValues.length - 2] = nextPath + (hardened ? '\'' : '');
134
- pathValues[pathValues.length - 1] = `0${hardened ? '\'' : ''}`;
135
- return pathValues.join('/');
136
- },
137
- /**
138
- * Increment that last part of the given path
139
- *
140
- * @param path string
141
- * @returns {*}
142
- */
143
- getNextPath(path) {
144
- const pathValues = path.split('/');
145
- const lastPart = pathValues[pathValues.length - 1];
146
- let hardened = false;
147
- if (lastPart.match('\'')) {
148
- hardened = true;
149
- }
150
- const nextPath = (Number(lastPart.replace(/[^0-9]/g, '')) + 1).toString();
151
- pathValues[pathValues.length - 1] = nextPath + (hardened ? '\'' : '');
152
- return pathValues.join('/');
153
- },
154
- };
155
-
156
- const BAP_BITCOM_ADDRESS = '1BAPSuaPnfGnSBM3GLV9yhxUdYe4vGbdMT';
157
- const BAP_BITCOM_ADDRESS_HEX = `0x${Buffer.from(BAP_BITCOM_ADDRESS).toString('hex')}`;
158
- const AIP_BITCOM_ADDRESS = '15PciHG22SNLQJXMoSUaWVi7WSqc7hCfva';
159
- `0x${Buffer.from(AIP_BITCOM_ADDRESS).toString('hex')}`;
160
- const BAP_SERVER = 'https://bap.network/api/v1';
161
- const MAX_INT = 2147483648 - 1; // 0x80000000
162
- // This is just a choice for this library and could be anything else if so needed/wanted
163
- // but it is advisable to use the same derivation between libraries for compatibility
164
- const SIGNING_PATH_PREFIX = 'm/424150\'/0\'/0\''; // BAP in hex
165
- const ENCRYPTION_PATH = `m/424150'/${MAX_INT}'/${MAX_INT}'`;
166
-
167
- var _BAP_ID_HDPrivateKey, _BAP_ID_BAP_SERVER, _BAP_ID_BAP_TOKEN, _BAP_ID_rootPath, _BAP_ID_previousPath, _BAP_ID_currentPath, _BAP_ID_idSeed;
168
- const { toArray: toArray$1, toHex, toBase58, toUTF8: toUTF8$1, toBase64: toBase64$1 } = sdk.Utils;
169
- const { bitcoreDecrypt: bitcoreDecrypt$1, bitcoreEncrypt: bitcoreEncrypt$1 } = sdk.ECIES;
170
- /**
171
- * BAP_ID class
172
- *
173
- * This class should be used in conjunction with the BAP class
174
- *
175
- * @type {BAP_ID}
176
- */
177
- class BAP_ID {
178
- constructor(HDPrivateKey, identityAttributes = {}, idSeed = "") {
179
- _BAP_ID_HDPrivateKey.set(this, void 0);
180
- _BAP_ID_BAP_SERVER.set(this, BAP_SERVER);
181
- _BAP_ID_BAP_TOKEN.set(this, "");
182
- _BAP_ID_rootPath.set(this, void 0);
183
- _BAP_ID_previousPath.set(this, void 0);
184
- _BAP_ID_currentPath.set(this, void 0);
185
- _BAP_ID_idSeed.set(this, void 0);
186
- __classPrivateFieldSet(this, _BAP_ID_idSeed, idSeed, "f");
187
- if (idSeed) {
188
- // create a new HDPrivateKey based on the seed
189
- const seedHex = toHex(sdk.Hash.sha256(idSeed, "utf8"));
190
- const seedPath = Utils.getSigningPathFromHex(seedHex);
191
- __classPrivateFieldSet(this, _BAP_ID_HDPrivateKey, HDPrivateKey.derive(seedPath), "f");
192
- }
193
- else {
194
- __classPrivateFieldSet(this, _BAP_ID_HDPrivateKey, HDPrivateKey, "f");
195
- }
196
- this.idName = "ID 1";
197
- this.description = "";
198
- __classPrivateFieldSet(this, _BAP_ID_rootPath, `${SIGNING_PATH_PREFIX}/0/0/0`, "f");
199
- __classPrivateFieldSet(this, _BAP_ID_previousPath, `${SIGNING_PATH_PREFIX}/0/0/0`, "f");
200
- __classPrivateFieldSet(this, _BAP_ID_currentPath, `${SIGNING_PATH_PREFIX}/0/0/1`, "f");
201
- const rootChild = __classPrivateFieldGet(this, _BAP_ID_HDPrivateKey, "f").derive(__classPrivateFieldGet(this, _BAP_ID_rootPath, "f"));
202
- this.rootAddress = rootChild.privKey.toPublicKey().toAddress();
203
- this.identityKey = this.deriveIdentityKey(this.rootAddress);
204
- // unlink the object
205
- identityAttributes = Object.assign({}, identityAttributes);
206
- this.identityAttributes = this.parseAttributes(identityAttributes);
207
- }
208
- set BAP_SERVER(bapServer) {
209
- __classPrivateFieldSet(this, _BAP_ID_BAP_SERVER, bapServer, "f");
210
- }
211
- get BAP_SERVER() {
212
- return __classPrivateFieldGet(this, _BAP_ID_BAP_SERVER, "f");
213
- }
214
- set BAP_TOKEN(token) {
215
- __classPrivateFieldSet(this, _BAP_ID_BAP_TOKEN, token, "f");
216
- }
217
- get BAP_TOKEN() {
218
- return __classPrivateFieldGet(this, _BAP_ID_BAP_TOKEN, "f");
219
- }
220
- deriveIdentityKey(address) {
221
- // base58( ripemd160 ( sha256 ( rootAddress ) ) )
222
- const rootAddressHash = toHex(sdk.Hash.sha256(address, "utf8"));
223
- return toBase58(sdk.Hash.ripemd160(rootAddressHash, "hex"));
224
- }
225
- /**
226
- * Helper function to parse identity attributes
227
- *
228
- * @param identityAttributes
229
- * @returns {{}}
230
- */
231
- parseAttributes(identityAttributes) {
232
- if (typeof identityAttributes === "string") {
233
- return this.parseStringUrns(identityAttributes);
234
- }
235
- for (const key in identityAttributes) {
236
- if (!identityAttributes[key].value || !identityAttributes[key].nonce) {
237
- throw new Error("Invalid identity attribute");
238
- }
239
- }
240
- return identityAttributes || {};
241
- }
242
- /**
243
- * Parse a text of urn string into identity attributes
244
- *
245
- * urn:bap:id:name:John Doe:e2c6fb4063cc04af58935737eaffc938011dff546d47b7fbb18ed346f8c4d4fa
246
- * urn:bap:id:birthday:1990-05-22:e61f23cbbb2284842d77965e2b0e32f0ca890b1894ca4ce652831347ee3596d9
247
- * urn:bap:id:over18:1:480ca17ccaacd671b28dc811332525f2f2cd594d8e8e7825de515ce5d52d30e8
248
- *
249
- * @param urnIdentityAttributes
250
- */
251
- parseStringUrns(urnIdentityAttributes) {
252
- const identityAttributes = {};
253
- // avoid forEach
254
- const attributesRaw = urnIdentityAttributes
255
- .replace(/^\s+/g, "")
256
- .replace(/\r/gm, "")
257
- .split("\n");
258
- for (const line of attributesRaw) {
259
- // remove any whitespace from the string (trim)
260
- const attribute = line.replace(/^\s+/g, "").replace(/\s+$/g, "");
261
- const urn = attribute.split(":");
262
- if (urn[0] === "urn" &&
263
- urn[1] === "bap" &&
264
- urn[2] === "id" &&
265
- urn[3] &&
266
- urn[4] &&
267
- urn[5]) {
268
- identityAttributes[urn[3]] = {
269
- value: urn[4],
270
- nonce: urn[5],
271
- };
272
- }
273
- }
274
- return identityAttributes;
275
- }
276
- /**
277
- * Returns the identity key
278
- *
279
- * @returns {*|string}
280
- */
281
- getIdentityKey() {
282
- return this.identityKey;
283
- }
284
- /**
285
- * Returns all the attributes in the identity
286
- *
287
- * @returns {*}
288
- */
289
- getAttributes() {
290
- return this.identityAttributes;
291
- }
292
- /**
293
- * Get the value of the given attribute
294
- *
295
- * @param attributeName
296
- * @returns {{}|null}
297
- */
298
- getAttribute(attributeName) {
299
- if (this.identityAttributes[attributeName]) {
300
- return this.identityAttributes[attributeName];
301
- }
302
- return null;
303
- }
304
- /**
305
- * Set the value of the given attribute
306
- *
307
- * If an empty value ('' || null || false) is given, the attribute is removed from the ID
308
- *
309
- * @param attributeName string
310
- * @param attributeValue any
311
- * @returns {{}|null}
312
- */
313
- setAttribute(attributeName, attributeValue) {
314
- if (attributeValue) {
315
- if (this.identityAttributes[attributeName]) {
316
- this.identityAttributes[attributeName].value = attributeValue;
317
- }
318
- else {
319
- this.addAttribute(attributeName, attributeValue);
320
- }
321
- }
322
- }
323
- /**
324
- * Unset the given attribute from the ID
325
- *
326
- * @param attributeName
327
- * @returns {{}|null}
328
- */
329
- unsetAttribute(attributeName) {
330
- delete this.identityAttributes[attributeName];
331
- }
332
- /**
333
- * Get all attribute urn's for this id
334
- *
335
- * @returns {string}
336
- */
337
- getAttributeUrns() {
338
- let urns = "";
339
- for (const key in this.identityAttributes) {
340
- const urn = this.getAttributeUrn(key);
341
- if (urn) {
342
- urns += `${urn}\n`;
343
- }
344
- }
345
- return urns;
346
- }
347
- /**
348
- * Create an return the attribute urn for the given attribute
349
- *
350
- * @param attributeName
351
- * @returns {string|null}
352
- */
353
- getAttributeUrn(attributeName) {
354
- const attribute = this.identityAttributes[attributeName];
355
- if (attribute) {
356
- return `urn:bap:id:${attributeName}:${attribute.value}:${attribute.nonce}`;
357
- }
358
- return null;
359
- }
360
- /**
361
- * Add an attribute to this identity
362
- *
363
- * @param attributeName
364
- * @param value
365
- * @param nonce
366
- */
367
- addAttribute(attributeName, value, nonce = "") {
368
- if (!nonce) {
369
- nonce = Utils.getRandomString();
370
- }
371
- this.identityAttributes[attributeName] = {
372
- value,
373
- nonce,
374
- };
375
- }
376
- /**
377
- * This should be called with the last part of the signing path (/.../.../...)
378
- * This library assumes the first part is m/424150'/0'/0' as defined at the top of this file
379
- *
380
- * @param path The second path of the signing path in the format [0-9]{0,9}/[0-9]{0,9}/[0-9]{0,9}
381
- */
382
- set rootPath(path) {
383
- if (__classPrivateFieldGet(this, _BAP_ID_HDPrivateKey, "f")) {
384
- if (path.split("/").length < 5) {
385
- path = `${SIGNING_PATH_PREFIX}${path}`;
386
- }
387
- if (!this.validatePath(path)) {
388
- throw new Error(`invalid signing path given ${path}`);
389
- }
390
- __classPrivateFieldSet(this, _BAP_ID_rootPath, path, "f");
391
- const derivedChild = __classPrivateFieldGet(this, _BAP_ID_HDPrivateKey, "f").derive(path);
392
- this.rootAddress = derivedChild.pubKey.toAddress();
393
- // Identity keys should be derivatives of the root address - this allows checking
394
- // of the creation transaction
395
- this.identityKey = this.deriveIdentityKey(this.rootAddress);
396
- // we also set this previousPath / currentPath to the root as we seem to be (re)setting this ID
397
- __classPrivateFieldSet(this, _BAP_ID_previousPath, path, "f");
398
- __classPrivateFieldSet(this, _BAP_ID_currentPath, path, "f");
399
- }
400
- }
401
- get rootPath() {
402
- return __classPrivateFieldGet(this, _BAP_ID_rootPath, "f");
403
- }
404
- getRootPath() {
405
- return __classPrivateFieldGet(this, _BAP_ID_rootPath, "f");
406
- }
407
- /**
408
- * This should be called with the last part of the signing path (/.../.../...)
409
- * This library assumes the first part is m/424150'/0'/0' as defined at the top of this file
410
- *
411
- * @param path The second path of the signing path in the format [0-9]{0,9}/[0-9]{0,9}/[0-9]{0,9}
412
- */
413
- set currentPath(path) {
414
- if (path.split("/").length < 5) {
415
- path = `${SIGNING_PATH_PREFIX}${path}`;
416
- }
417
- if (!this.validatePath(path)) {
418
- throw new Error("invalid signing path given");
419
- }
420
- __classPrivateFieldSet(this, _BAP_ID_previousPath, __classPrivateFieldGet(this, _BAP_ID_currentPath, "f"), "f");
421
- __classPrivateFieldSet(this, _BAP_ID_currentPath, path, "f");
422
- }
423
- get currentPath() {
424
- return __classPrivateFieldGet(this, _BAP_ID_currentPath, "f");
425
- }
426
- get previousPath() {
427
- return __classPrivateFieldGet(this, _BAP_ID_previousPath, "f");
428
- }
429
- /**
430
- * This can be used to break the deterministic way child keys are created to make it harder for
431
- * an attacker to steal the identites when the root key is compromised. This does however require
432
- * the seeds to be stored at all times. If the seed is lost, the identity will not be recoverable.
433
- */
434
- get idSeed() {
435
- return __classPrivateFieldGet(this, _BAP_ID_idSeed, "f");
436
- }
437
- /**
438
- * Increment current path to a new path
439
- *
440
- * @returns {*}
441
- */
442
- incrementPath() {
443
- this.currentPath = Utils.getNextPath(this.currentPath);
444
- }
445
- /**
446
- * Check whether the given path is a valid path for use with this class
447
- * The signing paths used here always have a length of 3
448
- *
449
- * @param path The last part of the signing path (example "/0/0/1")
450
- * @returns {boolean}
451
- */
452
- validatePath(path) {
453
- /* eslint-disable max-len */
454
- if (path.match(/\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?\/[0-9]{1,10}'?/)) {
455
- const pathValues = path.split("/");
456
- if (pathValues.length === 7 &&
457
- Number(pathValues[1].replace("'", "")) <= MAX_INT &&
458
- Number(pathValues[2].replace("'", "")) <= MAX_INT &&
459
- Number(pathValues[3].replace("'", "")) <= MAX_INT &&
460
- Number(pathValues[4].replace("'", "")) <= MAX_INT &&
461
- Number(pathValues[5].replace("'", "")) <= MAX_INT &&
462
- Number(pathValues[6].replace("'", "")) <= MAX_INT) {
463
- return true;
464
- }
465
- }
466
- return false;
467
- }
468
- /**
469
- * Get the OP_RETURN for the initial ID transaction (signed with root address)
470
- *
471
- * @returns {[]}
472
- */
473
- getInitialIdTransaction() {
474
- return this.getIdTransaction(__classPrivateFieldGet(this, _BAP_ID_rootPath, "f"));
475
- }
476
- /**
477
- * Get the OP_RETURN for the ID transaction of the current address / path
478
- *
479
- * @returns {[]}
480
- */
481
- getIdTransaction(previousPath = "") {
482
- if (__classPrivateFieldGet(this, _BAP_ID_currentPath, "f") === __classPrivateFieldGet(this, _BAP_ID_rootPath, "f")) {
483
- throw new Error("Current path equals rootPath. ID was probably not initialized properly");
484
- }
485
- const opReturn = [
486
- Buffer.from(BAP_BITCOM_ADDRESS).toString("hex"),
487
- Buffer.from("ID").toString("hex"),
488
- Buffer.from(this.identityKey).toString("hex"),
489
- Buffer.from(this.getCurrentAddress()).toString("hex"),
490
- ];
491
- previousPath = previousPath || __classPrivateFieldGet(this, _BAP_ID_previousPath, "f");
492
- return this.signOpReturnWithAIP(opReturn, previousPath);
493
- }
494
- /**
495
- * Get address for given path
496
- *
497
- * @param path
498
- * @returns {*}
499
- */
500
- getAddress(path) {
501
- const derivedChild = __classPrivateFieldGet(this, _BAP_ID_HDPrivateKey, "f").derive(path);
502
- return derivedChild.privKey.toPublicKey().toAddress();
503
- }
504
- /**
505
- * Get current signing address
506
- *
507
- * @returns {*}
508
- */
509
- getCurrentAddress() {
510
- return this.getAddress(__classPrivateFieldGet(this, _BAP_ID_currentPath, "f"));
511
- }
512
- /**
513
- * Get the public key for encrypting data for this identity
514
- */
515
- getEncryptionPublicKey() {
516
- const HDPrivateKey = __classPrivateFieldGet(this, _BAP_ID_HDPrivateKey, "f").derive(__classPrivateFieldGet(this, _BAP_ID_rootPath, "f"));
517
- const encryptionKey = HDPrivateKey.derive(ENCRYPTION_PATH).privKey;
518
- // @ts-ignore
519
- return encryptionKey.toPublicKey().toString();
520
- }
521
- /**
522
- * Get the public key for encrypting data for this identity, using a seed for the encryption
523
- */
524
- getEncryptionPublicKeyWithSeed(seed) {
525
- const encryptionKey = this.getEncryptionPrivateKeyWithSeed(seed);
526
- // @ts-ignore
527
- return encryptionKey.toPublicKey().toString("hex");
528
- }
529
- /**
530
- * Encrypt the given string data with the identity encryption key
531
- * @param stringData
532
- * @param counterPartyPublicKey Optional public key of the counterparty
533
- * @return string Base64
534
- */
535
- encrypt(stringData, counterPartyPublicKey) {
536
- const HDPrivateKey = __classPrivateFieldGet(this, _BAP_ID_HDPrivateKey, "f").derive(__classPrivateFieldGet(this, _BAP_ID_rootPath, "f"));
537
- const encryptionKey = HDPrivateKey.derive(ENCRYPTION_PATH).privKey;
538
- const publicKey = encryptionKey.toPublicKey();
539
- const pubKey = counterPartyPublicKey
540
- ? sdk.PublicKey.fromString(counterPartyPublicKey)
541
- : publicKey;
542
- return toBase64$1(bitcoreEncrypt$1(toArray$1(stringData), pubKey));
543
- }
544
- /**
545
- * Decrypt the given ciphertext with the identity encryption key
546
- * @param ciphertext
547
- * @param counterPartyPublicKey Optional public key of the counterparty
548
- */
549
- decrypt(ciphertext, counterPartyPublicKey) {
550
- const HDPrivateKey = __classPrivateFieldGet(this, _BAP_ID_HDPrivateKey, "f").derive(__classPrivateFieldGet(this, _BAP_ID_rootPath, "f"));
551
- const encryptionKey = HDPrivateKey.derive(ENCRYPTION_PATH).privKey;
552
- // const ecies = new ECIES();
553
- // if (counterPartyPublicKey) {
554
- // return toUTF8(bitcoreDecrypt(toArray(Buffer.from(ciphertext, 'base64'), 'base64'), encryptionKey))
555
- // }
556
- // TODO: It seems the counterPartyPublicKey is not being used here
557
- return toUTF8$1(bitcoreDecrypt$1(toArray$1(Buffer.from(ciphertext, "base64"), "base64"), encryptionKey));
558
- // ecies.privateKey(encryptionKey);
559
- // if (counterPartyPublicKey) {
560
- // ecies.publicKey(counterPartyPublicKey);
561
- // }
562
- // return ecies.decrypt(Buffer.from(ciphertext, 'base64')).toString();
563
- }
564
- /**
565
- * Encrypt the given string data with the identity encryption key
566
- * @param stringData
567
- * @param seed String seed
568
- * @param counterPartyPublicKey Optional public key of the counterparty
569
- * @return string Base64
570
- */
571
- encryptWithSeed(stringData, seed, counterPartyPublicKey) {
572
- const encryptionKey = this.getEncryptionPrivateKeyWithSeed(seed);
573
- const publicKey = encryptionKey.toPublicKey();
574
- // const ecies = new ECIES();
575
- if (counterPartyPublicKey) {
576
- // ecies.privateKey(encryptionKey);
577
- // ecies.publicKey(counterPartyPublicKey);
578
- return toBase64$1(bitcoreEncrypt$1(toArray$1(stringData), sdk.PublicKey.fromString(counterPartyPublicKey)));
579
- }
580
- // ecies.publicKey(publicKey);
581
- return toBase64$1(bitcoreEncrypt$1(toArray$1(stringData), publicKey));
582
- // return ecies.encrypt(stringData).toString('base64');
583
- }
584
- /**
585
- * Decrypt the given ciphertext with the identity encryption key
586
- * @param ciphertext
587
- * @param seed String seed
588
- * @param counterPartyPublicKey Public key of the counterparty
589
- */
590
- decryptWithSeed(ciphertext, seed, counterPartyPublicKey) {
591
- const encryptionKey = this.getEncryptionPrivateKeyWithSeed(seed);
592
- // const ecies = new ECIES();
593
- // ecies.privateKey(encryptionKey);
594
- // if (counterPartyPublicKey) {
595
- // ecies.publicKey(counterPartyPublicKey);
596
- // TODOL: It seems the counterPartyPublicKey is not being used here
597
- return toUTF8$1(bitcoreDecrypt$1(toArray$1(Buffer.from(ciphertext, "base64"), "base64"), encryptionKey));
598
- // }
599
- // return ecies.decrypt(Buffer.from(ciphertext, 'base64')).toString();
600
- }
601
- getEncryptionPrivateKeyWithSeed(seed) {
602
- const pathHex = toHex(sdk.Hash.sha256(seed, "utf8"));
603
- const path = Utils.getSigningPathFromHex(pathHex);
604
- const HDPrivateKey = __classPrivateFieldGet(this, _BAP_ID_HDPrivateKey, "f").derive(__classPrivateFieldGet(this, _BAP_ID_rootPath, "f"));
605
- return HDPrivateKey.derive(path).privKey;
606
- }
607
- /**
608
- * Get an attestation string for the given urn for this identity
609
- *
610
- * @param urn
611
- * @returns {string}
612
- */
613
- getAttestation(urn) {
614
- const urnHash = sdk.Hash.sha256(urn, "utf8");
615
- return `bap:attest:${toHex(urnHash)}:${this.getIdentityKey()}`;
616
- }
617
- /**
618
- * Generate and return the attestation hash for the given attribute of this identity
619
- *
620
- * @param attribute Attribute name (name, email etc.)
621
- * @returns {string}
622
- */
623
- getAttestationHash(attribute) {
624
- const urn = this.getAttributeUrn(attribute);
625
- if (!urn)
626
- return null;
627
- const attestation = this.getAttestation(urn);
628
- const attestationHash = sdk.Hash.sha256(attestation, "utf8");
629
- return toHex(attestationHash);
630
- }
631
- /**
632
- * Sign a message with the current signing address of this identity
633
- *
634
- * @param message
635
- * @param signingPath
636
- * @returns {{address, signature}}
637
- */
638
- signMessage(message, signingPath = "") {
639
- let msg;
640
- if (!(message instanceof Buffer)) {
641
- msg = Buffer.from(message);
642
- }
643
- else {
644
- msg = message;
645
- }
646
- signingPath = signingPath || __classPrivateFieldGet(this, _BAP_ID_currentPath, "f");
647
- const childPk = __classPrivateFieldGet(this, _BAP_ID_HDPrivateKey, "f").derive(signingPath).privKey;
648
- const address = childPk.toAddress();
649
- const signature = sdk.BSM.sign(toArray$1(msg), childPk).toCompact(0, true, "base64");
650
- return { address, signature };
651
- }
652
- /**
653
- * Sign a message using a key based on the given string seed
654
- *
655
- * This works by creating a private key from the root key of this identity. It will always
656
- * work with the rootPath / rootKey, to be deterministic. It will not change even if the keys
657
- * are rotated for this ID.
658
- *
659
- * This is used in for instance deterministic login systems, that do not support BAP.
660
- *
661
- * @param message
662
- * @param seed {string} String seed that will be used to generate a path
663
- */
664
- signMessageWithSeed(message, seed) {
665
- const pathHex = toHex(sdk.Hash.sha256(seed, "utf8"));
666
- const path = Utils.getSigningPathFromHex(pathHex);
667
- const HDPrivateKey = __classPrivateFieldGet(this, _BAP_ID_HDPrivateKey, "f").derive(__classPrivateFieldGet(this, _BAP_ID_rootPath, "f"));
668
- const derivedChild = HDPrivateKey.derive(path);
669
- const address = derivedChild.privKey.toPublicKey().toAddress();
670
- const signature = sdk.BSM.sign(toArray$1(Buffer.from(message)), derivedChild.privKey).toCompact(0, true, "base64");
671
- return { address, signature };
672
- }
673
- /**
674
- * Sign an op_return hex array with AIP
675
- * @param opReturn {array}
676
- * @param signingPath {string}
677
- * @param outputType {string}
678
- * @return {[]}
679
- */
680
- signOpReturnWithAIP(opReturn, signingPath = "", outputType = "hex") {
681
- const aipMessageBuffer = this.getAIPMessageBuffer(opReturn);
682
- const { address, signature } = this.signMessage(aipMessageBuffer, signingPath);
683
- return opReturn.concat([
684
- Buffer.from("|").toString(outputType),
685
- Buffer.from(AIP_BITCOM_ADDRESS).toString(outputType),
686
- Buffer.from("BITCOIN_ECDSA").toString(outputType),
687
- Buffer.from(address).toString(outputType),
688
- Buffer.from(signature, "base64").toString(outputType),
689
- ]);
690
- }
691
- /**
692
- * Construct an AIP buffer from the op return data
693
- * @param opReturn
694
- * @returns {Buffer}
695
- */
696
- getAIPMessageBuffer(opReturn) {
697
- const buffers = [];
698
- if (opReturn[0].replace("0x", "") !== "6a") {
699
- // include OP_RETURN in constructing the signature buffer
700
- buffers.push(Buffer.from("6a", "hex"));
701
- }
702
- for (const op of opReturn) {
703
- buffers.push(Buffer.from(op.replace("0x", ""), "hex"));
704
- }
705
- // add a trailing "|" - this is the AIP way
706
- buffers.push(Buffer.from("|"));
707
- return Buffer.concat([...buffers]);
708
- }
709
- /**
710
- * Get all signing keys for this identity
711
- */
712
- getIdSigningKeys() {
713
- return __awaiter(this, void 0, void 0, function* () {
714
- const signingKeys = yield this.getApiData("/signing-keys", {
715
- idKey: this.identityKey,
716
- });
717
- console.log("getIdSigningKeys", signingKeys);
718
- return signingKeys;
719
- });
720
- }
721
- /**
722
- * Get all attestations for the given attribute
723
- *
724
- * @param attribute
725
- */
726
- getAttributeAttestations(attribute) {
727
- return __awaiter(this, void 0, void 0, function* () {
728
- // This function needs to make a call to a BAP server to get all the attestations for this
729
- // identity for the given attribute
730
- const attestationHash = this.getAttestationHash(attribute);
731
- // get all BAP ATTEST records for the given attestationHash
732
- const attestations = yield this.getApiData("/attestations", {
733
- hash: attestationHash,
734
- });
735
- console.log("getAttestations", attribute, attestationHash, attestations);
736
- return attestations;
737
- });
738
- }
739
- /**
740
- * Helper function to get attestation from a BAP API server
741
- *
742
- * @param apiUrl
743
- * @param apiData
744
- * @returns {Promise<any>}
745
- */
746
- getApiData(apiUrl, apiData) {
747
- return __awaiter(this, void 0, void 0, function* () {
748
- const url = `${__classPrivateFieldGet(this, _BAP_ID_BAP_SERVER, "f")}${apiUrl}`;
749
- const response = yield fetch(url, {
750
- method: "post",
751
- headers: {
752
- "Content-type": "application/json; charset=utf-8",
753
- token: __classPrivateFieldGet(this, _BAP_ID_BAP_TOKEN, "f"),
754
- format: "json",
755
- },
756
- body: JSON.stringify(apiData),
757
- });
758
- return response.json();
759
- });
760
- }
761
- /**
762
- * Import an identity from a JSON object
763
- *
764
- * @param identity{{}}
765
- */
766
- import(identity) {
767
- this.idName = identity.name;
768
- this.description = identity.description || "";
769
- this.identityKey = identity.identityKey;
770
- __classPrivateFieldSet(this, _BAP_ID_rootPath, identity.rootPath, "f");
771
- this.rootAddress = identity.rootAddress;
772
- __classPrivateFieldSet(this, _BAP_ID_previousPath, identity.previousPath, "f");
773
- __classPrivateFieldSet(this, _BAP_ID_currentPath, identity.currentPath, "f");
774
- __classPrivateFieldSet(this, _BAP_ID_idSeed, identity.idSeed || "", "f");
775
- this.identityAttributes = this.parseAttributes(identity.identityAttributes);
776
- }
777
- /**
778
- * Export this identity to a JSON object
779
- * @returns {{}}
780
- */
781
- export() {
782
- return {
783
- name: this.idName,
784
- description: this.description,
785
- identityKey: this.identityKey,
786
- rootPath: __classPrivateFieldGet(this, _BAP_ID_rootPath, "f"),
787
- rootAddress: this.rootAddress,
788
- previousPath: __classPrivateFieldGet(this, _BAP_ID_previousPath, "f"),
789
- currentPath: __classPrivateFieldGet(this, _BAP_ID_currentPath, "f"),
790
- idSeed: __classPrivateFieldGet(this, _BAP_ID_idSeed, "f"),
791
- identityAttributes: this.getAttributes(),
792
- lastIdPath: "",
793
- };
794
- }
795
- }
796
- _BAP_ID_HDPrivateKey = new WeakMap(), _BAP_ID_BAP_SERVER = new WeakMap(), _BAP_ID_BAP_TOKEN = new WeakMap(), _BAP_ID_rootPath = new WeakMap(), _BAP_ID_previousPath = new WeakMap(), _BAP_ID_currentPath = new WeakMap(), _BAP_ID_idSeed = new WeakMap();
797
-
798
- var _HDPrivateKey, _ids, _BAP_SERVER, _BAP_TOKEN, _lastIdPath, _a;
799
- const { toArray, toUTF8, toBase64 } = sdk.Utils;
800
- const { bitcoreDecrypt, bitcoreEncrypt } = sdk.ECIES;
801
- /**
802
- * BAP class
803
- *
804
- * Creates an instance of the BAP class and uses the given HDPrivateKey for all BAP operations.
805
- *
806
- * @param HDPrivateKey
807
- */
808
- const BAP = (_a = class {
809
- constructor(HDPrivateKey, token = "") {
810
- _HDPrivateKey.set(this, void 0);
811
- _ids.set(this, {});
812
- _BAP_SERVER.set(this, BAP_SERVER);
813
- _BAP_TOKEN.set(this, "");
814
- _lastIdPath.set(this, "");
815
- if (!HDPrivateKey) {
816
- throw new Error("No HDPrivateKey given");
817
- }
818
- __classPrivateFieldSet(this, _HDPrivateKey, sdk.HD.fromString(HDPrivateKey), "f");
819
- if (token) {
820
- __classPrivateFieldSet(this, _BAP_TOKEN, token, "f");
821
- }
822
- }
823
- get lastIdPath() {
824
- return __classPrivateFieldGet(this, _lastIdPath, "f");
825
- }
826
- /**
827
- * Get the public key of the given childPath, or of the current HDPrivateKey of childPath is empty
828
- *
829
- * @param childPath Full derivation path for this child
830
- * @returns {*}
831
- */
832
- getPublicKey(childPath = "") {
833
- if (childPath) {
834
- return __classPrivateFieldGet(this, _HDPrivateKey, "f").derive(childPath).pubKey.toString();
835
- }
836
- return __classPrivateFieldGet(this, _HDPrivateKey, "f").pubKey.toString();
837
- }
838
- /**
839
- * Get the public key of the given childPath, or of the current HDPrivateKey of childPath is empty
840
- *
841
- * @param childPath Full derivation path for this child
842
- * @returns {*}
843
- */
844
- getHdPublicKey(childPath = "") {
845
- if (childPath) {
846
- return __classPrivateFieldGet(this, _HDPrivateKey, "f").derive(childPath).toPublic().toString();
847
- }
848
- return __classPrivateFieldGet(this, _HDPrivateKey, "f").toPublic().toString();
849
- }
850
- set BAP_SERVER(bapServer) {
851
- __classPrivateFieldSet(this, _BAP_SERVER, bapServer, "f");
852
- Object.keys(__classPrivateFieldGet(this, _ids, "f")).forEach((key) => {
853
- // @ts-ignore - does not recognize private fields that can be set
854
- __classPrivateFieldGet(this, _ids, "f")[key].BAP_SERVER = bapServer;
855
- });
856
- }
857
- get BAP_SERVER() {
858
- return __classPrivateFieldGet(this, _BAP_SERVER, "f");
859
- }
860
- set BAP_TOKEN(token) {
861
- __classPrivateFieldSet(this, _BAP_TOKEN, token, "f");
862
- Object.keys(__classPrivateFieldGet(this, _ids, "f")).forEach((key) => {
863
- // @ts-ignore - does not recognize private fields that can be set
864
- __classPrivateFieldGet(this, _ids, "f")[key].BAP_TOKEN = token;
865
- });
866
- }
867
- get BAP_TOKEN() {
868
- return __classPrivateFieldGet(this, _BAP_TOKEN, "f");
869
- }
870
- /**
871
- * This function verifies that the given bapId matches the given root address
872
- * This is used as a data integrity check
873
- *
874
- * @param bapId BAP_ID instance
875
- */
876
- checkIdBelongs(bapId) {
877
- const derivedChild = __classPrivateFieldGet(this, _HDPrivateKey, "f").derive(bapId.rootPath);
878
- const checkRootAddress = derivedChild.pubKey.toAddress();
879
- if (checkRootAddress !== bapId.rootAddress) {
880
- throw new Error("ID does not belong to this private key");
881
- }
882
- return true;
883
- }
884
- /**
885
- * Returns a list of all the identity keys that are stored in this instance
886
- *
887
- * @returns {string[]}
888
- */
889
- listIds() {
890
- return Object.keys(__classPrivateFieldGet(this, _ids, "f"));
891
- }
892
- /**
893
- * Create a new Id and link it to this BAP instance
894
- *
895
- * This function uses the length of the #ids of this class to determine the next valid path.
896
- * If not all ids related to this HDPrivateKey have been loaded, determine the path externally
897
- * and pass it to newId when creating a new ID.
898
- *
899
- * @param path
900
- * @param identityAttributes
901
- * @param idSeed
902
- * @returns {*}
903
- */
904
- newId(path = "", identityAttributes = {}, idSeed = "") {
905
- if (!path) {
906
- // get next usable path for this key
907
- path = this.getNextValidPath();
908
- }
909
- const newIdentity = new BAP_ID(__classPrivateFieldGet(this, _HDPrivateKey, "f"), identityAttributes, idSeed);
910
- newIdentity.BAP_SERVER = __classPrivateFieldGet(this, _BAP_SERVER, "f");
911
- newIdentity.BAP_TOKEN = __classPrivateFieldGet(this, _BAP_TOKEN, "f");
912
- newIdentity.rootPath = path;
913
- newIdentity.currentPath = Utils.getNextPath(path);
914
- const idKey = newIdentity.getIdentityKey();
915
- __classPrivateFieldGet(this, _ids, "f")[idKey] = newIdentity;
916
- __classPrivateFieldSet(this, _lastIdPath, path, "f");
917
- return __classPrivateFieldGet(this, _ids, "f")[idKey];
918
- }
919
- /**
920
- * Remove identity
921
- *
922
- * @param idKey
923
- * @returns {*}
924
- */
925
- removeId(idKey) {
926
- delete __classPrivateFieldGet(this, _ids, "f")[idKey];
927
- }
928
- /**
929
- * Get the next valid path for the used HDPrivateKey and loaded #ids
930
- *
931
- * @returns {string}
932
- */
933
- getNextValidPath() {
934
- // prefer hardened paths
935
- if (__classPrivateFieldGet(this, _lastIdPath, "f")) {
936
- return Utils.getNextIdentityPath(__classPrivateFieldGet(this, _lastIdPath, "f"));
937
- }
938
- return `/0'/${Object.keys(__classPrivateFieldGet(this, _ids, "f")).length}'/0'`;
939
- }
940
- /**
941
- * Get a certain Id
942
- *
943
- * @param identityKey
944
- * @returns {null}
945
- */
946
- getId(identityKey) {
947
- return __classPrivateFieldGet(this, _ids, "f")[identityKey] || null;
948
- }
949
- /**
950
- * This function is used when manipulating ID's, adding or removing attributes etc
951
- * First create an id through this class and then use getId to get it. Then you can add/edit or
952
- * increment the signing path and then re-set it with this function.
953
- *
954
- * Note: when you getId() from this class, you will be working on the same object as this class
955
- * has and any changes made will be propagated to the id in this class. When you call exportIds
956
- * your new changes will also be included, without having to setId().
957
- *
958
- * @param bapId
959
- */
960
- setId(bapId) {
961
- this.checkIdBelongs(bapId);
962
- __classPrivateFieldGet(this, _ids, "f")[bapId.getIdentityKey()] = bapId;
963
- }
964
- /**
965
- * This function is used to import IDs and attributes from some external storage
966
- *
967
- * The ID information should NOT be stored together with the HD private key !
968
- *
969
- * @param idData Array of ids that have been exported
970
- * @param encrypted Whether the data should be treated as being encrypted (default true)
971
- */
972
- importIds(idData, encrypted = true) {
973
- if (encrypted) {
974
- // we first need to decrypt the ids array using ECIES
975
- const derivedChild = __classPrivateFieldGet(this, _HDPrivateKey, "f").derive(ENCRYPTION_PATH);
976
- const decrypted = toUTF8(bitcoreDecrypt(toArray(Buffer.from(idData, Utils.isHex(idData) ? "hex" : "base64").toString("hex"), "hex"), derivedChild.privKey));
977
- idData = JSON.parse(decrypted);
978
- }
979
- let oldFormatImport = false;
980
- if (!idData.ids) {
981
- // old format id container
982
- oldFormatImport = true;
983
- idData = {
984
- lastIdPath: "",
985
- ids: idData,
986
- };
987
- }
988
- for (const id of idData.ids) {
989
- if (!id.identityKey || !id.identityAttributes || !id.rootAddress) {
990
- throw new Error("ID cannot be imported as it is not complete");
991
- }
992
- const importId = new BAP_ID(__classPrivateFieldGet(this, _HDPrivateKey, "f"), {}, id.idSeed);
993
- importId.BAP_SERVER = __classPrivateFieldGet(this, _BAP_SERVER, "f");
994
- importId.BAP_TOKEN = __classPrivateFieldGet(this, _BAP_TOKEN, "f");
995
- importId.import(id);
996
- this.checkIdBelongs(importId);
997
- __classPrivateFieldGet(this, _ids, "f")[importId.getIdentityKey()] = importId;
998
- if (oldFormatImport) {
999
- // overwrite with the last value on this array
1000
- idData.lastIdPath = importId.currentPath;
1001
- }
1002
- }
1003
- __classPrivateFieldSet(this, _lastIdPath, idData.lastIdPath, "f");
1004
- }
1005
- /**
1006
- * Export all the IDs of this instance for external storage
1007
- *
1008
- * By default this function will encrypt the data, using a derivative child of the main HD key
1009
- *
1010
- * @param encrypted Whether the data should be encrypted (default true)
1011
- * @returns {[]|*}
1012
- */
1013
- exportIds(encrypted = true) {
1014
- const idData = {
1015
- lastIdPath: __classPrivateFieldGet(this, _lastIdPath, "f"),
1016
- ids: [],
1017
- };
1018
- for (const key of Object.keys(__classPrivateFieldGet(this, _ids, "f"))) {
1019
- idData.ids.push(__classPrivateFieldGet(this, _ids, "f")[key].export());
1020
- }
1021
- if (encrypted) {
1022
- const derivedChild = __classPrivateFieldGet(this, _HDPrivateKey, "f").derive(ENCRYPTION_PATH);
1023
- return toBase64(bitcoreEncrypt(toArray(JSON.stringify(idData), 'utf8'), derivedChild.pubKey));
1024
- }
1025
- return idData;
1026
- }
1027
- /**
1028
- * Encrypt a string of data
1029
- *
1030
- * @param string
1031
- * @returns {string}
1032
- */
1033
- encrypt(string) {
1034
- const derivedChild = __classPrivateFieldGet(this, _HDPrivateKey, "f").derive(ENCRYPTION_PATH);
1035
- return toBase64(bitcoreEncrypt(toArray(string, 'utf8'), derivedChild.pubKey));
1036
- }
1037
- /**
1038
- * Decrypt a string of data
1039
- *
1040
- * @param string
1041
- * @returns {string}
1042
- */
1043
- decrypt(string) {
1044
- const derivedChild = __classPrivateFieldGet(this, _HDPrivateKey, "f").derive(ENCRYPTION_PATH);
1045
- return toUTF8(bitcoreDecrypt(toArray(string, 'base64'), derivedChild.privKey));
1046
- }
1047
- /**
1048
- * Sign an attestation for a user
1049
- *
1050
- * @param attestationHash The computed attestation hash for the user - this should be calculated with the BAP_ID class for an identity for the user
1051
- * @param identityKey The identity key we are using for the signing
1052
- * @param counter
1053
- * @param dataString Optional data string that will be appended to the BAP attestation
1054
- * @returns {string[]}
1055
- */
1056
- signAttestationWithAIP(attestationHash, identityKey, counter = 0, dataString = "") {
1057
- const id = this.getId(identityKey);
1058
- if (!id) {
1059
- throw new Error("Could not find identity to attest with");
1060
- }
1061
- const attestationBuffer = this.getAttestationBuffer(attestationHash, counter, dataString);
1062
- const { address, signature } = id.signMessage(attestationBuffer);
1063
- return this.createAttestationTransaction(attestationHash, counter, address, signature, dataString);
1064
- }
1065
- /**
1066
- * Verify an AIP signed attestation for a user
1067
- *
1068
- * [
1069
- * '0x6a',
1070
- * '0x31424150537561506e66476e53424d33474c56397968785564596534764762644d54',
1071
- * '0x415454455354',
1072
- * '0x33656166366361396334313936356538353831366439336439643034333136393032376633396661623034386333633031333663343364663635376462383761',
1073
- * '0x30',
1074
- * '0x7c',
1075
- * '0x313550636948473232534e4c514a584d6f5355615756693757537163376843667661',
1076
- * '0x424954434f494e5f4543445341',
1077
- * '0x31477531796d52567a595557634638776f6f506a7a4a4c764d383550795a64655876',
1078
- * '0x20ef60c5555001ddb1039bb0f215e46571fcb39ee46f48b089d1c08b0304dbcb3366d8fdf8bafd82be24b5ac42dcd6a5e96c90705dd42e3ad918b1b47ac3ce6ac2'
1079
- * ]
1080
- *
1081
- * @param tx Array of hex values for the OP_RETURN values
1082
- * @returns {{}}
1083
- */
1084
- verifyAttestationWithAIP(tx) {
1085
- if (!Array.isArray(tx) ||
1086
- tx[0] !== "0x6a" ||
1087
- tx[1] !== BAP_BITCOM_ADDRESS_HEX) {
1088
- throw new Error("Not a valid BAP transaction");
1089
- }
1090
- const dataOffset = tx[7] === "0x44415441" ? 5 : 0; // DATA
1091
- const attestation = {
1092
- type: Utils.hexDecode(tx[2]),
1093
- hash: Utils.hexDecode(tx[3]),
1094
- sequence: Utils.hexDecode(tx[4]),
1095
- signingProtocol: Utils.hexDecode(tx[7 + dataOffset]),
1096
- signingAddress: Utils.hexDecode(tx[8 + dataOffset]),
1097
- signature: Utils.hexDecode(tx[9 + dataOffset], "base64"),
1098
- };
1099
- if (dataOffset && tx[3] === tx[8]) {
1100
- // valid data addition
1101
- attestation.data = Utils.hexDecode(tx[9]);
1102
- }
1103
- try {
1104
- const signatureBufferStatements = [];
1105
- for (let i = 0; i < 6 + dataOffset; i++) {
1106
- signatureBufferStatements.push(Buffer.from(tx[i].replace("0x", ""), "hex"));
1107
- }
1108
- const attestationBuffer = Buffer.concat([...signatureBufferStatements]);
1109
- attestation.verified = this.verifySignature(attestationBuffer, attestation.signingAddress, attestation.signature);
1110
- }
1111
- catch (e) {
1112
- attestation.verified = false;
1113
- }
1114
- return attestation;
1115
- }
1116
- /**
1117
- * For BAP attestations we use all fields for the attestation
1118
- *
1119
- * @param attestationHash
1120
- * @param counter
1121
- * @param address
1122
- * @param signature
1123
- * @param dataString Optional data string that will be appended to the BAP attestation
1124
- * @returns {[string]}
1125
- */
1126
- createAttestationTransaction(attestationHash, counter, address, signature, dataString = "") {
1127
- const transaction = ["0x6a", Utils.hexEncode(BAP_BITCOM_ADDRESS)];
1128
- transaction.push(Utils.hexEncode("ATTEST"));
1129
- transaction.push(Utils.hexEncode(attestationHash));
1130
- transaction.push(Utils.hexEncode(`${counter}`));
1131
- transaction.push("0x7c"); // |
1132
- if (dataString) {
1133
- // data should be a string, either encrypted or stringified JSON if applicable
1134
- transaction.push(Utils.hexEncode(BAP_BITCOM_ADDRESS));
1135
- transaction.push(Utils.hexEncode("DATA"));
1136
- transaction.push(Utils.hexEncode(attestationHash));
1137
- transaction.push(Utils.hexEncode(dataString));
1138
- transaction.push("0x7c"); // |
1139
- }
1140
- transaction.push(Utils.hexEncode(AIP_BITCOM_ADDRESS));
1141
- transaction.push(Utils.hexEncode("BITCOIN_ECDSA"));
1142
- transaction.push(Utils.hexEncode(address));
1143
- transaction.push(`0x${Buffer.from(signature, "base64").toString("hex")}`);
1144
- return transaction;
1145
- }
1146
- /**
1147
- * This is a re-creation of how the bitcoinfiles-sdk creates a hash to sign for AIP
1148
- *
1149
- * @param attestationHash
1150
- * @param counter
1151
- * @param dataString Optional data string
1152
- * @returns {Buffer}
1153
- */
1154
- getAttestationBuffer(attestationHash, counter = 0, dataString = "") {
1155
- // re-create how AIP creates the buffer to sign
1156
- let dataStringBuffer = Buffer.from("");
1157
- if (dataString) {
1158
- dataStringBuffer = Buffer.concat([
1159
- Buffer.from(BAP_BITCOM_ADDRESS),
1160
- Buffer.from("DATA"),
1161
- Buffer.from(attestationHash),
1162
- Buffer.from(dataString),
1163
- Buffer.from("7c", "hex"),
1164
- ]);
1165
- }
1166
- return Buffer.concat([
1167
- Buffer.from("6a", "hex"),
1168
- Buffer.from(BAP_BITCOM_ADDRESS),
1169
- Buffer.from("ATTEST"),
1170
- Buffer.from(attestationHash),
1171
- Buffer.from(`${counter}`),
1172
- Buffer.from("7c", "hex"),
1173
- dataStringBuffer,
1174
- ]);
1175
- }
1176
- /**
1177
- * Verify that the identity challenge is signed by the address
1178
- *
1179
- * @param message Buffer or utf-8 string
1180
- * @param address Bitcoin address of signee
1181
- * @param signature Signature base64 string
1182
- *
1183
- * @return boolean
1184
- */
1185
- verifySignature(message, address, signature) {
1186
- // check the signature against the challenge
1187
- const messageBuffer = Buffer.isBuffer(message)
1188
- ? message
1189
- : Buffer.from(message);
1190
- const sig = sdk.Signature.fromCompact(signature, "base64");
1191
- let publicKey;
1192
- const msg = toArray(messageBuffer.toString("hex"), "hex");
1193
- for (let recovery = 0; recovery < 4; recovery++) {
1194
- try {
1195
- publicKey = sig.RecoverPublicKey(recovery, new sdk.BigNumber(sdk.BSM.magicHash(msg)));
1196
- const sigFitsPubkey = sdk.BSM.verify(msg, sig, publicKey);
1197
- if (sigFitsPubkey && publicKey.toAddress() === address) {
1198
- return true;
1199
- }
1200
- }
1201
- catch (e) {
1202
- // try next recovery
1203
- }
1204
- }
1205
- return false;
1206
- }
1207
- /**
1208
- * Check whether the given transaction (BAP OP_RETURN) is valid, is signed and that the
1209
- * identity signing is also valid at the time of signing
1210
- *
1211
- * @param idKey
1212
- * @param address
1213
- * @param challenge
1214
- * @param signature
1215
- *
1216
- * @returns {Promise<boolean|*>}
1217
- */
1218
- verifyChallengeSignature(idKey, address, challenge, signature) {
1219
- return __awaiter(this, void 0, void 0, function* () {
1220
- // first we test locally before sending to server
1221
- if (this.verifySignature(challenge, address, signature)) {
1222
- const result = yield this.getApiData("/attestation/valid", {
1223
- idKey,
1224
- challenge,
1225
- signature,
1226
- });
1227
- return result.data;
1228
- }
1229
- return false;
1230
- });
1231
- }
1232
- /**
1233
- * Check whether the given transaction (BAP OP_RETURN) is valid, is signed and that the
1234
- * identity signing is also valid at the time of signing
1235
- *
1236
- * @param tx
1237
- * @returns {Promise<boolean|*>}
1238
- */
1239
- isValidAttestationTransaction(tx) {
1240
- return __awaiter(this, void 0, void 0, function* () {
1241
- // first we test locally before sending to server
1242
- if (this.verifyAttestationWithAIP(tx)) {
1243
- return this.getApiData("/attestation/valid", {
1244
- tx,
1245
- });
1246
- }
1247
- return false;
1248
- });
1249
- }
1250
- /**
1251
- * Get all signing keys for the given idKey
1252
- *
1253
- * @param address
1254
- * @returns {Promise<*>}
1255
- */
1256
- getIdentityFromAddress(address) {
1257
- return __awaiter(this, void 0, void 0, function* () {
1258
- return this.getApiData("/identity/from-address", {
1259
- address,
1260
- });
1261
- });
1262
- }
1263
- /**
1264
- * Get all signing keys for the given idKey
1265
- *
1266
- * @param idKey
1267
- * @returns {Promise<*>}
1268
- */
1269
- getIdentity(idKey) {
1270
- return __awaiter(this, void 0, void 0, function* () {
1271
- return this.getApiData("/identity", {
1272
- idKey,
1273
- });
1274
- });
1275
- }
1276
- /**
1277
- * Get all attestations for the given attestation hash
1278
- *
1279
- * @param attestationHash
1280
- */
1281
- getAttestationsForHash(attestationHash) {
1282
- return __awaiter(this, void 0, void 0, function* () {
1283
- // get all BAP ATTEST records for the given attestationHash
1284
- return this.getApiData("/attestations", {
1285
- hash: attestationHash,
1286
- });
1287
- });
1288
- }
1289
- /**
1290
- * Helper function to get attestation from a BAP API server
1291
- *
1292
- * @param apiUrl
1293
- * @param apiData
1294
- * @returns {Promise<any>}
1295
- */
1296
- getApiData(apiUrl, apiData) {
1297
- return __awaiter(this, void 0, void 0, function* () {
1298
- const url = `${__classPrivateFieldGet(this, _BAP_SERVER, "f")}${apiUrl}`;
1299
- const response = yield fetch(url, {
1300
- method: "post",
1301
- headers: {
1302
- "Content-type": "application/json; charset=utf-8",
1303
- token: __classPrivateFieldGet(this, _BAP_TOKEN, "f"),
1304
- format: "json",
1305
- },
1306
- body: JSON.stringify(apiData),
1307
- });
1308
- return response.json();
1309
- });
1310
- }
1311
- },
1312
- _HDPrivateKey = new WeakMap(),
1313
- _ids = new WeakMap(),
1314
- _BAP_SERVER = new WeakMap(),
1315
- _BAP_TOKEN = new WeakMap(),
1316
- _lastIdPath = new WeakMap(),
1317
- _a);
1318
-
1319
- exports.BAP = BAP;
1320
- //# sourceMappingURL=typescript-npm-package.cjs.js.map