bsv-bap 0.0.1

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 (62) hide show
  1. package/.babelrc +20 -0
  2. package/.eslintrc +46 -0
  3. package/LICENSE +25 -0
  4. package/README.md +819 -0
  5. package/babel.config.js +6 -0
  6. package/bun.lockb +0 -0
  7. package/coverage/clover.xml +6 -0
  8. package/coverage/coverage-final.json +1 -0
  9. package/coverage/lcov-report/base.css +224 -0
  10. package/coverage/lcov-report/block-navigation.js +87 -0
  11. package/coverage/lcov-report/favicon.png +0 -0
  12. package/coverage/lcov-report/index.html +101 -0
  13. package/coverage/lcov-report/prettify.css +1 -0
  14. package/coverage/lcov-report/prettify.js +2 -0
  15. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  16. package/coverage/lcov-report/sorter.js +196 -0
  17. package/coverage/lcov-report/src/constants.ts.html +113 -0
  18. package/coverage/lcov-report/src/id.ts.html +2207 -0
  19. package/coverage/lcov-report/src/index.html +156 -0
  20. package/coverage/lcov-report/src/index.ts.html +1877 -0
  21. package/coverage/lcov-report/src/utils.ts.html +404 -0
  22. package/coverage/lcov-report/tests/data/index.html +111 -0
  23. package/coverage/lcov-report/tests/data/keys.js.html +86 -0
  24. package/coverage/lcov.info +0 -0
  25. package/dist/jest.config.d.ts +8 -0
  26. package/dist/src/constants.d.ts +8 -0
  27. package/dist/src/id.d.ts +295 -0
  28. package/dist/src/index.d.ts +238 -0
  29. package/dist/src/interface.d.ts +23 -0
  30. package/dist/src/poa.d.ts +6 -0
  31. package/dist/src/utils.d.ts +54 -0
  32. package/dist/typescript-npm-package.cjs.d.ts +554 -0
  33. package/dist/typescript-npm-package.cjs.js +1320 -0
  34. package/dist/typescript-npm-package.cjs.js.map +1 -0
  35. package/dist/typescript-npm-package.esm.d.ts +554 -0
  36. package/dist/typescript-npm-package.esm.js +1312 -0
  37. package/dist/typescript-npm-package.esm.js.map +1 -0
  38. package/dist/typescript-npm-package.umd.d.ts +554 -0
  39. package/dist/typescript-npm-package.umd.js +110193 -0
  40. package/dist/typescript-npm-package.umd.js.map +1 -0
  41. package/jest.config.ts +196 -0
  42. package/jsdoc.json +16 -0
  43. package/package.json +80 -0
  44. package/rollup.config.js +64 -0
  45. package/setup-jest.js +1 -0
  46. package/src/README.md +80 -0
  47. package/src/attributes.json +119 -0
  48. package/src/constants.ts +11 -0
  49. package/src/id.ts +783 -0
  50. package/src/index.ts +631 -0
  51. package/src/interface.ts +26 -0
  52. package/src/poa.ts +9 -0
  53. package/src/utils.ts +111 -0
  54. package/tests/data/ids.json +30 -0
  55. package/tests/data/keys.js +2 -0
  56. package/tests/data/old-ids.json +25 -0
  57. package/tests/data/test-vectors.json +122 -0
  58. package/tests/id.test.js +286 -0
  59. package/tests/index.test.js +335 -0
  60. package/tests/regression.test.js +28 -0
  61. package/tests/utils.test.js +27 -0
  62. package/tsconfig.json +17 -0
