@bsv/sdk 1.1.12 → 1.1.14

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 (146) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/primitives/Point.js +28 -8
  3. package/dist/cjs/src/primitives/Point.js.map +1 -1
  4. package/dist/cjs/src/primitives/Polynomial.js +81 -0
  5. package/dist/cjs/src/primitives/Polynomial.js.map +1 -0
  6. package/dist/cjs/src/primitives/PrivateKey.js +165 -0
  7. package/dist/cjs/src/primitives/PrivateKey.js.map +1 -1
  8. package/dist/cjs/src/primitives/PublicKey.js +16 -2
  9. package/dist/cjs/src/primitives/PublicKey.js.map +1 -1
  10. package/dist/cjs/src/primitives/index.js +5 -1
  11. package/dist/cjs/src/primitives/index.js.map +1 -1
  12. package/dist/cjs/src/primitives/utils.js +1 -1
  13. package/dist/cjs/src/script/templates/P2PKH.js.map +1 -1
  14. package/dist/cjs/src/script/templates/RPuzzle.js.map +1 -1
  15. package/dist/cjs/src/transaction/Transaction.js +9 -4
  16. package/dist/cjs/src/transaction/Transaction.js.map +1 -1
  17. package/dist/cjs/src/transaction/broadcasters/ARC.js +4 -4
  18. package/dist/cjs/src/transaction/broadcasters/ARC.js.map +1 -1
  19. package/dist/cjs/src/transaction/broadcasters/DefaultBroadcaster.js.map +1 -1
  20. package/dist/cjs/src/transaction/broadcasters/WhatsOnChainBroadcaster.js +3 -3
  21. package/dist/cjs/src/transaction/broadcasters/WhatsOnChainBroadcaster.js.map +1 -1
  22. package/dist/cjs/src/transaction/chaintrackers/DefaultChainTracker.js.map +1 -1
  23. package/dist/cjs/src/transaction/chaintrackers/WhatsOnChain.js +2 -2
  24. package/dist/cjs/src/transaction/chaintrackers/WhatsOnChain.js.map +1 -1
  25. package/dist/cjs/src/transaction/fee-models/SatoshisPerKilobyte.js.map +1 -1
  26. package/dist/cjs/src/transaction/http/DefaultHttpClient.js +2 -2
  27. package/dist/cjs/src/transaction/http/DefaultHttpClient.js.map +1 -1
  28. package/dist/cjs/src/transaction/http/FetchHttpClient.js +2 -2
  29. package/dist/cjs/src/transaction/http/FetchHttpClient.js.map +1 -1
  30. package/dist/cjs/src/transaction/http/NodejsHttpClient.js +2 -2
  31. package/dist/cjs/src/transaction/http/NodejsHttpClient.js.map +1 -1
  32. package/dist/cjs/src/transaction/http/index.js.map +1 -1
  33. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  34. package/dist/esm/src/primitives/Point.js +28 -8
  35. package/dist/esm/src/primitives/Point.js.map +1 -1
  36. package/dist/esm/src/primitives/Polynomial.js +77 -0
  37. package/dist/esm/src/primitives/Polynomial.js.map +1 -0
  38. package/dist/esm/src/primitives/PrivateKey.js +143 -0
  39. package/dist/esm/src/primitives/PrivateKey.js.map +1 -1
  40. package/dist/esm/src/primitives/PublicKey.js +16 -2
  41. package/dist/esm/src/primitives/PublicKey.js.map +1 -1
  42. package/dist/esm/src/primitives/index.js +2 -1
  43. package/dist/esm/src/primitives/index.js.map +1 -1
  44. package/dist/esm/src/primitives/utils.js +1 -1
  45. package/dist/esm/src/script/templates/P2PKH.js.map +1 -1
  46. package/dist/esm/src/script/templates/RPuzzle.js.map +1 -1
  47. package/dist/esm/src/transaction/Transaction.js +9 -4
  48. package/dist/esm/src/transaction/Transaction.js.map +1 -1
  49. package/dist/esm/src/transaction/broadcasters/ARC.js +7 -7
  50. package/dist/esm/src/transaction/broadcasters/ARC.js.map +1 -1
  51. package/dist/esm/src/transaction/broadcasters/DefaultBroadcaster.js +1 -1
  52. package/dist/esm/src/transaction/broadcasters/DefaultBroadcaster.js.map +1 -1
  53. package/dist/esm/src/transaction/broadcasters/WhatsOnChainBroadcaster.js +4 -4
  54. package/dist/esm/src/transaction/broadcasters/WhatsOnChainBroadcaster.js.map +1 -1
  55. package/dist/esm/src/transaction/chaintrackers/DefaultChainTracker.js +1 -1
  56. package/dist/esm/src/transaction/chaintrackers/DefaultChainTracker.js.map +1 -1
  57. package/dist/esm/src/transaction/chaintrackers/WhatsOnChain.js +3 -3
  58. package/dist/esm/src/transaction/chaintrackers/WhatsOnChain.js.map +1 -1
  59. package/dist/esm/src/transaction/fee-models/SatoshisPerKilobyte.js.map +1 -1
  60. package/dist/esm/src/transaction/http/DefaultHttpClient.js +2 -2
  61. package/dist/esm/src/transaction/http/DefaultHttpClient.js.map +1 -1
  62. package/dist/esm/src/transaction/http/FetchHttpClient.js +2 -2
  63. package/dist/esm/src/transaction/http/FetchHttpClient.js.map +1 -1
  64. package/dist/esm/src/transaction/http/NodejsHttpClient.js +2 -2
  65. package/dist/esm/src/transaction/http/NodejsHttpClient.js.map +1 -1
  66. package/dist/esm/src/transaction/http/index.js.map +1 -1
  67. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  68. package/dist/types/src/primitives/Point.d.ts +19 -1
  69. package/dist/types/src/primitives/Point.d.ts.map +1 -1
  70. package/dist/types/src/primitives/Polynomial.d.ts +32 -0
  71. package/dist/types/src/primitives/Polynomial.d.ts.map +1 -0
  72. package/dist/types/src/primitives/PrivateKey.d.ts +72 -0
  73. package/dist/types/src/primitives/PrivateKey.d.ts.map +1 -1
  74. package/dist/types/src/primitives/PublicKey.d.ts +12 -1
  75. package/dist/types/src/primitives/PublicKey.d.ts.map +1 -1
  76. package/dist/types/src/primitives/index.d.ts +2 -1
  77. package/dist/types/src/primitives/index.d.ts.map +1 -1
  78. package/dist/types/src/primitives/utils.d.ts +1 -1
  79. package/dist/types/src/script/templates/P2PKH.d.ts.map +1 -1
  80. package/dist/types/src/transaction/Transaction.d.ts.map +1 -1
  81. package/dist/types/src/transaction/broadcasters/ARC.d.ts +1 -1
  82. package/dist/types/src/transaction/broadcasters/ARC.d.ts.map +1 -1
  83. package/dist/types/src/transaction/broadcasters/DefaultBroadcaster.d.ts +1 -1
  84. package/dist/types/src/transaction/broadcasters/DefaultBroadcaster.d.ts.map +1 -1
  85. package/dist/types/src/transaction/broadcasters/WhatsOnChainBroadcaster.d.ts +1 -1
  86. package/dist/types/src/transaction/broadcasters/WhatsOnChainBroadcaster.d.ts.map +1 -1
  87. package/dist/types/src/transaction/chaintrackers/DefaultChainTracker.d.ts +1 -1
  88. package/dist/types/src/transaction/chaintrackers/DefaultChainTracker.d.ts.map +1 -1
  89. package/dist/types/src/transaction/chaintrackers/WhatsOnChain.d.ts +2 -2
  90. package/dist/types/src/transaction/chaintrackers/WhatsOnChain.d.ts.map +1 -1
  91. package/dist/types/src/transaction/fee-models/SatoshisPerKilobyte.d.ts.map +1 -1
  92. package/dist/types/src/transaction/http/DefaultHttpClient.d.ts.map +1 -1
  93. package/dist/types/src/transaction/http/FetchHttpClient.d.ts +7 -9
  94. package/dist/types/src/transaction/http/FetchHttpClient.d.ts.map +1 -1
  95. package/dist/types/src/transaction/http/HttpClient.d.ts +5 -5
  96. package/dist/types/src/transaction/http/HttpClient.d.ts.map +1 -1
  97. package/dist/types/src/transaction/http/NodejsHttpClient.d.ts +5 -6
  98. package/dist/types/src/transaction/http/NodejsHttpClient.d.ts.map +1 -1
  99. package/dist/types/src/transaction/http/index.d.ts.map +1 -1
  100. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  101. package/docs/primitives.md +231 -16
  102. package/docs/transaction.md +38 -37
  103. package/package.json +1 -1
  104. package/src/compat/__tests/BSM.test.ts +37 -37
  105. package/src/compat/__tests/ECIES.test.ts +71 -71
  106. package/src/compat/__tests/HD.test.ts +362 -362
  107. package/src/compat/__tests/Mnemonic.test.ts +147 -148
  108. package/src/compat/__tests/Mnemonic.vectors.ts +170 -170
  109. package/src/messages/__tests/EncryptedMessage.test.ts +16 -16
  110. package/src/primitives/Point.ts +29 -10
  111. package/src/primitives/Polynomial.ts +89 -0
  112. package/src/primitives/PrivateKey.ts +147 -1
  113. package/src/primitives/PublicKey.ts +17 -2
  114. package/src/primitives/__tests/AESGCM.test.ts +20 -20
  115. package/src/primitives/__tests/Hash.test.ts +2 -2
  116. package/src/primitives/__tests/PBKDF2.vectors.ts +93 -93
  117. package/src/primitives/__tests/PrivateKey.split.test.ts +70 -0
  118. package/src/primitives/__tests/PublicKey.test.ts +14 -1
  119. package/src/primitives/__tests/bug-31.test.ts +24 -26
  120. package/src/primitives/__tests/utils.test.ts +13 -13
  121. package/src/primitives/index.ts +2 -1
  122. package/src/primitives/utils.ts +1 -1
  123. package/src/script/__tests/Script.test.ts +1 -1
  124. package/src/script/__tests/SpendComplex.test.ts +6 -6
  125. package/src/script/__tests/script.invalid.vectors.ts +1464 -1464
  126. package/src/script/__tests/script.valid.vectors.ts +1962 -1962
  127. package/src/script/__tests/spend.valid.vectors.ts +1369 -1369
  128. package/src/script/templates/P2PKH.ts +6 -6
  129. package/src/script/templates/RPuzzle.ts +1 -1
  130. package/src/transaction/Transaction.ts +13 -7
  131. package/src/transaction/__tests/Transaction.test.ts +14 -5
  132. package/src/transaction/__tests/bump.invalid.vectors.ts +1 -1
  133. package/src/transaction/__tests/bump.valid.vectors.ts +3 -3
  134. package/src/transaction/broadcasters/ARC.ts +20 -21
  135. package/src/transaction/broadcasters/DefaultBroadcaster.ts +3 -3
  136. package/src/transaction/broadcasters/WhatsOnChainBroadcaster.ts +10 -10
  137. package/src/transaction/broadcasters/__tests/WhatsOnChainBroadcaster.test.ts +7 -10
  138. package/src/transaction/chaintrackers/DefaultChainTracker.ts +3 -3
  139. package/src/transaction/chaintrackers/WhatsOnChain.ts +10 -12
  140. package/src/transaction/chaintrackers/__tests/WhatsOnChainChainTracker.test.ts +13 -17
  141. package/src/transaction/fee-models/SatoshisPerKilobyte.ts +2 -2
  142. package/src/transaction/http/DefaultHttpClient.ts +13 -13
  143. package/src/transaction/http/FetchHttpClient.ts +14 -16
  144. package/src/transaction/http/HttpClient.ts +22 -23
  145. package/src/transaction/http/NodejsHttpClient.ts +23 -25
  146. package/src/transaction/http/index.ts +6 -6
