@bsv/sdk 1.6.16 → 1.6.18

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 (111) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/auth/Peer.js +16 -25
  3. package/dist/cjs/src/auth/Peer.js.map +1 -1
  4. package/dist/cjs/src/auth/SessionManager.js +2 -4
  5. package/dist/cjs/src/auth/SessionManager.js.map +1 -1
  6. package/dist/cjs/src/auth/certificates/Certificate.js +2 -4
  7. package/dist/cjs/src/auth/certificates/Certificate.js.map +1 -1
  8. package/dist/cjs/src/auth/certificates/MasterCertificate.js +1 -1
  9. package/dist/cjs/src/auth/certificates/MasterCertificate.js.map +1 -1
  10. package/dist/cjs/src/auth/clients/AuthFetch.js +2 -4
  11. package/dist/cjs/src/auth/clients/AuthFetch.js.map +1 -1
  12. package/dist/cjs/src/compat/ECIES.js +1 -1
  13. package/dist/cjs/src/compat/ECIES.js.map +1 -1
  14. package/dist/cjs/src/compat/Mnemonic.js +2 -2
  15. package/dist/cjs/src/compat/Mnemonic.js.map +1 -1
  16. package/dist/cjs/src/identity/IdentityClient.js +1 -1
  17. package/dist/cjs/src/identity/IdentityClient.js.map +1 -1
  18. package/dist/cjs/src/kvstore/LocalKVStore.js +1 -2
  19. package/dist/cjs/src/kvstore/LocalKVStore.js.map +1 -1
  20. package/dist/cjs/src/overlay-tools/LookupResolver.js +10 -8
  21. package/dist/cjs/src/overlay-tools/LookupResolver.js.map +1 -1
  22. package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js +9 -10
  23. package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js.map +1 -1
  24. package/dist/cjs/src/primitives/AESGCM.js +1 -2
  25. package/dist/cjs/src/primitives/AESGCM.js.map +1 -1
  26. package/dist/cjs/src/primitives/BigNumber.js +2 -3
  27. package/dist/cjs/src/primitives/BigNumber.js.map +1 -1
  28. package/dist/cjs/src/primitives/Curve.js +2 -3
  29. package/dist/cjs/src/primitives/Curve.js.map +1 -1
  30. package/dist/cjs/src/primitives/ECDSA.js +174 -396
  31. package/dist/cjs/src/primitives/ECDSA.js.map +1 -1
  32. package/dist/cjs/src/primitives/JacobianPoint.js +1 -2
  33. package/dist/cjs/src/primitives/JacobianPoint.js.map +1 -1
  34. package/dist/cjs/src/primitives/Point.js +217 -181
  35. package/dist/cjs/src/primitives/Point.js.map +1 -1
  36. package/dist/cjs/src/primitives/Polynomial.js +1 -1
  37. package/dist/cjs/src/primitives/Polynomial.js.map +1 -1
  38. package/dist/cjs/src/primitives/Random.js +1 -2
  39. package/dist/cjs/src/primitives/Random.js.map +1 -1
  40. package/dist/cjs/src/primitives/TransactionSignature.js +5 -7
  41. package/dist/cjs/src/primitives/TransactionSignature.js.map +1 -1
  42. package/dist/cjs/src/primitives/utils.js +1 -2
  43. package/dist/cjs/src/primitives/utils.js.map +1 -1
  44. package/dist/cjs/src/registry/RegistryClient.js +2 -4
  45. package/dist/cjs/src/registry/RegistryClient.js.map +1 -1
  46. package/dist/cjs/src/script/Spend.js +1 -2
  47. package/dist/cjs/src/script/Spend.js.map +1 -1
  48. package/dist/cjs/src/script/templates/P2PKH.js +4 -4
  49. package/dist/cjs/src/script/templates/P2PKH.js.map +1 -1
  50. package/dist/cjs/src/script/templates/PushDrop.js +7 -8
  51. package/dist/cjs/src/script/templates/PushDrop.js.map +1 -1
  52. package/dist/cjs/src/script/templates/RPuzzle.js +7 -6
  53. package/dist/cjs/src/script/templates/RPuzzle.js.map +1 -1
  54. package/dist/cjs/src/storage/StorageDownloader.js +1 -1
  55. package/dist/cjs/src/storage/StorageDownloader.js.map +1 -1
  56. package/dist/cjs/src/storage/StorageUploader.js +6 -9
  57. package/dist/cjs/src/storage/StorageUploader.js.map +1 -1
  58. package/dist/cjs/src/transaction/Beef.js +2 -3
  59. package/dist/cjs/src/transaction/Beef.js.map +1 -1
  60. package/dist/cjs/src/transaction/MerklePath.js +9 -12
  61. package/dist/cjs/src/transaction/MerklePath.js.map +1 -1
  62. package/dist/cjs/src/transaction/Transaction.js +15 -22
  63. package/dist/cjs/src/transaction/Transaction.js.map +1 -1
  64. package/dist/cjs/src/transaction/broadcasters/ARC.js +3 -3
  65. package/dist/cjs/src/transaction/broadcasters/ARC.js.map +1 -1
  66. package/dist/cjs/src/transaction/broadcasters/Teranode.js +2 -3
  67. package/dist/cjs/src/transaction/broadcasters/Teranode.js.map +1 -1
  68. package/dist/cjs/src/transaction/broadcasters/WhatsOnChainBroadcaster.js +2 -3
  69. package/dist/cjs/src/transaction/broadcasters/WhatsOnChainBroadcaster.js.map +1 -1
  70. package/dist/cjs/src/transaction/chaintrackers/BlockHeadersService.js +2 -2
  71. package/dist/cjs/src/transaction/chaintrackers/BlockHeadersService.js.map +1 -1
  72. package/dist/cjs/src/transaction/chaintrackers/WhatsOnChain.js +2 -2
  73. package/dist/cjs/src/transaction/chaintrackers/WhatsOnChain.js.map +1 -1
  74. package/dist/cjs/src/transaction/http/FetchHttpClient.js +1 -2
  75. package/dist/cjs/src/transaction/http/FetchHttpClient.js.map +1 -1
  76. package/dist/cjs/src/wallet/CachedKeyDeriver.js +1 -1
  77. package/dist/cjs/src/wallet/CachedKeyDeriver.js.map +1 -1
  78. package/dist/cjs/src/wallet/KeyDeriver.js +4 -3
  79. package/dist/cjs/src/wallet/KeyDeriver.js.map +1 -1
  80. package/dist/cjs/src/wallet/ProtoWallet.js +21 -25
  81. package/dist/cjs/src/wallet/ProtoWallet.js.map +1 -1
  82. package/dist/cjs/src/wallet/substrates/HTTPWalletJSON.js +2 -3
  83. package/dist/cjs/src/wallet/substrates/HTTPWalletJSON.js.map +1 -1
  84. package/dist/cjs/src/wallet/substrates/HTTPWalletWire.js +1 -1
  85. package/dist/cjs/src/wallet/substrates/HTTPWalletWire.js.map +1 -1
  86. package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js +12 -19
  87. package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js.map +1 -1
  88. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  89. package/dist/esm/src/overlay-tools/LookupResolver.js +4 -0
  90. package/dist/esm/src/overlay-tools/LookupResolver.js.map +1 -1
  91. package/dist/esm/src/primitives/ECDSA.js +174 -395
  92. package/dist/esm/src/primitives/ECDSA.js.map +1 -1
  93. package/dist/esm/src/primitives/Point.js +192 -146
  94. package/dist/esm/src/primitives/Point.js.map +1 -1
  95. package/dist/esm/src/wallet/KeyDeriver.js +3 -1
  96. package/dist/esm/src/wallet/KeyDeriver.js.map +1 -1
  97. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  98. package/dist/types/src/overlay-tools/LookupResolver.d.ts.map +1 -1
  99. package/dist/types/src/primitives/ECDSA.d.ts.map +1 -1
  100. package/dist/types/src/primitives/Point.d.ts.map +1 -1
  101. package/dist/types/src/wallet/KeyDeriver.d.ts.map +1 -1
  102. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  103. package/dist/umd/bundle.js +1 -1
  104. package/docs/reference/primitives.md +165 -377
  105. package/package.json +1 -1
  106. package/src/overlay-tools/LookupResolver.ts +5 -0
  107. package/src/primitives/ECDSA.ts +218 -488
  108. package/src/primitives/Point.ts +212 -162
  109. package/src/transaction/__tests/Transaction.test.ts +1 -1
  110. package/src/wallet/KeyDeriver.ts +2 -1
  111. package/src/wallet/__tests/ProtoWallet.test.ts +46 -1