@@ -0,0 +1,554 @@
1
+ /// <reference types="node" />
2
+ import { HD } from '@bsv/sdk';
3
+
4
+ interface Identity {
5
+ name: string;
6
+ description: string;
7
+ identityKey: string;
8
+ rootPath: string;
9
+ rootAddress: string;
10
+ previousPath: string;
11
+ currentPath: string;
12
+ lastIdPath: string;
13
+ idSeed: string;
14
+ identityAttributes: any;
15
+ }
16
+ type PathPrefix = `/${number}/${number}/${number}` | `/${number}'/${number}'/${number}'`;
17
+ interface Attestation {
18
+ type: string;
19
+ hash: string;
20
+ sequence: string;
21
+ signingProtocol: string;
22
+ signingAddress: string;
23
+ signature: string;
24
+ data?: string;
25
+ verified?: boolean;
26
+ }
27
+
28
+ /**
29
+ * BAP_ID class
30
+ *
31
+ * This class should be used in conjunction with the BAP class
32
+ *
33
+ * @type {BAP_ID}
34
+ */
35
+ declare class BAP_ID {
36
+ #private;
37
+ idName: string;
38
+ description: string;
39
+ rootAddress: string;
40
+ identityKey: string;
41
+ identityAttributes: {
42
+ [key: string]: any;
43
+ };
44
+ constructor(HDPrivateKey: HD, identityAttributes?: {
45
+ [key: string]: any;
46
+ }, idSeed?: string);
47
+ set BAP_SERVER(bapServer: string);
48
+ get BAP_SERVER(): string;
49
+ set BAP_TOKEN(token: string);
50
+ get BAP_TOKEN(): string;
51
+ deriveIdentityKey(address: string): string;
52
+ /**
53
+ * Helper function to parse identity attributes
54
+ *
55
+ * @param identityAttributes
56
+ * @returns {{}}
57
+ */
58
+ parseAttributes(identityAttributes: {
59
+ [key: string]: any;
60
+ } | string): {
61
+ [key: string]: any;
62
+ };
63
+ /**
64
+ * Parse a text of urn string into identity attributes
65
+ *
66
+ * urn:bap:id:name:John Doe:e2c6fb4063cc04af58935737eaffc938011dff546d47b7fbb18ed346f8c4d4fa
67
+ * urn:bap:id:birthday:1990-05-22:e61f23cbbb2284842d77965e2b0e32f0ca890b1894ca4ce652831347ee3596d9
68
+ * urn:bap:id:over18:1:480ca17ccaacd671b28dc811332525f2f2cd594d8e8e7825de515ce5d52d30e8
69
+ *
70
+ * @param urnIdentityAttributes
71
+ */
72
+ parseStringUrns(urnIdentityAttributes: string): {
73
+ [key: string]: any;
74
+ };
75
+ /**
76
+ * Returns the identity key
77
+ *
78
+ * @returns {*|string}
79
+ */
80
+ getIdentityKey(): string;
81
+ /**
82
+ * Returns all the attributes in the identity
83
+ *
84
+ * @returns {*}
85
+ */
86
+ getAttributes(): {
87
+ [key: string]: any;
88
+ };
89
+ /**
90
+ * Get the value of the given attribute
91
+ *
92
+ * @param attributeName
93
+ * @returns {{}|null}
94
+ */
95
+ getAttribute(attributeName: string): any;
96
+ /**
97
+ * Set the value of the given attribute
98
+ *
99
+ * If an empty value ('' || null || false) is given, the attribute is removed from the ID
100
+ *
101
+ * @param attributeName string
102
+ * @param attributeValue any
103
+ * @returns {{}|null}
104
+ */
105
+ setAttribute(attributeName: string, attributeValue: any): void;
106
+ /**
107
+ * Unset the given attribute from the ID
108
+ *
109
+ * @param attributeName
110
+ * @returns {{}|null}
111
+ */
112
+ unsetAttribute(attributeName: string): void;
113
+ /**
114
+ * Get all attribute urn's for this id
115
+ *
116
+ * @returns {string}
117
+ */
118
+ getAttributeUrns(): string;
119
+ /**
120
+ * Create an return the attribute urn for the given attribute
121
+ *
122
+ * @param attributeName
123
+ * @returns {string|null}
124
+ */
125
+ getAttributeUrn(attributeName: string): string | null;
126
+ /**
127
+ * Add an attribute to this identity
128
+ *
129
+ * @param attributeName
130
+ * @param value
131
+ * @param nonce
132
+ */
133
+ addAttribute(attributeName: string, value: any, nonce?: string): void;
134
+ /**
135
+ * This should be called with the last part of the signing path (/.../.../...)
136
+ * This library assumes the first part is m/424150'/0'/0' as defined at the top of this file
137
+ *
138
+ * @param path The second path of the signing path in the format [0-9]{0,9}/[0-9]{0,9}/[0-9]{0,9}
139
+ */
140
+ set rootPath(path: string);
141
+ get rootPath(): string;
142
+ getRootPath(): string;
143
+ /**
144
+ * This should be called with the last part of the signing path (/.../.../...)
145
+ * This library assumes the first part is m/424150'/0'/0' as defined at the top of this file
146
+ *
147
+ * @param path The second path of the signing path in the format [0-9]{0,9}/[0-9]{0,9}/[0-9]{0,9}
148
+ */
149
+ set currentPath(path: string);
150
+ get currentPath(): string;
151
+ get previousPath(): string;
152
+ /**
153
+ * This can be used to break the deterministic way child keys are created to make it harder for
154
+ * an attacker to steal the identites when the root key is compromised. This does however require
155
+ * the seeds to be stored at all times. If the seed is lost, the identity will not be recoverable.
156
+ */
157
+ get idSeed(): string;
158
+ /**
159
+ * Increment current path to a new path
160
+ *
161
+ * @returns {*}
162
+ */
163
+ incrementPath(): void;
164
+ /**
165
+ * Check whether the given path is a valid path for use with this class
166
+ * The signing paths used here always have a length of 3
167
+ *
168
+ * @param path The last part of the signing path (example "/0/0/1")
169
+ * @returns {boolean}
170
+ */
171
+ validatePath(path: string): boolean;
172
+ /**
173
+ * Get the OP_RETURN for the initial ID transaction (signed with root address)
174
+ *
175
+ * @returns {[]}
176
+ */
177
+ getInitialIdTransaction(): string[];
178
+ /**
179
+ * Get the OP_RETURN for the ID transaction of the current address / path
180
+ *
181
+ * @returns {[]}
182
+ */
183
+ getIdTransaction(previousPath?: string): string[];
184
+ /**
185
+ * Get address for given path
186
+ *
187
+ * @param path
188
+ * @returns {*}
189
+ */
190
+ getAddress(path: string): string;
191
+ /**
192
+ * Get current signing address
193
+ *
194
+ * @returns {*}
195
+ */
196
+ getCurrentAddress(): string;
197
+ /**
198
+ * Get the public key for encrypting data for this identity
199
+ */
200
+ getEncryptionPublicKey(): string;
201
+ /**
202
+ * Get the public key for encrypting data for this identity, using a seed for the encryption
203
+ */
204
+ getEncryptionPublicKeyWithSeed(seed: string): string;
205
+ /**
206
+ * Encrypt the given string data with the identity encryption key
207
+ * @param stringData
208
+ * @param counterPartyPublicKey Optional public key of the counterparty
209
+ * @return string Base64
210
+ */
211
+ encrypt(stringData: string, counterPartyPublicKey?: string): string;
212
+ /**
213
+ * Decrypt the given ciphertext with the identity encryption key
214
+ * @param ciphertext
215
+ * @param counterPartyPublicKey Optional public key of the counterparty
216
+ */
217
+ decrypt(ciphertext: string, counterPartyPublicKey?: string): string;
218
+ /**
219
+ * Encrypt the given string data with the identity encryption key
220
+ * @param stringData
221
+ * @param seed String seed
222
+ * @param counterPartyPublicKey Optional public key of the counterparty
223
+ * @return string Base64
224
+ */
225
+ encryptWithSeed(stringData: string, seed: string, counterPartyPublicKey?: string): string;
226
+ /**
227
+ * Decrypt the given ciphertext with the identity encryption key
228
+ * @param ciphertext
229
+ * @param seed String seed
230
+ * @param counterPartyPublicKey Public key of the counterparty
231
+ */
232
+ decryptWithSeed(ciphertext: string, seed: string, counterPartyPublicKey?: string): string;
233
+ private getEncryptionPrivateKeyWithSeed;
234
+ /**
235
+ * Get an attestation string for the given urn for this identity
236
+ *
237
+ * @param urn
238
+ * @returns {string}
239
+ */
240
+ getAttestation(urn: string): string;
241
+ /**
242
+ * Generate and return the attestation hash for the given attribute of this identity
243
+ *
244
+ * @param attribute Attribute name (name, email etc.)
245
+ * @returns {string}
246
+ */
247
+ getAttestationHash(attribute: string): string | null;
248
+ /**
249
+ * Sign a message with the current signing address of this identity
250
+ *
251
+ * @param message
252
+ * @param signingPath
253
+ * @returns {{address, signature}}
254
+ */
255
+ signMessage(message: string | Buffer, signingPath?: string): {
256
+ address: string;
257
+ signature: string;
258
+ };
259
+ /**
260
+ * Sign a message using a key based on the given string seed
261
+ *
262
+ * This works by creating a private key from the root key of this identity. It will always
263
+ * work with the rootPath / rootKey, to be deterministic. It will not change even if the keys
264
+ * are rotated for this ID.
265
+ *
266
+ * This is used in for instance deterministic login systems, that do not support BAP.
267
+ *
268
+ * @param message
269
+ * @param seed {string} String seed that will be used to generate a path
270
+ */
271
+ signMessageWithSeed(message: string, seed: string): {
272
+ address: string;
273
+ signature: string;
274
+ };
275
+ /**
276
+ * Sign an op_return hex array with AIP
277
+ * @param opReturn {array}
278
+ * @param signingPath {string}
279
+ * @param outputType {string}
280
+ * @return {[]}
281
+ */
282
+ signOpReturnWithAIP(opReturn: string[], signingPath?: string, outputType?: BufferEncoding): string[];
283
+ /**
284
+ * Construct an AIP buffer from the op return data
285
+ * @param opReturn
286
+ * @returns {Buffer}
287
+ */
288
+ getAIPMessageBuffer(opReturn: string[]): Buffer;
289
+ /**
290
+ * Get all signing keys for this identity
291
+ */
292
+ getIdSigningKeys(): Promise<any>;
293
+ /**
294
+ * Get all attestations for the given attribute
295
+ *
296
+ * @param attribute
297
+ */
298
+ getAttributeAttestations(attribute: string): Promise<any>;
299
+ /**
300
+ * Helper function to get attestation from a BAP API server
301
+ *
302
+ * @param apiUrl
303
+ * @param apiData
304
+ * @returns {Promise<any>}
305
+ */
306
+ getApiData(apiUrl: string, apiData: any): Promise<any>;
307
+ /**
308
+ * Import an identity from a JSON object
309
+ *
310
+ * @param identity{{}}
311
+ */
312
+ import(identity: Identity): void;
313
+ /**
314
+ * Export this identity to a JSON object
315
+ * @returns {{}}
316
+ */
317
+ export(): Identity;
318
+ }
319
+
320
+ /**
321
+ * BAP class
322
+ *
323
+ * Creates an instance of the BAP class and uses the given HDPrivateKey for all BAP operations.
324
+ *
325
+ * @param HDPrivateKey
326
+ */
327
+ declare const BAP: {
328
+ new (HDPrivateKey: string, token?: string): {
329
+ "__#1030@#HDPrivateKey": HD;
330
+ "__#1030@#ids": {
331
+ [key: string]: BAP_ID;
332
+ };
333
+ "__#1030@#BAP_SERVER": string;
334
+ "__#1030@#BAP_TOKEN": string;
335
+ "__#1030@#lastIdPath": string;
336
+ readonly lastIdPath: string;
337
+ /**
338
+ * Get the public key of the given childPath, or of the current HDPrivateKey of childPath is empty
339
+ *
340
+ * @param childPath Full derivation path for this child
341
+ * @returns {*}
342
+ */
343
+ getPublicKey(childPath?: string): string;
344
+ /**
345
+ * Get the public key of the given childPath, or of the current HDPrivateKey of childPath is empty
346
+ *
347
+ * @param childPath Full derivation path for this child
348
+ * @returns {*}
349
+ */
350
+ getHdPublicKey(childPath?: string): string;
351
+ BAP_SERVER: string;
352
+ BAP_TOKEN: string;
353
+ /**
354
+ * This function verifies that the given bapId matches the given root address
355
+ * This is used as a data integrity check
356
+ *
357
+ * @param bapId BAP_ID instance
358
+ */
359
+ checkIdBelongs(bapId: BAP_ID): boolean;
360
+ /**
361
+ * Returns a list of all the identity keys that are stored in this instance
362
+ *
363
+ * @returns {string[]}
364
+ */
365
+ listIds(): string[];
366
+ /**
367
+ * Create a new Id and link it to this BAP instance
368
+ *
369
+ * This function uses the length of the #ids of this class to determine the next valid path.
370
+ * If not all ids related to this HDPrivateKey have been loaded, determine the path externally
371
+ * and pass it to newId when creating a new ID.
372
+ *
373
+ * @param path
374
+ * @param identityAttributes
375
+ * @param idSeed
376
+ * @returns {*}
377
+ */
378
+ newId(path?: string, identityAttributes?: any, idSeed?: string): BAP_ID;
379
+ /**
380
+ * Remove identity
381
+ *
382
+ * @param idKey
383
+ * @returns {*}
384
+ */
385
+ removeId(idKey: string): void;
386
+ /**
387
+ * Get the next valid path for the used HDPrivateKey and loaded #ids
388
+ *
389
+ * @returns {string}
390
+ */
391
+ getNextValidPath(): PathPrefix;
392
+ /**
393
+ * Get a certain Id
394
+ *
395
+ * @param identityKey
396
+ * @returns {null}
397
+ */
398
+ getId(identityKey: string): BAP_ID | null;
399
+ /**
400
+ * This function is used when manipulating ID's, adding or removing attributes etc
401
+ * First create an id through this class and then use getId to get it. Then you can add/edit or
402
+ * increment the signing path and then re-set it with this function.
403
+ *
404
+ * Note: when you getId() from this class, you will be working on the same object as this class
405
+ * has and any changes made will be propagated to the id in this class. When you call exportIds
406
+ * your new changes will also be included, without having to setId().
407
+ *
408
+ * @param bapId
409
+ */
410
+ setId(bapId: BAP_ID): void;
411
+ /**
412
+ * This function is used to import IDs and attributes from some external storage
413
+ *
414
+ * The ID information should NOT be stored together with the HD private key !
415
+ *
416
+ * @param idData Array of ids that have been exported
417
+ * @param encrypted Whether the data should be treated as being encrypted (default true)
418
+ */
419
+ importIds(idData: any, encrypted?: boolean): void;
420
+ /**
421
+ * Export all the IDs of this instance for external storage
422
+ *
423
+ * By default this function will encrypt the data, using a derivative child of the main HD key
424
+ *
425
+ * @param encrypted Whether the data should be encrypted (default true)
426
+ * @returns {[]|*}
427
+ */
428
+ exportIds(encrypted?: boolean): any;
429
+ /**
430
+ * Encrypt a string of data
431
+ *
432
+ * @param string
433
+ * @returns {string}
434
+ */
435
+ encrypt(string: string): string;
436
+ /**
437
+ * Decrypt a string of data
438
+ *
439
+ * @param string
440
+ * @returns {string}
441
+ */
442
+ decrypt(string: string): string;
443
+ /**
444
+ * Sign an attestation for a user
445
+ *
446
+ * @param attestationHash The computed attestation hash for the user - this should be calculated with the BAP_ID class for an identity for the user
447
+ * @param identityKey The identity key we are using for the signing
448
+ * @param counter
449
+ * @param dataString Optional data string that will be appended to the BAP attestation
450
+ * @returns {string[]}
451
+ */
452
+ signAttestationWithAIP(attestationHash: string, identityKey: string, counter?: number, dataString?: string): string[];
453
+ /**
454
+ * Verify an AIP signed attestation for a user
455
+ *
456
+ * [
457
+ * '0x6a',
458
+ * '0x31424150537561506e66476e53424d33474c56397968785564596534764762644d54',
459
+ * '0x415454455354',
460
+ * '0x33656166366361396334313936356538353831366439336439643034333136393032376633396661623034386333633031333663343364663635376462383761',
461
+ * '0x30',
462
+ * '0x7c',
463
+ * '0x313550636948473232534e4c514a584d6f5355615756693757537163376843667661',
464
+ * '0x424954434f494e5f4543445341',
465
+ * '0x31477531796d52567a595557634638776f6f506a7a4a4c764d383550795a64655876',
466
+ * '0x20ef60c5555001ddb1039bb0f215e46571fcb39ee46f48b089d1c08b0304dbcb3366d8fdf8bafd82be24b5ac42dcd6a5e96c90705dd42e3ad918b1b47ac3ce6ac2'
467
+ * ]
468
+ *
469
+ * @param tx Array of hex values for the OP_RETURN values
470
+ * @returns {{}}
471
+ */
472
+ verifyAttestationWithAIP(tx: string[]): Attestation;
473
+ /**
474
+ * For BAP attestations we use all fields for the attestation
475
+ *
476
+ * @param attestationHash
477
+ * @param counter
478
+ * @param address
479
+ * @param signature
480
+ * @param dataString Optional data string that will be appended to the BAP attestation
481
+ * @returns {[string]}
482
+ */
483
+ createAttestationTransaction(attestationHash: string, counter: number, address: string, signature: string, dataString?: string): string[];
484
+ /**
485
+ * This is a re-creation of how the bitcoinfiles-sdk creates a hash to sign for AIP
486
+ *
487
+ * @param attestationHash
488
+ * @param counter
489
+ * @param dataString Optional data string
490
+ * @returns {Buffer}
491
+ */
492
+ getAttestationBuffer(attestationHash: string, counter?: number, dataString?: string): Buffer;
493
+ /**
494
+ * Verify that the identity challenge is signed by the address
495
+ *
496
+ * @param message Buffer or utf-8 string
497
+ * @param address Bitcoin address of signee
498
+ * @param signature Signature base64 string
499
+ *
500
+ * @return boolean
501
+ */
502
+ verifySignature(message: string | Buffer, address: string, signature: string): boolean;
503
+ /**
504
+ * Check whether the given transaction (BAP OP_RETURN) is valid, is signed and that the
505
+ * identity signing is also valid at the time of signing
506
+ *
507
+ * @param idKey
508
+ * @param address
509
+ * @param challenge
510
+ * @param signature
511
+ *
512
+ * @returns {Promise<boolean|*>}
513
+ */
514
+ verifyChallengeSignature(idKey: string, address: string, challenge: string, signature: string): Promise<boolean>;
515
+ /**
516
+ * Check whether the given transaction (BAP OP_RETURN) is valid, is signed and that the
517
+ * identity signing is also valid at the time of signing
518
+ *
519
+ * @param tx
520
+ * @returns {Promise<boolean|*>}
521
+ */
522
+ isValidAttestationTransaction(tx: string[]): Promise<any>;
523
+ /**
524
+ * Get all signing keys for the given idKey
525
+ *
526
+ * @param address
527
+ * @returns {Promise<*>}
528
+ */
529
+ getIdentityFromAddress(address: string): Promise<any>;
530
+ /**
531
+ * Get all signing keys for the given idKey
532
+ *
533
+ * @param idKey
534
+ * @returns {Promise<*>}
535
+ */
536
+ getIdentity(idKey: string): Promise<any>;
537
+ /**
538
+ * Get all attestations for the given attestation hash
539
+ *
540
+ * @param attestationHash
541
+ */
542
+ getAttestationsForHash(attestationHash: string): Promise<any>;
543
+ /**
544
+ * Helper function to get attestation from a BAP API server
545
+ *
546
+ * @param apiUrl
547
+ * @param apiData
548
+ * @returns {Promise<any>}
549
+ */
550
+ getApiData(apiUrl: string, apiData: any): Promise<any>;
551
+ };
552
+ };
553
+
554
+ export { BAP };