@@ -6,7 +6,58 @@ import Curve from './Curve.js'
6
6
  import { sign, verify } from './ECDSA.js'
7
7
  import { sha256, sha256hmac } from './Hash.js'
8
8
  import Random from './Random.js'
9
- import { fromBase58Check, toArray, toBase58Check } from './utils.js'
9
+ import { fromBase58Check, toArray, toBase58, toBase58Check } from './utils.js'
10
+ import Polynomial, { PointInFiniteField } from './Polynomial.js'
11
+
12
+ /**
13
+ * @class KeyShares
14
+ *
15
+ * This class is used to store the shares of a private key.
16
+ *
17
+ * @param shares - An array of shares
18
+ * @param threshold - The number of shares required to recombine the private key
19
+ *
20
+ * @returns KeyShares
21
+ *
22
+ * @example
23
+ * const key = PrivateKey.fromShares(shares)
24
+ *
25
+ */
26
+
27
+ export class KeyShares {
28
+ points: PointInFiniteField[]
29
+ threshold: number
30
+ integrity: string
31
+
32
+ constructor (points: PointInFiniteField[], threshold: number, integrity: string) {
33
+ this.points = points
34
+ this.threshold = threshold
35
+ this.integrity = integrity
36
+ }
37
+
38
+ static fromBackupFormat (shares: string[]): KeyShares {
39
+ let threshold = 0
40
+ let integrity = ''
41
+ const points = shares.map((share, idx) => {
42
+ const shareParts = share.split('.')
43
+ if (shareParts.length !== 4) throw Error('Invalid share format in share ' + idx + '. Expected format: "x.y.t.i" - received ' + share)
44
+ const [x, y, t, i] = shareParts
45
+ if (!t) throw Error('Threshold not found in share ' + idx)
46
+ if (!i) throw Error('Integrity not found in share ' + idx)
47
+ const tInt = parseInt(t)
48
+ if (idx !== 0 && threshold !== tInt) throw Error('Threshold mismatch in share ' + idx)
49
+ if (idx !== 0 && integrity !== i) throw Error('Integrity mismatch in share ' + idx)
50
+ threshold = tInt
51
+ integrity = i
52
+ return PointInFiniteField.fromString([x, y].join('.'))
53
+ })
54
+ return new KeyShares(points, threshold, integrity)
55
+ }
56
+
57
+ toBackupFormat () {
58
+ return this.points.map(share => share.toString() + '.' + this.threshold + '.' + this.integrity)
59
+ }
60
+ }
10
61
 