@@ -60,324 +60,86 @@ export const sign = (
60
60
  forceLowS: boolean = false,
61
61
  customK?: BigNumber | ((iter: number) => BigNumber)
62
62
  ): Signature => {
63
- if (typeof BigInt === 'function') {
64
- // Curve parameters for secp256k1
65
- const zero = BigInt(0)
66
- const one = BigInt(1)
67
- const two = BigInt(2)
68
- const n = BigInt(
69
- '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'
70
- ) // Order of the curve
71
- const p = BigInt(
72
- '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'
73
- ) // Field prime
74
- const Gx = BigInt(
75
- '0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'
76
- )
77
- const Gy = BigInt(
78
- '0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8'
79
- )
80
- const G = { x: Gx, y: Gy }
81
-
82
- // Convert msg and key to BigInt
83
- const z = BigInt('0x' + msg.toString(16))
84
- const d = BigInt('0x' + key.toString(16))
85
-
86
- // Validate private key
87
- if (d <= zero || d >= n) {
88
- throw new Error('Invalid private key')
63
+ const curve = new Curve()
64
+ msg = truncateToN(msg)
65
+
66
+ // Zero-extend key to provide enough entropy
67
+ const bytes = curve.n.byteLength()
68
+ const bkey = key.toArray('be', bytes)
69
+
70
+ // Zero-extend nonce to have the same byte size as N
71
+ const nonce = msg.toArray('be', bytes)
72
+
73
+ // Instantiate Hmac_DRBG
74
+ const drbg = new DRBG(bkey, nonce)
75
+
76
+ // Number of bytes to generate
77
+ const ns1 = curve.n.subn(1)
78
+
79
+ for (let iter = 0; ; iter++) {
80
+ // Compute the k-value
81
+ let k =
82
+ typeof customK === 'function'
83
+ ? customK(iter)
84
+ : BigNumber.isBN(customK)
85
+ ? customK
86
+ : new BigNumber(drbg.generate(bytes), 16)
87
+ if (k != null) {
88
+ k = truncateToN(k, true)
89
+ } else {
90
+ throw new Error('k is undefined')
89
91
  }
90
-
91
- // Helper function to convert BigInt to byte array
92
- function bigIntToBytes (value: bigint, length: number): Uint8Array {
93
- const hex = value.toString(16).padStart(length * 2, '0')
94
- const bytes = new Uint8Array(length)
95
- for (let i = 0; i < length; i++) {
96
- bytes[i] = parseInt(hex.substr(i * 2, 2), 16)
97
- }
98
- return bytes
99
- }
100
-
101
- // Zero-extend key to provide enough entropy
102
- const bytes = 32 // Assuming 256-bit curve
103
- const bkey = bigIntToBytes(d, bytes) // 'd' is the private key BigInt
104
-
105
- // Zero-extend nonce to have the same byte size as N
106
- const nonce = bigIntToBytes(z, bytes) // 'z' is the message hash BigInt
107
-
108
- // Instantiate Hmac_DRBG
109
- const drbg = new DRBG(Array.from(bkey), Array.from(nonce))
110
-
111
- // Number of bytes to generate
112
- const ns1 = n - one
113
-
114
- let iter = 0
115
-
116
- // Truncate to N function for BigInt
117
- function truncateToN (
118
- k: bigint,
119
- n: bigint,
120
- truncOnly: boolean = true
121
- ): bigint {
122
- const kBitLength = k.toString(2).length
123
- const nBitLength = n.toString(2).length
124
- const delta = kBitLength - nBitLength
125
- if (delta > 0) {
126
- k = k >> BigInt(delta)
127
- }
128
- if (!truncOnly && k >= n) {
129
- return k - n
92
+ if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) {
93
+ if (BigNumber.isBN(customK)) {
94
+ throw new Error(
95
+ 'Invalid fixed custom K value (must be more than 1 and less than N-1)'
96
+ )
130
97
  } else {
131
- return k
98
+ continue
132
99
  }
133
100
  }
134
101
 
135
- function generateK (
136
- customK?: BigNumber | ((iter: number) => BigNumber)
137
- ): bigint {
138
- if (typeof customK === 'function') {
139
- // Call customK function to get k as BigNumber
140
- const kbn = customK(iter)
141
- // Convert k_bn (BigNumber) to BigInt
142
- const kstr = kbn.toString(16)
143
- return BigInt('0x' + kstr)
144
- } else if ((customK != null) && BigNumber.isBN(customK)) {
145
- // Use customK provided, convert to BigInt
146
- const kstr = customK.toString(16)
147
- return BigInt('0x' + kstr)
102
+ const kp = curve.g.mul(k)
103
+ if (kp.isInfinity()) {
104
+ if (BigNumber.isBN(customK)) {
105
+ throw new Error(
106
+ 'Invalid fixed custom K value (must not create a point at infinity when multiplied by the generator point)'
107
+ )
148
108
  } else {
149
- // Use DRBG to generate k
150
- const khex = drbg.generate(bytes) // Generate hex string
151
- return BigInt('0x' + khex)
152
- }
153
- }
154
-
155
- // Modular arithmetic functions
156
- function mod (a: bigint, m: bigint): bigint {
157
- return ((a % m) + m) % m
158
- }
159
-
160
- function modInv (a: bigint, m: bigint): bigint {
161
- let lm = one
162
- let hm = zero
163
- let low = mod(a, m)
164
- let high = m
165
- while (low > one) {
166
- const r = high / low
167
- const nm = hm - lm * r
168
- const neww = high - low * r
169
- hm = lm
170
- lm = nm
171
- high = low
172
- low = neww
109
+ continue
173
110
  }
174
- return mod(lm, m)
175
111
  }
176
112
 
177
- function pointAdd (
178
- P: { x: bigint, y: bigint } | null,
179
- Q: { x: bigint, y: bigint } | null
180
- ): { x: bigint, y: bigint } | null {
181
- if (P === null) return Q
182
- if (Q === null) return P
183
-
184
- if (P.x === Q.x && P.y === mod(-Q.y, p)) {
185
- return null // Point at infinity
186
- }
187
-
188
- let m: bigint
189
- if (P.x === Q.x && P.y === Q.y) {
190
- // Point doubling
191
- if (P.y === zero) {
192
- return null // Point at infinity
193
- }
194
- const numerator = mod(BigInt(3) * P.x * P.x, p) // 3 * x^2
195
- const denominator = modInv(two * P.y, p)
196
- m = mod(numerator * denominator, p)
113
+ const kpX = kp.getX()
114
+ const r = kpX.umod(curve.n)
115
+ if (r.cmpn(0) === 0) {
116
+ if (BigNumber.isBN(customK)) {
117
+ throw new Error(
118
+ 'Invalid fixed custom K value (when multiplied by G, the resulting x coordinate mod N must not be zero)'
119
+ )
197
120
  } else {
198
- const numerator = mod(Q.y - P.y, p)
199
- const denominator = modInv(Q.x - P.x, p)
200
- m = mod(numerator * denominator, p)
121
+ continue
201
122
  }
202
-
203
- const xR = mod(m * m - P.x - Q.x, p)
204
- const yR = mod(m * (P.x - xR) - P.y, p)
205
-
206
- return { x: xR, y: yR }
207
- }
208
-
209
- function scalarMul (
210
- k: bigint,
211
- P: { x: bigint, y: bigint }
212
- ): { x: bigint, y: bigint } {
213
- let N = P
214
- let Q: { x: bigint, y: bigint } | null = null
215
-
216
- while (k > BigInt(0)) {
217
- if (k % BigInt(2) === BigInt(1)) {
218
- Q = Q === null ? N : (pointAdd(Q, N) ?? Q)
219
- }
220
- N = pointAdd(N, N) ?? N
221
- k >>= BigInt(1)
222
- }
223
-
224
- if (Q === null) {
225
- throw new Error('Scalar multiplication resulted in an invalid point.')
226
- }
227
-
228
- return Q
229
123
  }
230
124
 
231
- let validSignature = false
232
- while (!validSignature) {
233
- iter += 1
234
- validSignature = true
235
- iter += 1
236
-
237
- // Generate k value
238
- let k = generateK(customK)
239
-
240
- // Truncate k to n bits
241
- k = truncateToN(k, n, true)
242
-
243
- if (k <= one || k >= ns1) {
244
- if (customK instanceof BigNumber) {
245
- throw new Error(
246
- 'Invalid fixed custom K value (must be more than 1 and less than N-1)'
247
- )
248
- } else {
249
- continue
250
- }
251
- }
252
-
253
- const R = scalarMul(k, G)
254
- if (R === null) {
255
- if (customK instanceof BigNumber) {
256
- throw new Error(
257
- 'Invalid fixed custom K value (must not create a point at infinity when multiplied by the generator point)'
258
- )
259
- } else {
260
- continue
261
- }
262
- }
263
-
264
- const r = mod(R.x, n)
265
- if (r === zero) {
266
- if (customK instanceof BigNumber) {
267
- throw new Error(
268
- 'Invalid fixed custom K value (when multiplied by G, the resulting x coordinate mod N must not be zero)'
269
- )
270
- } else {
271
- continue
272
- }
273
- }
274
-
275
- const kInv = modInv(k, n)
276
- const rd = mod(r * d, n)
277
- let s = mod(kInv * (z + rd), n)
278
- if (s === zero) {
279
- if (customK instanceof BigNumber) {
280
- throw new Error(
281
- 'Invalid fixed custom K value (when used with the key, it cannot create a zero value for S)'
282
- )
283
- } else {
284
- continue
285
- }
286
- }
287
-
288
- // Use complement of `s` if it is > n / 2
289
- if (forceLowS && s > n / two) {
290
- s = n - s
291
- }
292
-
293
- // Return signature as BigNumbers
294
- const rbn = new BigNumber(r.toString(16), 16)
295
- const sbn = new BigNumber(s.toString(16), 16)
296
- return new Signature(rbn, sbn)
297
- }
298
- } else {
299
- const curve = new Curve()
300
- msg = truncateToN(msg)
301
-
302
- // Zero-extend key to provide enough entropy
303
- const bytes = curve.n.byteLength()
304
- const bkey = key.toArray('be', bytes)
305
-
306
- // Zero-extend nonce to have the same byte size as N
307
- const nonce = msg.toArray('be', bytes)
308
-
309
- // Instantiate Hmac_DRBG
310
- const drbg = new DRBG(bkey, nonce)
311
-
312
- // Number of bytes to generate
313
- const ns1 = curve.n.subn(1)
314
-
315
- for (let iter = 0; ; iter++) {
316
- // Compute the k-value
317
- let k =
318
- typeof customK === 'function'
319
- ? customK(iter)
320
- : BigNumber.isBN(customK)
321
- ? customK
322
- : new BigNumber(drbg.generate(bytes), 16)
323
- if (k != null) {
324
- k = truncateToN(k, true)
125
+ let s = k.invm(curve.n).mul(r.mul(key).iadd(msg))
126
+ s = s.umod(curve.n)
127
+ if (s.cmpn(0) === 0) {
128
+ if (BigNumber.isBN(customK)) {
129
+ throw new Error(
130
+ 'Invalid fixed custom K value (when used with the key, it cannot create a zero value for S)'
131
+ )
325
132
  } else {
326
- throw new Error('k is undefined')
327
- }
328
- if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) {
329
- if (BigNumber.isBN(customK)) {
330
- throw new Error(
331
- 'Invalid fixed custom K value (must be more than 1 and less than N-1)'
332
- )
333
- } else {
334
- continue
335
- }
336
- }
337
-
338
- const kp = curve.g.mul(k)
339
- if (kp.isInfinity()) {
340
- if (BigNumber.isBN(customK)) {
341
- throw new Error(
342
- 'Invalid fixed custom K value (must not create a point at infinity when multiplied by the generator point)'
343
- )
344
- } else {
345
- continue
346
- }
347
- }
348
-
349
- const kpX = kp.getX()
350
- const r = kpX.umod(curve.n)
351
- if (r.cmpn(0) === 0) {
352
- if (BigNumber.isBN(customK)) {
353
- throw new Error(
354
- 'Invalid fixed custom K value (when multiplied by G, the resulting x coordinate mod N must not be zero)'
355
- )
356
- } else {
357
- continue
358
- }
359
- }
360
-
361
- let s = k.invm(curve.n).mul(r.mul(key).iadd(msg))
362
- s = s.umod(curve.n)
363
- if (s.cmpn(0) === 0) {
364
- if (BigNumber.isBN(customK)) {
365
- throw new Error(
366
- 'Invalid fixed custom K value (when used with the key, it cannot create a zero value for S)'
367
- )
368
- } else {
369
- continue
370
- }
133
+ continue
371
134
  }
135
+ }
372
136
 
373
- // Use complement of `s`, if it is > `n / 2`
374
- if (forceLowS && s.cmp(curve.n.ushrn(1)) > 0) {
375
- s = curve.n.sub(s)
376
- }
377
- return new Signature(r, s)
137
+ // Use complement of `s`, if it is > `n / 2`
138
+ if (forceLowS && s.cmp(curve.n.ushrn(1)) > 0) {
139
+ s = curve.n.sub(s)
378
140
  }
141
+ return new Signature(r, s)
379
142
  }
380
- throw new Error('Failed to generate a valid signature')
381
143
  }
382
144
 
383
145
  /**
@@ -399,222 +161,190 @@ export const sign = (
399
161
  * const isVerified = verify(msg, sig, key)
400
162
  */
401
163
  export const verify = (msg: BigNumber, sig: Signature, key: Point): boolean => {
402
- // Use BigInt for verification opportunistically
403
- if (typeof BigInt === 'function') {
404
- // Curve parameters for secp256k1
405
- const zero = BigInt(0)
406
- const one = BigInt(1)
407
- const two = BigInt(2)
408
- const three = BigInt(3)
409
- const p = BigInt(
410
- '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'
411
- ) // Field prime
412
- const n = BigInt(
413
- '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'
414
- ) // Order of the curve
415
- const G = {
416
- x: BigInt(
417
- '0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'
418
- ),
419
- y: BigInt(
420
- '0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8'
421
- )
422
- }
164
+ // Curve parameters for secp256k1
165
+ const zero = BigInt(0)
166
+ const one = BigInt(1)
167
+ const two = BigInt(2)
168
+ const three = BigInt(3)
169
+ const p = BigInt(
170
+ '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'
171
+ ) // Field prime
172
+ const n = BigInt(
173
+ '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'
174
+ ) // Order of the curve
175
+ const G = {
176
+ x: BigInt(
177
+ '0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'
178
+ ),
179
+ y: BigInt(
180
+ '0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8'
181
+ )
182
+ }
423
183
 
424
- // Modular arithmetic functions
425
- const mod = (a: bigint, m: bigint): bigint => ((a % m) + m) % m
426
- const modInv = (a: bigint, m: bigint): bigint => {
427
- // Extended Euclidean Algorithm for modular inverse
428
- let [oldr, r] = [a, m]
429
- let [olds, s] = [BigInt(1), BigInt(0)]
430
- while (r !== zero) {
431
- const q = oldr / r;
432
- [oldr, r] = [r, oldr - q * r];
433
- [olds, s] = [s, olds - q * s]
434
- }
435
- if (oldr > one) return zero // No inverse
436
- return mod(olds, m)
437
- }
438
- const modMul = (a: bigint, b: bigint, m: bigint): bigint => mod(a * b, m)
439
- const modSub = (a: bigint, b: bigint, m: bigint): bigint => mod(a - b, m)
440
-
441
- // Define constants
442
- const four = BigInt(4)
443
- const eight = BigInt(8)
444
-
445
- // Elliptic curve point operations in Jacobian coordinates
446
- interface JacobianPoint {
447
- X: bigint
448
- Y: bigint
449
- Z: bigint
184
+ // Modular arithmetic functions
185
+ const mod = (a: bigint, m: bigint): bigint => ((a % m) + m) % m
186
+ const modInv = (a: bigint, m: bigint): bigint => {
187
+ // Extended Euclidean Algorithm for modular inverse
188
+ let [oldr, r] = [a, m]
189
+ let [olds, s] = [BigInt(1), BigInt(0)]
190
+ while (r !== zero) {
191
+ const q = oldr / r;
192
+ [oldr, r] = [r, oldr - q * r];
193
+ [olds, s] = [s, olds - q * s]
450
194
  }
195
+ if (oldr > one) return zero // No inverse
196
+ return mod(olds, m)
197
+ }
198
+ const modMul = (a: bigint, b: bigint, m: bigint): bigint => mod(a * b, m)
199
+ const modSub = (a: bigint, b: bigint, m: bigint): bigint => mod(a - b, m)
200
+
201
+ // Define constants
202
+ const four = BigInt(4)
203
+ const eight = BigInt(8)
204
+
205
+ // Elliptic curve point operations in Jacobian coordinates
206
+ interface JacobianPoint {
207
+ X: bigint
208
+ Y: bigint
209
+ Z: bigint
210
+ }
451
211
 
452
- // Point Doubling
453
- const pointDouble = (P: JacobianPoint): JacobianPoint => {
454
- const { X: X1, Y: Y1, Z: Z1 } = P
455
-
456
- if (Y1 === zero) {
457
- return { X: zero, Y: one, Z: zero } // Point at infinity
458
- }
212
+ // Point Doubling
213
+ const pointDouble = (P: JacobianPoint): JacobianPoint => {
214
+ const { X: X1, Y: Y1, Z: Z1 } = P
459
215
 
460
- const Y1sq = modMul(Y1, Y1, p) // Y1^2
461
- const S = modMul(four, modMul(X1, Y1sq, p), p) // S = 4 * X1 * Y1^2
462
- const M = modMul(three, modMul(X1, X1, p), p) // M = 3 * X1^2
463
- const X3 = modSub(modMul(M, M, p), modMul(two, S, p), p) // X3 = M^2 - 2 * S
464
- const Y3 = modSub(
465
- modMul(M, modSub(S, X3, p), p),
466
- modMul(eight, modMul(Y1sq, Y1sq, p), p),
467
- p
468
- ) // Y3 = M * (S - X3) - 8 * Y1^4
469
- const Z3 = modMul(two, modMul(Y1, Z1, p), p) // Z3 = 2 * Y1 * Z1
470
-
471
- return { X: X3, Y: Y3, Z: Z3 }
216
+ if (Y1 === zero) {
217
+ return { X: zero, Y: one, Z: zero } // Point at infinity
472
218
  }
473
219
 
474
- // Point Addition
475
- const pointAdd = (P: JacobianPoint, Q: JacobianPoint): JacobianPoint => {
476
- if (P.Z === zero) return Q
477
- if (Q.Z === zero) return P
478
-
479
- const Z1Z1 = modMul(P.Z, P.Z, p)
480
- const Z2Z2 = modMul(Q.Z, Q.Z, p)
481
- const U1 = modMul(P.X, Z2Z2, p)
482
- const U2 = modMul(Q.X, Z1Z1, p)
483
- const S1 = modMul(P.Y, modMul(Z2Z2, Q.Z, p), p)
484
- const S2 = modMul(Q.Y, modMul(Z1Z1, P.Z, p), p)
485
-
486
- const H = modSub(U2, U1, p)
487
- const r = modSub(S2, S1, p)
488
-
489
- if (H === zero) {
490
- if (r === zero) {
491
- // P == Q
492
- return pointDouble(P)
493
- } else {
494
- // Point at infinity
495
- return { X: zero, Y: one, Z: zero }
496
- }
497
- }
220
+ const Y1sq = modMul(Y1, Y1, p) // Y1^2
221
+ const S = modMul(four, modMul(X1, Y1sq, p), p) // S = 4 * X1 * Y1^2
222
+ const M = modMul(three, modMul(X1, X1, p), p) // M = 3 * X1^2
223
+ const X3 = modSub(modMul(M, M, p), modMul(two, S, p), p) // X3 = M^2 - 2 * S
224
+ const Y3 = modSub(
225
+ modMul(M, modSub(S, X3, p), p),
226
+ modMul(eight, modMul(Y1sq, Y1sq, p), p),
227
+ p
228
+ ) // Y3 = M * (S - X3) - 8 * Y1^4
229
+ const Z3 = modMul(two, modMul(Y1, Z1, p), p) // Z3 = 2 * Y1 * Z1
230
+
231
+ return { X: X3, Y: Y3, Z: Z3 }
232
+ }
498
233
 
499
- const HH = modMul(H, H, p)
500
- const HHH = modMul(H, HH, p)
501
- const V = modMul(U1, HH, p)
234
+ // Point Addition
235
+ const pointAdd = (P: JacobianPoint, Q: JacobianPoint): JacobianPoint => {
236
+ if (P.Z === zero) return Q
237
+ if (Q.Z === zero) return P
502
238
 
503
- const X3 = modSub(modSub(modMul(r, r, p), HHH, p), modMul(two, V, p), p)
504
- const Y3 = modSub(modMul(r, modSub(V, X3, p), p), modMul(S1, HHH, p), p)
505
- const Z3 = modMul(H, modMul(P.Z, Q.Z, p), p)
239
+ const Z1Z1 = modMul(P.Z, P.Z, p)
240
+ const Z2Z2 = modMul(Q.Z, Q.Z, p)
241
+ const U1 = modMul(P.X, Z2Z2, p)
242
+ const U2 = modMul(Q.X, Z1Z1, p)
243
+ const S1 = modMul(P.Y, modMul(Z2Z2, Q.Z, p), p)
244
+ const S2 = modMul(Q.Y, modMul(Z1Z1, P.Z, p), p)
506
245
 
507
- return { X: X3, Y: Y3, Z: Z3 }
508
- }
246
+ const H = modSub(U2, U1, p)
247
+ const r = modSub(S2, S1, p)
509
248
 
510
- // Scalar Multiplication
511
- const scalarMultiply = (
512
- k: bigint,
513
- P: { x: bigint, y: bigint }
514
- ): JacobianPoint => {
515
- const N: JacobianPoint = { X: P.x, Y: P.y, Z: one }
516
- let Q: JacobianPoint = { X: zero, Y: one, Z: zero } // Point at infinity
517
-
518
- const kBin = k.toString(2)
519
- for (let i = 0; i < kBin.length; i++) {
520
- Q = pointDouble(Q)
521
- if (kBin[i] === '1') {
522
- Q = pointAdd(Q, N)
523
- }
249
+ if (H === zero) {
250
+ if (r === zero) {
251
+ // P == Q
252
+ return pointDouble(P)
253
+ } else {
254
+ // Point at infinity
255
+ return { X: zero, Y: one, Z: zero }
524
256
  }
525
- return Q
526
257
  }
527
258
 
528
- // Verify Function Using Jacobian Coordinates
529
- const verifyECDSA = (
530
- hash: bigint,
531
- publicKey: { x: bigint, y: bigint },
532
- signature: { r: bigint, s: bigint }
533
- ): boolean => {
534
- const { r, s } = signature
535
- const z = hash
536
-
537
- // Check r and s are in [1, n - 1]
538
- if (r <= zero || r >= n || s <= zero || s >= n) {
539
- return false
540
- }
541
-
542
- const w = modInv(s, n) // w = s^-1 mod n
543
- if (w === zero) {
544
- return false // No inverse exists
545
- }
546
- const u1 = modMul(z, w, n)
547
- const u2 = modMul(r, w, n)
259
+ const HH = modMul(H, H, p)
260
+ const HHH = modMul(H, HH, p)
261
+ const V = modMul(U1, HH, p)
548
262
 
549
- // Compute point R = u1 * G + u2 * Q
550
- const RG = scalarMultiply(u1, G)
551
- const RQ = scalarMultiply(u2, publicKey)
552
- const R = pointAdd(RG, RQ)
263
+ const X3 = modSub(modSub(modMul(r, r, p), HHH, p), modMul(two, V, p), p)
264
+ const Y3 = modSub(modMul(r, modSub(V, X3, p), p), modMul(S1, HHH, p), p)
265
+ const Z3 = modMul(H, modMul(P.Z, Q.Z, p), p)
553
266
 
554
- if (R.Z === zero) {
555
- // Point at infinity
556
- return false
557
- }
267
+ return { X: X3, Y: Y3, Z: Z3 }
268
+ }
558
269
 
559
- // Compute affine x-coordinate x1 = X / Z^2 mod p
560
- const ZInv = modInv(R.Z, p)
561
- if (ZInv === zero) {
562
- return false // No inverse exists
270
+ // Scalar Multiplication
271
+ const scalarMultiply = (
272
+ k: bigint,
273
+ P: { x: bigint, y: bigint }
274
+ ): JacobianPoint => {
275
+ const N: JacobianPoint = { X: P.x, Y: P.y, Z: one }
276
+ let Q: JacobianPoint = { X: zero, Y: one, Z: zero } // Point at infinity
277
+
278
+ const kBin = k.toString(2)
279
+ for (let i = 0; i < kBin.length; i++) {
280
+ Q = pointDouble(Q)
281
+ if (kBin[i] === '1') {
282
+ Q = pointAdd(Q, N)
563
283
  }
564
- const ZInv2 = modMul(ZInv, ZInv, p)
565
- const x1affine = modMul(R.X, ZInv2, p)
566
-
567
- // Compute v = x1_affine mod n
568
- const v = mod(x1affine, n)
569
-
570
- // Signature is valid if v == r mod n
571
- return v === r
572
284
  }
285
+ return Q
286
+ }
573
287
 
574
- // Convert inputs to BigInt
575
- const hash = BigInt('0x' + msg.toString(16))
576
- if ((key.x == null) || (key.y == null)) {
577
- throw new Error('Invalid public key: missing coordinates.')
288
+ // Verify Function Using Jacobian Coordinates
289
+ const verifyECDSA = (
290
+ hash: bigint,
291
+ publicKey: { x: bigint, y: bigint },
292
+ signature: { r: bigint, s: bigint }
293
+ ): boolean => {
294
+ const { r, s } = signature
295
+ const z = hash
296
+
297
+ // Check r and s are in [1, n - 1]
298
+ if (r <= zero || r >= n || s <= zero || s >= n) {
299
+ return false
578
300
  }
579
301
 
580
- const publicKey = {
581
- x: BigInt('0x' + key.x.toString(16)),
582
- y: BigInt('0x' + key.y.toString(16))
583
- }
584
- const signature = {
585
- r: BigInt('0x' + sig.r.toString(16)),
586
- s: BigInt('0x' + sig.s.toString(16))
302
+ const w = modInv(s, n) // w = s^-1 mod n
303
+ if (w === zero) {
304
+ return false // No inverse exists
587
305
  }
306
+ const u1 = modMul(z, w, n)
307
+ const u2 = modMul(r, w, n)
588
308
 
589
- return verifyECDSA(hash, publicKey, signature)
590
- } else {
591
- const curve = new Curve()
592
- msg = truncateToN(msg)
593
- // Perform primitive values validation
594
- const r = sig.r
595
- const s = sig.s
596
- if (r.cmpn(1) < 0 || r.cmp(curve.n) >= 0) {
309
+ // Compute point R = u1 * G + u2 * Q
310
+ const RG = scalarMultiply(u1, G)
311
+ const RQ = scalarMultiply(u2, publicKey)
312
+ const R = pointAdd(RG, RQ)
313
+
314
+ if (R.Z === zero) {
315
+ // Point at infinity
597
316
  return false
598
317
  }
599
- if (s.cmpn(1) < 0 || s.cmp(curve.n) >= 0) {
600
- return false
318
+
319
+ // Compute affine x-coordinate x1 = X / Z^2 mod p
320
+ const ZInv = modInv(R.Z, p)
321
+ if (ZInv === zero) {
322
+ return false // No inverse exists
601
323
  }
324
+ const ZInv2 = modMul(ZInv, ZInv, p)
325
+ const x1affine = modMul(R.X, ZInv2, p)
602
326
 
603
- // Validate signature
604
- const sinv = s.invm(curve.n)
605
- const u1 = sinv.mul(msg).umod(curve.n)
606
- const u2 = sinv.mul(r).umod(curve.n)
327
+ // Compute v = x1_affine mod n
328
+ const v = mod(x1affine, n)
607
329
 
608
- // NOTE: Greg Maxwell's trick, inspired by:
609
- // https://git.io/vad3K
610
- const p = curve.g.jmulAdd(u1, key, u2)
611
- if (p.isInfinity()) {
612
- return false
613
- }
330
+ // Signature is valid if v == r mod n
331
+ return v === r
332
+ }
333
+
334
+ // Convert inputs to BigInt
335
+ const hash = BigInt('0x' + msg.toString(16))
336
+ if ((key.x == null) || (key.y == null)) {
337
+ throw new Error('Invalid public key: missing coordinates.')
338
+ }
614
339
 
615
- // Compare `p.x` of Jacobian point with `r`,
616
- // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the
617
- // inverse of `p.z^2`
618
- return p.eqXToP(r)
340
+ const publicKey = {
341
+ x: BigInt('0x' + key.x.toString(16)),
342
+ y: BigInt('0x' + key.y.toString(16))
619
343
  }
344
+ const signature = {
345
+ r: BigInt('0x' + sig.r.toString(16)),
346
+ s: BigInt('0x' + sig.s.toString(16))
347
+ }
348
+
349
+ return verifyECDSA(hash, publicKey, signature)
620
350
  }