@bsv/sdk 1.9.23 → 1.9.29

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 (67) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/primitives/AESGCM.js +160 -76
  3. package/dist/cjs/src/primitives/AESGCM.js.map +1 -1
  4. package/dist/cjs/src/primitives/Hash.js +70 -5
  5. package/dist/cjs/src/primitives/Hash.js.map +1 -1
  6. package/dist/cjs/src/primitives/Point.js +41 -18
  7. package/dist/cjs/src/primitives/Point.js.map +1 -1
  8. package/dist/cjs/src/primitives/SymmetricKey.js +20 -19
  9. package/dist/cjs/src/primitives/SymmetricKey.js.map +1 -1
  10. package/dist/cjs/src/primitives/hex.js +1 -3
  11. package/dist/cjs/src/primitives/hex.js.map +1 -1
  12. package/dist/cjs/src/primitives/utils.js +10 -0
  13. package/dist/cjs/src/primitives/utils.js.map +1 -1
  14. package/dist/cjs/src/totp/totp.js +3 -1
  15. package/dist/cjs/src/totp/totp.js.map +1 -1
  16. package/dist/cjs/src/wallet/ProtoWallet.js +4 -2
  17. package/dist/cjs/src/wallet/ProtoWallet.js.map +1 -1
  18. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  19. package/dist/esm/src/primitives/AESGCM.js +158 -75
  20. package/dist/esm/src/primitives/AESGCM.js.map +1 -1
  21. package/dist/esm/src/primitives/Hash.js +68 -6
  22. package/dist/esm/src/primitives/Hash.js.map +1 -1
  23. package/dist/esm/src/primitives/Point.js +41 -18
  24. package/dist/esm/src/primitives/Point.js.map +1 -1
  25. package/dist/esm/src/primitives/SymmetricKey.js +20 -19
  26. package/dist/esm/src/primitives/SymmetricKey.js.map +1 -1
  27. package/dist/esm/src/primitives/hex.js +1 -3
  28. package/dist/esm/src/primitives/hex.js.map +1 -1
  29. package/dist/esm/src/primitives/utils.js +9 -0
  30. package/dist/esm/src/primitives/utils.js.map +1 -1
  31. package/dist/esm/src/totp/totp.js +3 -1
  32. package/dist/esm/src/totp/totp.js.map +1 -1
  33. package/dist/esm/src/wallet/ProtoWallet.js +4 -2
  34. package/dist/esm/src/wallet/ProtoWallet.js.map +1 -1
  35. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  36. package/dist/types/src/primitives/AESGCM.d.ts +59 -9
  37. package/dist/types/src/primitives/AESGCM.d.ts.map +1 -1
  38. package/dist/types/src/primitives/Hash.d.ts +47 -0
  39. package/dist/types/src/primitives/Hash.d.ts.map +1 -1
  40. package/dist/types/src/primitives/Point.d.ts +1 -0
  41. package/dist/types/src/primitives/Point.d.ts.map +1 -1
  42. package/dist/types/src/primitives/SymmetricKey.d.ts.map +1 -1
  43. package/dist/types/src/primitives/hex.d.ts.map +1 -1
  44. package/dist/types/src/primitives/utils.d.ts +1 -0
  45. package/dist/types/src/primitives/utils.d.ts.map +1 -1
  46. package/dist/types/src/totp/totp.d.ts.map +1 -1
  47. package/dist/types/src/wallet/ProtoWallet.d.ts.map +1 -1
  48. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  49. package/dist/umd/bundle.js +3 -3
  50. package/dist/umd/bundle.js.map +1 -1
  51. package/docs/reference/primitives.md +206 -60
  52. package/package.json +1 -1
  53. package/src/primitives/AESGCM.ts +225 -103
  54. package/src/primitives/Hash.ts +72 -7
  55. package/src/primitives/Point.ts +67 -20
  56. package/src/primitives/SymmetricKey.ts +28 -20
  57. package/src/primitives/__tests/AESGCM.test.ts +254 -354
  58. package/src/primitives/__tests/ECDSA.test.ts +27 -0
  59. package/src/primitives/__tests/Hash.test.ts +62 -10
  60. package/src/primitives/__tests/Point.test.ts +52 -0
  61. package/src/primitives/__tests/utils.test.ts +24 -1
  62. package/src/primitives/hex.ts +1 -3
  63. package/src/primitives/utils.ts +10 -0
  64. package/src/totp/__tests/totp.test.ts +21 -0
  65. package/src/totp/totp.ts +9 -1
  66. package/src/wallet/ProtoWallet.ts +8 -3
  67. package/src/wallet/__tests/ProtoWallet.test.ts +55 -34
