bsv-bap 0.0.1 → 0.0.3

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