11
62
  /**
12
63
  * Represents a Private Key, which is a secret that can be used to generate signatures in a cryptographic system.
@@ -256,4 +307,99 @@ export default class PrivateKey extends BigNumber {
256
307
  const curve = new Curve()
257
308
  return new PrivateKey(this.add(new BigNumber(hmac)).mod(curve.n).toArray())
258
309
  }
310
+
311
+ /**
312
+ * Splits the private key into shares using Shamir's Secret Sharing Scheme.
313
+ *
314
+ * @param threshold The minimum number of shares required to reconstruct the private key.
315
+ * @param totalShares The total number of shares to generate.
316
+ * @param prime The prime number to be used in Shamir's Secret Sharing Scheme.
317
+ * @returns An array of shares.
318
+ *
319
+ * @example
320
+ * const key = PrivateKey.fromRandom()
321
+ * const shares = key.toKeyShares(2, 5)
322
+ */
323
+ toKeyShares (threshold: number, totalShares: number): KeyShares {
324
+ if (typeof threshold !== 'number' || typeof totalShares !== 'number') throw new Error('threshold and totalShares must be numbers')
325
+ if (threshold < 2) throw new Error('threshold must be at least 2')
326
+ if (totalShares < 2) throw new Error('totalShares must be at least 2')
327
+ if (threshold > totalShares) throw new Error('threshold should be less than or equal to totalShares')
328
+
329
+ const poly = Polynomial.fromPrivateKey(this, threshold)
330
+
331
+ const points = []
332
+ for (let i = 0; i < totalShares; i++) {
333
+ const x = new BigNumber(PrivateKey.fromRandom().toArray())
334
+ const y = poly.valueAt(x)
335
+ points.push(new PointInFiniteField(x, y))
336
+ }
337
+
338
+ const integrity = (this.toPublicKey().toHash('hex') as string).slice(0, 8)
339
+
340
+ return new KeyShares(points, threshold, integrity)
341
+ }
342
+
343
+ /**
344
+ * @method toBackupShares
345
+ *
346
+ * Creates a backup of the private key by splitting it into shares.
347
+ *
348
+ *
349
+ * @param threshold The number of shares which will be required to reconstruct the private key.
350
+ * @param totalShares The number of shares to generate for distribution.
351
+ * @returns
352
+ */
353
+ toBackupShares (threshold: number, totalShares: number): string[] {
354
+ return this.toKeyShares(threshold, totalShares).toBackupFormat()
355
+ }
356
+
357
+ /**
358
+ *
359
+ * @method fromBackupShares
360
+ *
361
+ * Creates a private key from backup shares.
362
+ *
363
+ * @param shares
364
+ * @returns PrivateKey
365
+ */
366
+ static fromBackupShares (shares: string[]): PrivateKey {
367
+ return PrivateKey.fromKeyShares(KeyShares.fromBackupFormat(shares))
368
+ }
369
+
370
+ /**
371
+ * Combines shares to reconstruct the private key.
372
+ *
373
+ * @param shares An array of points (shares) to be used to reconstruct the private key.
374
+ * @param threshold The minimum number of shares required to reconstruct the private key.
375
+ *
376
+ * @returns The reconstructed private key.
377
+ *
378
+ * @example
379
+ * const share1 = '2NWeap6SDBTL5jVnvk9yUxyfLqNrDs2Bw85KNDfLJwRT.4yLtSm327NApsbuP7QXVW3CWDuBRgmS6rRiFkAkTukic'
380
+ * const share2 = '7NbgGA8iAsxg2s6mBLkLFtGKQrnc4aCbooHJJV31cWs4.GUgXtudthawE3Eevc1waT3Atr1Ft7j1XxdUguVo3B7x3'
381
+ * const reconstructedKey = PrivateKey.fromKeyShares({ shares: [share1, share2], threshold: 2, integrity: '23409547' })
382
+ *
383
+ **/
384
+ static fromKeyShares (keyShares: KeyShares): PrivateKey {
385
+ const { points, threshold, integrity } = keyShares
386
+ if (threshold < 2 || threshold > 99) throw new Error('threshold should be between 2 and 99')
387
+ if (points.length < threshold) throw new Error(`At least ${threshold} shares are required to reconstruct the private key`)
388
+ // check to see if two points have the same x value
389
+ for (let i = 0; i < threshold; i++) {
390
+ for (let j = i + 1; j < threshold; j++) {
391
+ if (points[i].x.eq(points[j].x)) {
392
+ throw new Error('Duplicate share detected, each must be unique.')
393
+ }
394
+ }
395
+ }
396
+ const poly = new Polynomial(points, threshold)
397
+ const privateKey = new PrivateKey(poly.valueAt(new BigNumber(0)).toArray())
398
+ const integrityHash = privateKey.toPublicKey().toHash('hex').slice(0, 8)
399
+ if (integrityHash !== integrity) {
400
+ throw new Error('Integrity hash mismatch')
401
+ }
402
+
403
+ return privateKey
404
+ }
259
405
  }