@@ -44,14 +44,17 @@ export const biModInv = (a: bigint): bigint => { // binary‑ext GCD
44
44
  export const biModSqr = (a: bigint): bigint => biModMul(a, a)
45
45
 
46
46
  export const biModPow = (base: bigint, exp: bigint): bigint => {
47
- let result = BI_ONE
47
+ let result = 1n
48
48
  base = biMod(base)
49
- let e = exp
50
- while (e > BI_ZERO) {
51
- if ((e & BI_ONE) === BI_ONE) result = biModMul(result, base)
49
+
50
+ while (exp > 0n) {
51
+ if ((exp & 1n) !== 0n) {
52
+ result = biModMul(result, base)
53
+ }
52
54
  base = biModMul(base, base)
53
- e >>= BI_ONE
55
+ exp >>= 1n
54
56
  }
57
+
55
58
  return result
56
59
  }
57
60
 
@@ -59,7 +62,12 @@ export const P_PLUS1_DIV4 = (P_BIGINT + 1n) >> 2n
59
62
 
60
63
  export const biModSqrt = (a: bigint): bigint | null => {
61
64
  const r = biModPow(a, P_PLUS1_DIV4)
62
- return biModMul(r, r) === biMod(a) ? r : null
65
+
66
+ if (biModMul(r, r) !== biMod(a)) {
67
+ return null
68
+ }
69
+
70
+ return r
63
71
  }
64
72
 
65
73
  const toBigInt = (x: BigNumber | number | number[] | string): bigint => {
@@ -220,6 +228,13 @@ export default class Point extends BasePoint {
220
228
  y: BigNumber | null
221
229
  inf: boolean
222
230
 
231
+ static _assertOnCurve (p: Point): Point {
232
+ if (!p.validate()) {
233
+ throw new Error('Invalid point')
234
+ }
235
+ return p
236
+ }
237
+
223
238
  /**
224
239
  * Creates a point object from a given Array. These numbers can represent coordinates in hex format, or points
225
240
  * in multiple established formats.
@@ -238,7 +253,6 @@ export default class Point extends BasePoint {
238
253
  */
239
254
  static fromDER (bytes: number[]): Point {
240
255
  const len = 32
241
- // uncompressed, hybrid-odd, hybrid-even
242
256
  if (
243
257
  (bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) &&
244
258
  bytes.length - 1 === 2 * len
@@ -258,12 +272,14 @@ export default class Point extends BasePoint {
258
272
  bytes.slice(1 + len, 1 + 2 * len)
259
273
  )
260
274
 
261
- return res
275
+ return Point._assertOnCurve(res)
262
276
  } else if (
263
277
  (bytes[0] === 0x02 || bytes[0] === 0x03) &&
264
278
  bytes.length - 1 === len
265
279
  ) {
266
- return Point.fromX(bytes.slice(1, 1 + len), bytes[0] === 0x03)
280
+ return Point._assertOnCurve(
281
+ Point.fromX(bytes.slice(1, 1 + len), bytes[0] === 0x03)
282
+ )
267
283
  }
268
284
  throw new Error('Unknown point format')
269
285
  }
@@ -287,7 +303,7 @@ export default class Point extends BasePoint {
287
303
  */
288
304
  static fromString (str: string): Point {
289
305
  const bytes = toArray(str, 'hex')
290
- return Point.fromDER(bytes)
306
+ return Point._assertOnCurve(Point.fromDER(bytes))
291
307
  }
292
308
 
293
309
  /**
@@ -308,16 +324,22 @@ export default class Point extends BasePoint {
308
324
  static fromX (x: BigNumber | number | number[] | string, odd: boolean): Point {
309
325
  let xBigInt = toBigInt(x)
310
326
  xBigInt = biMod(xBigInt)
327
+
311
328
  const y2 = biModAdd(biModMul(biModSqr(xBigInt), xBigInt), 7n)
312
329
  const y = biModSqrt(y2)
313
- if (y === null) throw new Error('Invalid point')
330
+ if (y === null) {
331
+ throw new Error('Invalid point')
332
+ }
333
+
314
334
  let yBig = y
315
335
  if ((yBig & BI_ONE) !== (odd ? BI_ONE : BI_ZERO)) {
316
336
  yBig = biModSub(P_BIGINT, yBig)
317
337
  }
338
+
318
339
  const xBN = new BigNumber(xBigInt.toString(16), 16)
319
340
  const yBN = new BigNumber(yBig.toString(16), 16)
320
- return new Point(xBN, yBN)
341
+
342
+ return Point._assertOnCurve(new Point(xBN, yBN))
321
343
  }
322
344
 
323
345
  /**
@@ -339,33 +361,45 @@ export default class Point extends BasePoint {
339
361
  if (typeof obj === 'string') {
340
362
  obj = JSON.parse(obj)
341
363
  }
342
- const res = new Point(obj[0], obj[1], isRed)
343
- if (typeof obj[2] !== 'object') {
364
+
365
+ let res = new Point(obj[0], obj[1], isRed)
366
+ res = Point._assertOnCurve(res)
367
+
368
+ if (typeof obj[2] !== 'object' || obj[2] === null) {
344
369
  return res
345
370
  }
346
371
 
347
- const obj2point = (obj): Point => {
348
- return new Point(obj[0], obj[1], isRed)
372
+ const pre = obj[2]
373
+
374
+ const obj2point = (p): Point => {
375
+ const pt = new Point(p[0], p[1], isRed)
376
+ return Point._assertOnCurve(pt)
349
377
  }
350
378
 
351
- const pre = obj[2]
352
379
  res.precomputed = {
353
380
  beta: null,
381
+
354
382
  doubles:
355
383
  typeof pre.doubles === 'object' && pre.doubles !== null
356
384
  ? {
357
385
  step: pre.doubles.step,
358
- points: [res].concat(pre.doubles.points.map(obj2point))
386
+ points: [res].concat(
387
+ pre.doubles.points.map(obj2point)
388
+ )
359
389
  }
360
390
  : undefined,
391
+
361
392
  naf:
362
393
  typeof pre.naf === 'object' && pre.naf !== null
363
394
  ? {
364
395
  wnd: pre.naf.wnd,
365
- points: [res].concat(pre.naf.points.map(obj2point))
396
+ points: [res].concat(
397
+ pre.naf.points.map(obj2point)
398
+ )
366
399
  }
367
400
  : undefined
368
401
  }
402
+
369
403
  return res
370
404
  }
371
405
 
@@ -426,7 +460,20 @@ export default class Point extends BasePoint {
426
460
  * const isValid = aPoint.validate();
427
461
  */
428
462
  validate (): boolean {
429
- return this.curve.validate(this)
463
+ if (this.inf || this.x == null || this.y == null) return false
464
+
465
+ try {
466
+ const xBig = BigInt('0x' + this.x.fromRed().toString(16))
467
+ const yBig = BigInt('0x' + this.y.fromRed().toString(16))
468
+
469
+ // compute y² and x³ + 7 using bigint-secure field ops
470
+ const lhs = biModMul(yBig, yBig)
471
+ const rhs = biModAdd(biModMul(biModMul(xBig, xBig), xBig), 7n)
472
+
473
+ return lhs === rhs
474
+ } catch {
475
+ return false
476
+ }
430
477
  }
431
478
 
432
479
  /**
@@ -41,19 +41,27 @@ export default class SymmetricKey extends BigNumber {
41
41
  * const encryptedMessage = key.encrypt('plainText', 'utf8');
42
42
  */
43
43
  encrypt (msg: number[] | string, enc?: 'hex'): string | number[] {
44
- const iv = Random(32)
45
- msg = toArray(msg, enc)
46
- const keyBytes = this.toArray('be', 32)
47
- const { result, authenticationTag } = AESGCM(msg, [], iv, keyBytes)
44
+ const iv = new Uint8Array(Random(32))
45
+ const msgBytes = new Uint8Array(toArray(msg, enc))
46
+ const keyBytes = new Uint8Array(this.toArray('be', 32))
47
+
48
+ const { result, authenticationTag } = AESGCM(
49
+ msgBytes,
50
+ iv,
51
+ keyBytes
52
+ )
53
+
48
54
  const totalLength = iv.length + result.length + authenticationTag.length
49
- const combined = new Array(totalLength)
55
+ const combined = new Uint8Array(totalLength)
50
56
  let offset = 0
51
- for (const chunk of [iv, result, authenticationTag]) {
52
- for (let i = 0; i < chunk.length; i++) {
53
- combined[offset++] = chunk[i]
54
- }
55
- }
56
- return encode(combined, enc)
57
+
58
+ combined.set(iv, offset)
59
+ offset += iv.length
60
+ combined.set(result, offset)
61
+ offset += result.length
62
+ combined.set(authenticationTag, offset)
63
+
64
+ return encode(Array.from(combined), enc)
57
65
  }
58
66
 
59
67
  /**
@@ -73,30 +81,30 @@ export default class SymmetricKey extends BigNumber {
73
81
  * @throws {Error} Will throw an error if the decryption fails, likely due to message tampering or incorrect decryption key.
74
82
  */
75
83
  decrypt (msg: number[] | string, enc?: 'hex' | 'utf8'): string | number[] {
76
- msg = toArray(msg, enc)
84
+ const msgBytes = new Uint8Array(toArray(msg, enc))
77
85
 
78
86
  const ivLength = 32
79
87
  const tagLength = 16
80
88
 
81
- if (msg.length < ivLength + tagLength) {
89
+ if (msgBytes.length < ivLength + tagLength) {
82
90
  throw new Error('Ciphertext too short')
83
91
  }
84
92
 
85
- const iv = msg.slice(0, ivLength)
86
- const tagStart = msg.length - tagLength
87
- const ciphertext = msg.slice(ivLength, tagStart)
88
- const messageTag = msg.slice(tagStart)
93
+ const iv = msgBytes.slice(0, ivLength)
94
+ const tagStart = msgBytes.length - tagLength
95
+ const ciphertext = msgBytes.slice(ivLength, tagStart)
96
+ const messageTag = msgBytes.slice(tagStart)
89
97
 
98
+ const keyBytes = new Uint8Array(this.toArray('be', 32))
90
99
  const result = AESGCMDecrypt(
91
100
  ciphertext,
92
- [],
93
101
  iv,
94
102
  messageTag,
95
- this.toArray('be', 32)
103
+ keyBytes
96
104
  )
97
105
  if (result === null) {
98
106
  throw new Error('Decryption failed!')
99
107
  }
100
- return encode(result, enc)
108
+ return encode(Array.from(result), enc)
101
109
  }
102
110
  }