@bsv/sdk 1.6.15 → 1.6.17
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.
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/auth/Peer.js +16 -25
- package/dist/cjs/src/auth/Peer.js.map +1 -1
- package/dist/cjs/src/auth/SessionManager.js +2 -4
- package/dist/cjs/src/auth/SessionManager.js.map +1 -1
- package/dist/cjs/src/auth/certificates/Certificate.js +2 -4
- package/dist/cjs/src/auth/certificates/Certificate.js.map +1 -1
- package/dist/cjs/src/auth/certificates/MasterCertificate.js +1 -1
- package/dist/cjs/src/auth/certificates/MasterCertificate.js.map +1 -1
- package/dist/cjs/src/auth/certificates/__tests/CompletedProtoWallet.js +1 -1
- package/dist/cjs/src/auth/certificates/__tests/CompletedProtoWallet.js.map +1 -1
- package/dist/cjs/src/auth/clients/AuthFetch.js +2 -4
- package/dist/cjs/src/auth/clients/AuthFetch.js.map +1 -1
- package/dist/cjs/src/compat/ECIES.js +1 -1
- package/dist/cjs/src/compat/ECIES.js.map +1 -1
- package/dist/cjs/src/compat/Mnemonic.js +2 -2
- package/dist/cjs/src/compat/Mnemonic.js.map +1 -1
- package/dist/cjs/src/identity/IdentityClient.js +1 -1
- package/dist/cjs/src/identity/IdentityClient.js.map +1 -1
- package/dist/cjs/src/kvstore/LocalKVStore.js +1 -2
- package/dist/cjs/src/kvstore/LocalKVStore.js.map +1 -1
- package/dist/cjs/src/overlay-tools/LookupResolver.js +6 -8
- package/dist/cjs/src/overlay-tools/LookupResolver.js.map +1 -1
- package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js +9 -10
- package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js.map +1 -1
- package/dist/cjs/src/primitives/AESGCM.js +1 -2
- package/dist/cjs/src/primitives/AESGCM.js.map +1 -1
- package/dist/cjs/src/primitives/BigNumber.js +2 -3
- package/dist/cjs/src/primitives/BigNumber.js.map +1 -1
- package/dist/cjs/src/primitives/Curve.js +2 -3
- package/dist/cjs/src/primitives/Curve.js.map +1 -1
- package/dist/cjs/src/primitives/ECDSA.js +174 -396
- package/dist/cjs/src/primitives/ECDSA.js.map +1 -1
- package/dist/cjs/src/primitives/JacobianPoint.js +1 -2
- package/dist/cjs/src/primitives/JacobianPoint.js.map +1 -1
- package/dist/cjs/src/primitives/Point.js +279 -126
- package/dist/cjs/src/primitives/Point.js.map +1 -1
- package/dist/cjs/src/primitives/Polynomial.js +1 -1
- package/dist/cjs/src/primitives/Polynomial.js.map +1 -1
- package/dist/cjs/src/primitives/PrivateKey.js +19 -2
- package/dist/cjs/src/primitives/PrivateKey.js.map +1 -1
- package/dist/cjs/src/primitives/PublicKey.js +19 -2
- package/dist/cjs/src/primitives/PublicKey.js.map +1 -1
- package/dist/cjs/src/primitives/Random.js +1 -2
- package/dist/cjs/src/primitives/Random.js.map +1 -1
- package/dist/cjs/src/primitives/TransactionSignature.js +5 -7
- package/dist/cjs/src/primitives/TransactionSignature.js.map +1 -1
- package/dist/cjs/src/primitives/utils.js +1 -2
- package/dist/cjs/src/primitives/utils.js.map +1 -1
- package/dist/cjs/src/registry/RegistryClient.js +2 -4
- package/dist/cjs/src/registry/RegistryClient.js.map +1 -1
- package/dist/cjs/src/script/Spend.js +1 -2
- package/dist/cjs/src/script/Spend.js.map +1 -1
- package/dist/cjs/src/script/templates/P2PKH.js +4 -4
- package/dist/cjs/src/script/templates/P2PKH.js.map +1 -1
- package/dist/cjs/src/script/templates/PushDrop.js +7 -8
- package/dist/cjs/src/script/templates/PushDrop.js.map +1 -1
- package/dist/cjs/src/script/templates/RPuzzle.js +7 -6
- package/dist/cjs/src/script/templates/RPuzzle.js.map +1 -1
- package/dist/cjs/src/storage/StorageDownloader.js +1 -1
- package/dist/cjs/src/storage/StorageDownloader.js.map +1 -1
- package/dist/cjs/src/storage/StorageUploader.js +6 -9
- package/dist/cjs/src/storage/StorageUploader.js.map +1 -1
- package/dist/cjs/src/transaction/Beef.js +2 -3
- package/dist/cjs/src/transaction/Beef.js.map +1 -1
- package/dist/cjs/src/transaction/MerklePath.js +9 -12
- package/dist/cjs/src/transaction/MerklePath.js.map +1 -1
- package/dist/cjs/src/transaction/Transaction.js +15 -22
- package/dist/cjs/src/transaction/Transaction.js.map +1 -1
- package/dist/cjs/src/transaction/broadcasters/ARC.js +3 -3
- package/dist/cjs/src/transaction/broadcasters/ARC.js.map +1 -1
- package/dist/cjs/src/transaction/broadcasters/Teranode.js +2 -3
- package/dist/cjs/src/transaction/broadcasters/Teranode.js.map +1 -1
- package/dist/cjs/src/transaction/broadcasters/WhatsOnChainBroadcaster.js +2 -3
- package/dist/cjs/src/transaction/broadcasters/WhatsOnChainBroadcaster.js.map +1 -1
- package/dist/cjs/src/transaction/chaintrackers/BlockHeadersService.js +2 -2
- package/dist/cjs/src/transaction/chaintrackers/BlockHeadersService.js.map +1 -1
- package/dist/cjs/src/transaction/chaintrackers/WhatsOnChain.js +2 -2
- package/dist/cjs/src/transaction/chaintrackers/WhatsOnChain.js.map +1 -1
- package/dist/cjs/src/transaction/http/FetchHttpClient.js +1 -2
- package/dist/cjs/src/transaction/http/FetchHttpClient.js.map +1 -1
- package/dist/cjs/src/wallet/CachedKeyDeriver.js +13 -2
- package/dist/cjs/src/wallet/CachedKeyDeriver.js.map +1 -1
- package/dist/cjs/src/wallet/KeyDeriver.js +12 -8
- package/dist/cjs/src/wallet/KeyDeriver.js.map +1 -1
- package/dist/cjs/src/wallet/ProtoWallet.js +26 -27
- package/dist/cjs/src/wallet/ProtoWallet.js.map +1 -1
- package/dist/cjs/src/wallet/substrates/HTTPWalletJSON.js +2 -3
- package/dist/cjs/src/wallet/substrates/HTTPWalletJSON.js.map +1 -1
- package/dist/cjs/src/wallet/substrates/HTTPWalletWire.js +1 -1
- package/dist/cjs/src/wallet/substrates/HTTPWalletWire.js.map +1 -1
- package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js +12 -19
- package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/auth/certificates/__tests/CompletedProtoWallet.js +2 -2
- package/dist/esm/src/auth/certificates/__tests/CompletedProtoWallet.js.map +1 -1
- package/dist/esm/src/primitives/ECDSA.js +174 -395
- package/dist/esm/src/primitives/ECDSA.js.map +1 -1
- package/dist/esm/src/primitives/Point.js +254 -91
- package/dist/esm/src/primitives/Point.js.map +1 -1
- package/dist/esm/src/primitives/PrivateKey.js +19 -2
- package/dist/esm/src/primitives/PrivateKey.js.map +1 -1
- package/dist/esm/src/primitives/PublicKey.js +19 -2
- package/dist/esm/src/primitives/PublicKey.js.map +1 -1
- package/dist/esm/src/wallet/CachedKeyDeriver.js +20 -1
- package/dist/esm/src/wallet/CachedKeyDeriver.js.map +1 -1
- package/dist/esm/src/wallet/KeyDeriver.js +14 -6
- package/dist/esm/src/wallet/KeyDeriver.js.map +1 -1
- package/dist/esm/src/wallet/ProtoWallet.js +2 -2
- package/dist/esm/src/wallet/ProtoWallet.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/auth/certificates/__tests/CompletedProtoWallet.d.ts.map +1 -1
- package/dist/types/src/primitives/ECDSA.d.ts.map +1 -1
- package/dist/types/src/primitives/Point.d.ts.map +1 -1
- package/dist/types/src/primitives/PrivateKey.d.ts +3 -1
- package/dist/types/src/primitives/PrivateKey.d.ts.map +1 -1
- package/dist/types/src/primitives/PublicKey.d.ts +3 -1
- package/dist/types/src/primitives/PublicKey.d.ts.map +1 -1
- package/dist/types/src/wallet/CachedKeyDeriver.d.ts +10 -2
- package/dist/types/src/wallet/CachedKeyDeriver.d.ts.map +1 -1
- package/dist/types/src/wallet/KeyDeriver.d.ts +5 -2
- package/dist/types/src/wallet/KeyDeriver.d.ts.map +1 -1
- package/dist/types/src/wallet/ProtoWallet.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +1 -1
- package/docs/reference/primitives.md +179 -383
- package/docs/reference/wallet.md +25 -6
- package/package.json +1 -1
- package/src/auth/certificates/__tests/CompletedProtoWallet.ts +3 -2
- package/src/primitives/ECDSA.ts +218 -488
- package/src/primitives/Point.ts +291 -94
- package/src/primitives/PrivateKey.ts +22 -2
- package/src/primitives/PublicKey.ts +22 -2
- package/src/transaction/__tests/Transaction.test.ts +1 -1
- package/src/wallet/CachedKeyDeriver.ts +32 -8
- package/src/wallet/KeyDeriver.ts +24 -7
- package/src/wallet/ProtoWallet.ts +3 -2
- package/src/wallet/__tests/ProtoWallet.test.ts +46 -1
package/src/primitives/ECDSA.ts
CHANGED
|
@@ -60,324 +60,86 @@ export const sign = (
|
|
|
60
60
|
forceLowS: boolean = false,
|
|
61
61
|
customK?: BigNumber | ((iter: number) => BigNumber)
|
|
62
62
|
): Signature => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (
|
|
88
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
98
|
+
continue
|
|
132
99
|
}
|
|
133
100
|
}
|
|
134
101
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
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
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
-
|
|
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
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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
|
-
|
|
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
|
-
|
|
374
|
-
|
|
375
|
-
|
|
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
|
-
//
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
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
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
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
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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
|
-
|
|
461
|
-
|
|
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
|
-
//
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
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
|
-
|
|
500
|
-
|
|
501
|
-
|
|
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
|
-
|
|
504
|
-
|
|
505
|
-
|
|
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
|
-
|
|
508
|
-
|
|
246
|
+
const H = modSub(U2, U1, p)
|
|
247
|
+
const r = modSub(S2, S1, p)
|
|
509
248
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
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
|
-
|
|
529
|
-
const
|
|
530
|
-
|
|
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
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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
|
-
|
|
555
|
-
|
|
556
|
-
return false
|
|
557
|
-
}
|
|
267
|
+
return { X: X3, Y: Y3, Z: Z3 }
|
|
268
|
+
}
|
|
558
269
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
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
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
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
|
|
581
|
-
|
|
582
|
-
|
|
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
|
-
|
|
590
|
-
|
|
591
|
-
const
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
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
|
-
|
|
600
|
-
|
|
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
|
-
//
|
|
604
|
-
const
|
|
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
|
-
//
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
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
|
-
|
|
616
|
-
|
|
617
|
-
|
|
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
|
}
|