@@ -51,6 +51,21 @@ export default class PublicKey extends Point {
51
51
  return new PublicKey(p.x, p.y)
52
52
  }
53
53
 
54
+ /**
55
+ * Static factory method to create a PublicKey instance from a number array.
56
+ *
57
+ * @param bytes - A number array representing a public key.
58
+ *
59
+ * @returns Returns the PublicKey created from the number array.
60
+ *
61
+ * @example
62
+ * const myPubKey = PublicKey.fromString("03....")
63
+ */
64
+ static fromDER (bytes: number[]): PublicKey {
65
+ const p = Point.fromDER(bytes)
66
+ return new PublicKey(p.x, p.y)
67
+ }
68
+
54
69
  /**
55
70
  * @constructor
56
71
  * @param x - A point or the x-coordinate of the point. May be a number, a BigNumber, a string (which will be interpreted as hex), a number array, or null. If null, an "Infinity" point is constructed.
@@ -121,8 +136,8 @@ export default class PublicKey extends Point {
121
136
  * @example
122
137
  * const derPublicKey = myPubKey.toDER()
123
138
  */
124
- toDER (): string {
125
- return this.encode(true, 'hex') as string
139
+ toDER (enc?: 'hex' | undefined): string {
140
+ return this.encode(true, enc) as string
126
141
  }
127
142
 
128
143
  /**
@@ -61,7 +61,7 @@ describe('AESGCM', () => {
61
61
  it('should encrypt: Test Case 3', () => {
62
62
  const output = AESGCM(toArray('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956' +
63
63
  '809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', 'hex'), [], toArray('cafebabefacedbaddecaf888', 'hex'),
64
- toArray('feffe9928665731c6d6a8f9467308308', 'hex'))
64
+ toArray('feffe9928665731c6d6a8f9467308308', 'hex'))
65
65
 
66
66
  expect(toArray('42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8' +
67
67
  'f6a5aac84aa051ba30b396a0aac973d58e091473f5985', 'hex')).toEqual(output.result)
@@ -71,7 +71,7 @@ describe('AESGCM', () => {
71
71
  it('should encrypt: Test Case 4', () => {
72
72
  const output = AESGCM(toArray('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956' +
73
73
  '809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', 'hex'), toArray('feedfacedeadbeeffeedfacedeadbeefabaddad2', 'hex'),
74
- toArray('cafebabefacedbaddecaf888', 'hex'), toArray('feffe9928665731c6d6a8f9467308308', 'hex'))
74
+ toArray('cafebabefacedbaddecaf888', 'hex'), toArray('feffe9928665731c6d6a8f9467308308', 'hex'))
75
75
  expect(toArray('42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8' +
76
76
  'f6a5aac84aa051ba30b396a0aac973d58e091', 'hex')).toEqual(output.result)
77
77
  expect(toArray('5bc94fbc3221a5db94fae95ae7121a47', 'hex')).toEqual(output.authenticationTag)
@@ -80,7 +80,7 @@ describe('AESGCM', () => {
80
80
  it('should encrypt: Test Case 5', () => {
81
81
  const output = AESGCM(toArray('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956' +
82
82
  '809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', 'hex'), toArray('feedfacedeadbeeffeedfacedeadbeefabaddad2', 'hex'),
83
- toArray('cafebabefacedbad', 'hex'), toArray('feffe9928665731c6d6a8f9467308308', 'hex'))
83
+ toArray('cafebabefacedbad', 'hex'), toArray('feffe9928665731c6d6a8f9467308308', 'hex'))
84
84
 
85
85
  expect(toArray('61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b0' +
86
86
  '97544d4896b424989b5e1ebac0f07c23f4598', 'hex')).toEqual(output.result)
@@ -90,7 +90,7 @@ describe('AESGCM', () => {
90
90
  it('should encrypt: Test Case 6', () => {
91
91
  const output = AESGCM(toArray('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956' +
92
92
  '809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', 'hex'), toArray('feedfacedeadbeeffeedfacedeadbeefabaddad2', 'hex'),
93
- toArray('9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416' +
93
+ toArray('9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416' +
94
94
  'aedbf5a0de6a57a637b39b', 'hex'), toArray('feffe9928665731c6d6a8f9467308308', 'hex'))
95
95
 
96
96
  expect(toArray('8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccd' +
@@ -117,7 +117,7 @@ describe('AESGCM', () => {
117
117
  it('should encrypt: Test Case 9', () => {
118
118
  const output = AESGCM(toArray('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956' +
119
119
  '809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', 'hex'), [], toArray('cafebabefacedbaddecaf888', 'hex'),
120
- toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c', 'hex'))
120
+ toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c', 'hex'))
121
121
 
122
122
  expect(toArray('3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac6' +
123
123
  '19d18c84a3f4718e2448b2fe324d9ccda2710acade256', 'hex')).toEqual(output.result)
@@ -127,7 +127,7 @@ describe('AESGCM', () => {
127
127
  it('should encrypt: Test Case 10', () => {
128
128
  const output = AESGCM(toArray('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956' +
129
129
  '809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', 'hex'), toArray('feedfacedeadbeeffeedfacedeadbeefabaddad2', 'hex'),
130
- toArray('cafebabefacedbaddecaf888', 'hex'), toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c', 'hex'))
130
+ toArray('cafebabefacedbaddecaf888', 'hex'), toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c', 'hex'))
131
131
 
132
132
  expect(toArray('3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac6' +
133
133
  '19d18c84a3f4718e2448b2fe324d9ccda2710', 'hex')).toEqual(output.result)
@@ -137,7 +137,7 @@ describe('AESGCM', () => {
137
137
  it('should encrypt: Test Case 11', () => {
138
138
  const output = AESGCM(toArray('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956' +
139
139
  '809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', 'hex'), toArray('feedfacedeadbeeffeedfacedeadbeefabaddad2', 'hex'),
140
- toArray('cafebabefacedbad', 'hex'), toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c', 'hex'))
140
+ toArray('cafebabefacedbad', 'hex'), toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c', 'hex'))
141
141
 
142
142
  expect(toArray('0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66' +
143
143
  '541d4d4dad1c9e93a19a58e8b473fa0f062f7', 'hex')).toEqual(output.result)
@@ -147,7 +147,7 @@ describe('AESGCM', () => {
147
147
  it('should encrypt: Test Case 12', () => {
148
148
  const output = AESGCM(toArray('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956' +
149
149
  '809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', 'hex'), toArray('feedfacedeadbeeffeedfacedeadbeefabaddad2', 'hex'),
150
- toArray('9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254' +
150
+ toArray('9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254' +
151
151
  '16aedbf5a0de6a57a637b39b', 'hex'), toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c', 'hex'))
152
152
 
153
153
  expect(toArray('d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f' +
@@ -175,8 +175,8 @@ describe('AESGCM', () => {
175
175
  it('should encrypt: Test Case 15', () => {
176
176
  const output = AESGCM(toArray('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956' +
177
177
  '809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', 'hex'), [],
178
- toArray('cafebabefacedbaddecaf888', 'hex'),
179
- toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', 'hex'))
178
+ toArray('cafebabefacedbaddecaf888', 'hex'),
179
+ toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', 'hex'))
180
180
 
181
181
  expect(toArray('522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b' +
182
182
  '08b1056828838c5f61e6393ba7a0abcc9f662898015ad', 'hex')).toEqual(output.result)
@@ -186,8 +186,8 @@ describe('AESGCM', () => {
186
186
  it('should encrypt: Test Case 16', () => {
187
187
  const output = AESGCM(toArray('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956' +
188
188
  '809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', 'hex'), toArray('feedfacedeadbeeffeedfacedeadbeefabaddad2', 'hex'),
189
- toArray('cafebabefacedbaddecaf888', 'hex'),
190
- toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', 'hex'))
189
+ toArray('cafebabefacedbaddecaf888', 'hex'),
190
+ toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', 'hex'))
191
191
 
192
192
  expect(toArray('522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b' +
193
193
  '08b1056828838c5f61e6393ba7a0abcc9f662', 'hex')).toEqual(output.result)
@@ -197,9 +197,9 @@ describe('AESGCM', () => {
197
197
  it('should encrypt: Test Case 17', () => {
198
198
  const output = AESGCM(toArray('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956' +
199
199
  '809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', 'hex'),
200
- toArray('feedfacedeadbeeffeedfacedeadbeefabaddad2', 'hex'),
201
- toArray('cafebabefacedbad', 'hex'),
202
- toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', 'hex'))
200
+ toArray('feedfacedeadbeeffeedfacedeadbeefabaddad2', 'hex'),
201
+ toArray('cafebabefacedbad', 'hex'),
202
+ toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', 'hex'))
203
203
 
204
204
  expect(toArray('c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954' +
205
205
  'cc2363bc73f7862ac430e64abe499f47c9b1f', 'hex')).toEqual(output.result)
@@ -209,10 +209,10 @@ describe('AESGCM', () => {
209
209
  it('should encrypt: Test Case 18', () => {
210
210
  const output = AESGCM(toArray('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956' +
211
211
  '809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', 'hex'),
212
- toArray('feedfacedeadbeeffeedfacedeadbeefabaddad2', 'hex'),
213
- toArray('9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416' +
212
+ toArray('feedfacedeadbeeffeedfacedeadbeefabaddad2', 'hex'),
213
+ toArray('9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416' +
214
214
  'aedbf5a0de6a57a637b39b', 'hex'),
215
- toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', 'hex'))
215
+ toArray('feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', 'hex'))
216
216
 
217
217
  expect(toArray('5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da' +
218
218
  '3ebf1c5d82cdea2418997200ef82e44ae7e3f', 'hex')).toEqual(output.result)
@@ -248,8 +248,8 @@ describe('multiply', () => {
248
248
  it('should commutatively multiply', () => {
249
249
  expect(multiply(toArray('48692853686179295b477565726f6e5d', 'hex'),
250
250
  toArray('7b5b54657374566563746f725d53475d', 'hex'))).toEqual(
251
- multiply(toArray('7b5b54657374566563746f725d53475d', 'hex'),
252
- toArray('48692853686179295b477565726f6e5d', 'hex')))
251
+ multiply(toArray('7b5b54657374566563746f725d53475d', 'hex'),
252
+ toArray('48692853686179295b477565726f6e5d', 'hex')))
253
253
  })
254
254
  })
255
255
 
@@ -5,7 +5,7 @@ import PBKDF2Vectors from './PBKDF2.vectors'
5
5
  import { toArray, toHex } from '../../../dist/cjs/src/primitives/utils'
6
6
 
7
7
  describe('Hash', function () {
8
- function test(Hash, cases): void {
8
+ function test (Hash, cases): void {
9
9
  for (let i = 0; i < cases.length; i++) {
10
10
  const msg = cases[i][0]
11
11
  const res = cases[i][1]
@@ -92,7 +92,7 @@ describe('Hash', function () {
92
92
 
93
93
  describe('PBKDF2 vectors', () => {
94
94
  for (let i = 0; i < PBKDF2Vectors.length; i++) {
95
- let v = PBKDF2Vectors[i]
95
+ const v = PBKDF2Vectors[i]
96
96
  let key, salt
97
97
  if (v.keyUint8Array) {
98
98
  key = v.keyUint8Array
@@ -1,119 +1,119 @@
1
1
  export default [{
2
- "key": "password",
3
- "salt": "salt",
4
- "iterations": 1,
5
- "dkLen": 32,
6
- "results": {
7
- "sha512": "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252"
8
- }
2
+ key: 'password',
3
+ salt: 'salt',
4
+ iterations: 1,
5
+ dkLen: 32,
6
+ results: {
7
+ sha512: '867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252'
8
+ }
9
9
  },
10
10
  {
11
- "key": "password",
12
- "salt": "salt",
13
- "iterations": 2,
14
- "dkLen": 32,
15
- "results": {
16
- "sha512": "e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53c"
17
- }
11
+ key: 'password',
12
+ salt: 'salt',
13
+ iterations: 2,
14
+ dkLen: 32,
15
+ results: {
16
+ sha512: 'e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53c'
17
+ }
18
18
  },
19
19
  {
20
- "key": "password",
21
- "salt": "salt",
22
- "iterations": 1,
23
- "dkLen": 64,
24
- "results": {
25
- "sha512": "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce"
26
- }
20
+ key: 'password',
21
+ salt: 'salt',
22
+ iterations: 1,
23
+ dkLen: 64,
24
+ results: {
25
+ sha512: '867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce'
26
+ }
27
27
  },
28
28
  {
29
- "key": "password",
30
- "salt": "salt",
31
- "iterations": 2,
32
- "dkLen": 64,
33
- "results": {
34
- "sha512": "e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e"
35
- }
29
+ key: 'password',
30
+ salt: 'salt',
31
+ iterations: 2,
32
+ dkLen: 64,
33
+ results: {
34
+ sha512: 'e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e'
35
+ }
36
36
  },
37
37
  {
38
- "key": "password",
39
- "salt": "salt",
40
- "iterations": 4096,
41
- "dkLen": 32,
42
- "results": {
43
- "sha512": "d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5"
44
- }
38
+ key: 'password',
39
+ salt: 'salt',
40
+ iterations: 4096,
41
+ dkLen: 32,
42
+ results: {
43
+ sha512: 'd197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5'
44
+ }
45
45
  },
46
46
  {
47
- "key": "passwordPASSWORDpassword",
48
- "salt": "saltSALTsaltSALTsaltSALTsaltSALTsalt",
49
- "iterations": 4096,
50
- "dkLen": 40,
51
- "results": {
52
- "sha512": "8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd953"
53
- }
47
+ key: 'passwordPASSWORDpassword',
48
+ salt: 'saltSALTsaltSALTsaltSALTsaltSALTsalt',
49
+ iterations: 4096,
50
+ dkLen: 40,
51
+ results: {
52
+ sha512: '8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd953'
53
+ }
54
54
  },
55
55
  {
56
- "key": "pass\u00000word",
57
- "salt": "sa\u00000lt",
58
- "iterations": 4096,
59
- "dkLen": 16,
60
- "results": {
61
- "sha512": "336d14366099e8aac2c46c94a8f178d2"
62
- }
56
+ key: 'pass\u00000word',
57
+ salt: 'sa\u00000lt',
58
+ iterations: 4096,
59
+ dkLen: 16,
60
+ results: {
61
+ sha512: '336d14366099e8aac2c46c94a8f178d2'
62
+ }
63
63
  },
64
64
  {
65
- "keyHex": "63ffeeddccbbaa",
66
- "salt": "salt",
67
- "iterations": 1,
68
- "dkLen": 32,
69
- "results": {
70
- "sha512": "f69de451247225a7b30cc47632899572bb980f500d7c606ac9b1c04f928a3488"
71
- }
65
+ keyHex: '63ffeeddccbbaa',
66
+ salt: 'salt',
67
+ iterations: 1,
68
+ dkLen: 32,
69
+ results: {
70
+ sha512: 'f69de451247225a7b30cc47632899572bb980f500d7c606ac9b1c04f928a3488'
71
+ }
72
72
  },
73
73
  {
74
- "description": "Unicode salt, no truncation due to hex",
75
- "key": "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
76
- "saltHex": "6d6e656d6f6e6963e383a1e383bce38388e383abe382abe38299e3838fe38299e382a6e38299e382a1e381afe3829ae381afe38299e3818fe38299e3829de38299e381a1e381a1e38299e58d81e4babae58d81e889b2",
77
- "iterations": 2048,
78
- "dkLen": 64,
79
- "results": {
80
- "sha512": "ba553eedefe76e67e2602dc20184c564010859faada929a090dd2c57aacb204ceefd15404ab50ef3e8dbeae5195aeae64b0def4d2eead1cdc728a33ced520ffd"
81
- }
74
+ description: 'Unicode salt, no truncation due to hex',
75
+ key: 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
76
+ saltHex: '6d6e656d6f6e6963e383a1e383bce38388e383abe382abe38299e3838fe38299e382a6e38299e382a1e381afe3829ae381afe38299e3818fe38299e3829de38299e381a1e381a1e38299e58d81e4babae58d81e889b2',
77
+ iterations: 2048,
78
+ dkLen: 64,
79
+ results: {
80
+ sha512: 'ba553eedefe76e67e2602dc20184c564010859faada929a090dd2c57aacb204ceefd15404ab50ef3e8dbeae5195aeae64b0def4d2eead1cdc728a33ced520ffd'
81
+ }
82
82
  },
83
83
  {
84
- "key": "password",
85
- "salt": "salt",
86
- "iterations": 1,
87
- "dkLen": 10,
88
- "results": {
89
- "sha512": "867f70cf1ade02cff375"
90
- }
84
+ key: 'password',
85
+ salt: 'salt',
86
+ iterations: 1,
87
+ dkLen: 10,
88
+ results: {
89
+ sha512: '867f70cf1ade02cff375'
90
+ }
91
91
  },
92
92
  {
93
- "key": "password",
94
- "salt": "salt",
95
- "iterations": 1,
96
- "dkLen": 100,
97
- "results": {
98
- "sha512": "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce7b532e206c2967d4c7d2ffa460539fc4d4e5eec70125d74c6c7cf86d25284f297907fcea"
99
- }
93
+ key: 'password',
94
+ salt: 'salt',
95
+ iterations: 1,
96
+ dkLen: 100,
97
+ results: {
98
+ sha512: '867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce7b532e206c2967d4c7d2ffa460539fc4d4e5eec70125d74c6c7cf86d25284f297907fcea'
99
+ }
100
100
  },
101
101
  {
102
- "keyUint8Array": [112, 97, 115, 115, 119, 111, 114, 100],
103
- "salt": "salt",
104
- "iterations": 1,
105
- "dkLen": 32,
106
- "results": {
107
- "sha512": "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252"
108
- }
102
+ keyUint8Array: [112, 97, 115, 115, 119, 111, 114, 100],
103
+ salt: 'salt',
104
+ iterations: 1,
105
+ dkLen: 32,
106
+ results: {
107
+ sha512: '867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252'
108
+ }
109
109
  },
110
110
  {
111
- "key": "password",
112
- "saltUint8Array": [115, 97, 108, 116],
113
- "iterations": 1,
114
- "dkLen": 32,
115
- "results": {
116
- "sha512": "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252"
117
- }
111
+ key: 'password',
112
+ saltUint8Array: [115, 97, 108, 116],
113
+ iterations: 1,
114
+ dkLen: 32,
115
+ results: {
116
+ sha512: '867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252'
117
+ }
118
118
  }
119
- ]
119
+ ]
@@ -0,0 +1,70 @@
1
+ import PrivateKey, { KeyShares } from '../../../dist/cjs/src/primitives/PrivateKey'
2
+ import { PointInFiniteField } from '../../../dist/cjs/src/primitives/Polynomial'
3
+
4
+ describe('PrivateKey', () => {
5
+ it('should split the private key into shares correctly', () => {
6
+ const privateKey = PrivateKey.fromRandom()
7
+ const threshold = 2
8
+ const totalShares = 5
9
+
10
+ // Split the private key
11
+ const shares = privateKey.toKeyShares(threshold, totalShares)
12
+ const backup = shares.toBackupFormat()
13
+
14
+ // Check the number of shares
15
+ expect(backup.length).toBe(totalShares)
16
+
17
+ // Check that each share is a BigNumber
18
+ shares.points.forEach(share => {
19
+ expect(share).toBeInstanceOf(PointInFiniteField)
20
+ })
21
+ expect(shares.threshold).toBe(threshold)
22
+ })
23
+
24
+ it('should recombine the shares into a private key correctly', () => {
25
+ let x = 0
26
+ while (x < 3) {
27
+ const key = PrivateKey.fromRandom()
28
+ const allShares = key.toKeyShares(3, 5)
29
+ const backup = allShares.toBackupFormat()
30
+ const someShares = KeyShares.fromBackupFormat(backup.slice(0,3))
31
+ const rebuiltKey = PrivateKey.fromKeyShares(someShares)
32
+ expect(rebuiltKey.toWif()).toBe(key.toWif())
33
+ x++
34
+ }
35
+ })
36
+
37
+ it('should throw an error for invalid threshold or totalShares', () => {
38
+ const k = PrivateKey.fromRandom()
39
+ expect(() => k.toKeyShares('12', 14)).toThrow('threshold and totalShares must be numbers')
40
+ expect(() => k.toKeyShares(4, '5')).toThrow('threshold and totalShares must be numbers')
41
+ })
42
+
43
+ it('should throw an error for invalid threshold', () => {
44
+ const k = PrivateKey.fromRandom()
45
+ expect(() => k.toKeyShares(1, 2)).toThrow('threshold must be at least 2')
46
+ })
47
+
48
+ it('should throw an error for invalid totalShares', () => {
49
+ const k = PrivateKey.fromRandom()
50
+ expect(() => k.toKeyShares(2, -4)).toThrow('totalShares must be at least 2')
51
+ })
52
+
53
+ it('should throw an error for totalShares being less than threshold', () => {
54
+ const k = PrivateKey.fromRandom()
55
+ expect(() => k.toKeyShares(3, 2)).toThrow('threshold should be less than or equal to totalShares')
56
+ })
57
+
58
+ it('should throw an error if the same share is included twice during recovery', () => {
59
+ const backup = [ '45s4vLL2hFvqmxrarvbRT2vZoQYGZGocsmaEksZ64o5M.A7nZrGux15nEsQGNZ1mbfnMKugNnS6SYYEQwfhfbDZG8.3.2f804d43', '7aPzkiGZgvU4Jira5PN9Qf9o7FEg6uwy1zcxd17NBhh3.CCt7NH1sPFgceb6phTRkfviim2WvmUycJCQd2BxauxP9.3.2f804d43', '9GaS2Tw5sXqqbuigdjwGPwPsQuEFqzqUXo5MAQhdK3es.8MLh2wyE3huyq6hiBXjSkJRucgyKh4jVY6ESq5jNtXRE.3.2f804d43', 'GBmoNRbsMVsLmEK5A6G28fktUNonZkn9mDrJJ58FXgsf.HDBRkzVUCtZ38ApEu36fvZtDoDSQTv3TWmbnxwwR7kto.3.2f804d43', '2gHebXBgPd7daZbsj6w9TPDta3vQzqvbkLtJG596rdN1.E7ZaHyyHNDCwR6qxZvKkPPWWXzFCiKQFentJtvSSH5Bi.3.2f804d43' ]
60
+ const recovery = KeyShares.fromBackupFormat([backup[0], backup[1], backup[1]])
61
+ expect(() => PrivateKey.fromKeyShares(recovery)).toThrow('Duplicate share detected, each must be unique.')
62
+ })
63
+
64
+ it('should be able to create a backup array from a private key, and recover the same key back from the backup', () => {
65
+ const key = PrivateKey.fromRandom()
66
+ const backup = key.toBackupShares(3, 5)
67
+ const recoveredKey = PrivateKey.fromBackupShares(backup.slice(0, 3))
68
+ expect(recoveredKey.toWif()).toBe(key.toWif())
69
+ })
70
+ })
@@ -47,10 +47,23 @@ describe('PublicKey', () => {
47
47
  })
48
48
 
49
49
  test('toDER should return DER encoded string of public key', () => {
50
- const derString = publicKey.toDER()
50
+ const derString = publicKey.toString()
51
51
  expect(typeof derString).toBe('string')
52
52
  expect(derString.length).toBe(66)
53
53
  })
54
+
55
+ test('toDER should return DER encoded number[] of public key', () => {
56
+ const der = publicKey.toDER()
57
+ expect(typeof der).toBe('object')
58
+ expect(der.length).toBe(33)
59
+ })
60
+
61
+ test('fromDER and fromString should result in the same public key', () => {
62
+ const key = PrivateKey.fromRandom()
63
+ const original = key.toPublicKey()
64
+ const backAndForth = PublicKey.fromString(PublicKey.fromDER(original.toDER()).toString())
65
+ expect(backAndForth.toString()).toEqual(original.toString())
66
+ })
54
67
  })
55
68
  describe('BRC42 vectors', () => {
56
69
  for (let i = 0; i < BRC42Public.length; i++) {