@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.
- 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/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 +10 -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 +217 -181
- 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/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 +1 -1
- package/dist/cjs/src/wallet/CachedKeyDeriver.js.map +1 -1
- package/dist/cjs/src/wallet/KeyDeriver.js +4 -3
- package/dist/cjs/src/wallet/KeyDeriver.js.map +1 -1
- package/dist/cjs/src/wallet/ProtoWallet.js +21 -25
- 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/overlay-tools/LookupResolver.js +4 -0
- package/dist/esm/src/overlay-tools/LookupResolver.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 +192 -146
- package/dist/esm/src/primitives/Point.js.map +1 -1
- package/dist/esm/src/wallet/KeyDeriver.js +3 -1
- package/dist/esm/src/wallet/KeyDeriver.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/overlay-tools/LookupResolver.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/wallet/KeyDeriver.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 +165 -377
- package/package.json +1 -1
- package/src/overlay-tools/LookupResolver.ts +5 -0
- package/src/primitives/ECDSA.ts +218 -488
- package/src/primitives/Point.ts +212 -162
- package/src/transaction/__tests/Transaction.test.ts +1 -1
- package/src/wallet/KeyDeriver.ts +2 -1
- package/src/wallet/__tests/ProtoWallet.test.ts +46 -1
|
@@ -55,265 +55,73 @@ function truncateToN(msg, truncOnly, curve = new Curve_js_1.default()) {
|
|
|
55
55
|
* const signature = sign(msg, key)
|
|
56
56
|
*/
|
|
57
57
|
const sign = (msg, key, forceLowS = false, customK) => {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
58
|
+
const curve = new Curve_js_1.default();
|
|
59
|
+
msg = truncateToN(msg);
|
|
60
|
+
// Zero-extend key to provide enough entropy
|
|
61
|
+
const bytes = curve.n.byteLength();
|
|
62
|
+
const bkey = key.toArray('be', bytes);
|
|
63
|
+
// Zero-extend nonce to have the same byte size as N
|
|
64
|
+
const nonce = msg.toArray('be', bytes);
|
|
65
|
+
// Instantiate Hmac_DRBG
|
|
66
|
+
const drbg = new DRBG_js_1.default(bkey, nonce);
|
|
67
|
+
// Number of bytes to generate
|
|
68
|
+
const ns1 = curve.n.subn(1);
|
|
69
|
+
for (let iter = 0;; iter++) {
|
|
70
|
+
// Compute the k-value
|
|
71
|
+
let k = typeof customK === 'function'
|
|
72
|
+
? customK(iter)
|
|
73
|
+
: BigNumber_js_1.default.isBN(customK)
|
|
74
|
+
? customK
|
|
75
|
+
: new BigNumber_js_1.default(drbg.generate(bytes), 16);
|
|
76
|
+
if (k != null) {
|
|
77
|
+
k = truncateToN(k, true);
|
|
74
78
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const hex = value.toString(16).padStart(length * 2, '0');
|
|
78
|
-
const bytes = new Uint8Array(length);
|
|
79
|
-
for (let i = 0; i < length; i++) {
|
|
80
|
-
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
|
|
81
|
-
}
|
|
82
|
-
return bytes;
|
|
79
|
+
else {
|
|
80
|
+
throw new Error('k is undefined');
|
|
83
81
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
// Zero-extend nonce to have the same byte size as N
|
|
88
|
-
const nonce = bigIntToBytes(z, bytes); // 'z' is the message hash BigInt
|
|
89
|
-
// Instantiate Hmac_DRBG
|
|
90
|
-
const drbg = new DRBG_js_1.default(Array.from(bkey), Array.from(nonce));
|
|
91
|
-
// Number of bytes to generate
|
|
92
|
-
const ns1 = n - one;
|
|
93
|
-
let iter = 0;
|
|
94
|
-
// Truncate to N function for BigInt
|
|
95
|
-
function truncateToN(k, n, truncOnly = true) {
|
|
96
|
-
const kBitLength = k.toString(2).length;
|
|
97
|
-
const nBitLength = n.toString(2).length;
|
|
98
|
-
const delta = kBitLength - nBitLength;
|
|
99
|
-
if (delta > 0) {
|
|
100
|
-
k = k >> BigInt(delta);
|
|
101
|
-
}
|
|
102
|
-
if (!truncOnly && k >= n) {
|
|
103
|
-
return k - n;
|
|
82
|
+
if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) {
|
|
83
|
+
if (BigNumber_js_1.default.isBN(customK)) {
|
|
84
|
+
throw new Error('Invalid fixed custom K value (must be more than 1 and less than N-1)');
|
|
104
85
|
}
|
|
105
86
|
else {
|
|
106
|
-
|
|
87
|
+
continue;
|
|
107
88
|
}
|
|
108
89
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
// Convert k_bn (BigNumber) to BigInt
|
|
114
|
-
const kstr = kbn.toString(16);
|
|
115
|
-
return BigInt('0x' + kstr);
|
|
116
|
-
}
|
|
117
|
-
else if ((customK != null) && BigNumber_js_1.default.isBN(customK)) {
|
|
118
|
-
// Use customK provided, convert to BigInt
|
|
119
|
-
const kstr = customK.toString(16);
|
|
120
|
-
return BigInt('0x' + kstr);
|
|
90
|
+
const kp = curve.g.mul(k);
|
|
91
|
+
if (kp.isInfinity()) {
|
|
92
|
+
if (BigNumber_js_1.default.isBN(customK)) {
|
|
93
|
+
throw new Error('Invalid fixed custom K value (must not create a point at infinity when multiplied by the generator point)');
|
|
121
94
|
}
|
|
122
95
|
else {
|
|
123
|
-
|
|
124
|
-
const khex = drbg.generate(bytes); // Generate hex string
|
|
125
|
-
return BigInt('0x' + khex);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
// Modular arithmetic functions
|
|
129
|
-
function mod(a, m) {
|
|
130
|
-
return ((a % m) + m) % m;
|
|
131
|
-
}
|
|
132
|
-
function modInv(a, m) {
|
|
133
|
-
let lm = one;
|
|
134
|
-
let hm = zero;
|
|
135
|
-
let low = mod(a, m);
|
|
136
|
-
let high = m;
|
|
137
|
-
while (low > one) {
|
|
138
|
-
const r = high / low;
|
|
139
|
-
const nm = hm - lm * r;
|
|
140
|
-
const neww = high - low * r;
|
|
141
|
-
hm = lm;
|
|
142
|
-
lm = nm;
|
|
143
|
-
high = low;
|
|
144
|
-
low = neww;
|
|
96
|
+
continue;
|
|
145
97
|
}
|
|
146
|
-
return mod(lm, m);
|
|
147
98
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (
|
|
152
|
-
|
|
153
|
-
if (P.x === Q.x && P.y === mod(-Q.y, p)) {
|
|
154
|
-
return null; // Point at infinity
|
|
155
|
-
}
|
|
156
|
-
let m;
|
|
157
|
-
if (P.x === Q.x && P.y === Q.y) {
|
|
158
|
-
// Point doubling
|
|
159
|
-
if (P.y === zero) {
|
|
160
|
-
return null; // Point at infinity
|
|
161
|
-
}
|
|
162
|
-
const numerator = mod(BigInt(3) * P.x * P.x, p); // 3 * x^2
|
|
163
|
-
const denominator = modInv(two * P.y, p);
|
|
164
|
-
m = mod(numerator * denominator, p);
|
|
99
|
+
const kpX = kp.getX();
|
|
100
|
+
const r = kpX.umod(curve.n);
|
|
101
|
+
if (r.cmpn(0) === 0) {
|
|
102
|
+
if (BigNumber_js_1.default.isBN(customK)) {
|
|
103
|
+
throw new Error('Invalid fixed custom K value (when multiplied by G, the resulting x coordinate mod N must not be zero)');
|
|
165
104
|
}
|
|
166
105
|
else {
|
|
167
|
-
|
|
168
|
-
const denominator = modInv(Q.x - P.x, p);
|
|
169
|
-
m = mod(numerator * denominator, p);
|
|
170
|
-
}
|
|
171
|
-
const xR = mod(m * m - P.x - Q.x, p);
|
|
172
|
-
const yR = mod(m * (P.x - xR) - P.y, p);
|
|
173
|
-
return { x: xR, y: yR };
|
|
174
|
-
}
|
|
175
|
-
function scalarMul(k, P) {
|
|
176
|
-
var _a, _b;
|
|
177
|
-
let N = P;
|
|
178
|
-
let Q = null;
|
|
179
|
-
while (k > BigInt(0)) {
|
|
180
|
-
if (k % BigInt(2) === BigInt(1)) {
|
|
181
|
-
Q = Q === null ? N : ((_a = pointAdd(Q, N)) !== null && _a !== void 0 ? _a : Q);
|
|
182
|
-
}
|
|
183
|
-
N = (_b = pointAdd(N, N)) !== null && _b !== void 0 ? _b : N;
|
|
184
|
-
k >>= BigInt(1);
|
|
185
|
-
}
|
|
186
|
-
if (Q === null) {
|
|
187
|
-
throw new Error('Scalar multiplication resulted in an invalid point.');
|
|
106
|
+
continue;
|
|
188
107
|
}
|
|
189
|
-
return Q;
|
|
190
|
-
}
|
|
191
|
-
let validSignature = false;
|
|
192
|
-
while (!validSignature) {
|
|
193
|
-
iter += 1;
|
|
194
|
-
validSignature = true;
|
|
195
|
-
iter += 1;
|
|
196
|
-
// Generate k value
|
|
197
|
-
let k = generateK(customK);
|
|
198
|
-
// Truncate k to n bits
|
|
199
|
-
k = truncateToN(k, n, true);
|
|
200
|
-
if (k <= one || k >= ns1) {
|
|
201
|
-
if (customK instanceof BigNumber_js_1.default) {
|
|
202
|
-
throw new Error('Invalid fixed custom K value (must be more than 1 and less than N-1)');
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
continue;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
const R = scalarMul(k, G);
|
|
209
|
-
if (R === null) {
|
|
210
|
-
if (customK instanceof BigNumber_js_1.default) {
|
|
211
|
-
throw new Error('Invalid fixed custom K value (must not create a point at infinity when multiplied by the generator point)');
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
continue;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
const r = mod(R.x, n);
|
|
218
|
-
if (r === zero) {
|
|
219
|
-
if (customK instanceof BigNumber_js_1.default) {
|
|
220
|
-
throw new Error('Invalid fixed custom K value (when multiplied by G, the resulting x coordinate mod N must not be zero)');
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
const kInv = modInv(k, n);
|
|
227
|
-
const rd = mod(r * d, n);
|
|
228
|
-
let s = mod(kInv * (z + rd), n);
|
|
229
|
-
if (s === zero) {
|
|
230
|
-
if (customK instanceof BigNumber_js_1.default) {
|
|
231
|
-
throw new Error('Invalid fixed custom K value (when used with the key, it cannot create a zero value for S)');
|
|
232
|
-
}
|
|
233
|
-
else {
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
// Use complement of `s` if it is > n / 2
|
|
238
|
-
if (forceLowS && s > n / two) {
|
|
239
|
-
s = n - s;
|
|
240
|
-
}
|
|
241
|
-
// Return signature as BigNumbers
|
|
242
|
-
const rbn = new BigNumber_js_1.default(r.toString(16), 16);
|
|
243
|
-
const sbn = new BigNumber_js_1.default(s.toString(16), 16);
|
|
244
|
-
return new Signature_js_1.default(rbn, sbn);
|
|
245
108
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const bytes = curve.n.byteLength();
|
|
252
|
-
const bkey = key.toArray('be', bytes);
|
|
253
|
-
// Zero-extend nonce to have the same byte size as N
|
|
254
|
-
const nonce = msg.toArray('be', bytes);
|
|
255
|
-
// Instantiate Hmac_DRBG
|
|
256
|
-
const drbg = new DRBG_js_1.default(bkey, nonce);
|
|
257
|
-
// Number of bytes to generate
|
|
258
|
-
const ns1 = curve.n.subn(1);
|
|
259
|
-
for (let iter = 0;; iter++) {
|
|
260
|
-
// Compute the k-value
|
|
261
|
-
let k = typeof customK === 'function'
|
|
262
|
-
? customK(iter)
|
|
263
|
-
: BigNumber_js_1.default.isBN(customK)
|
|
264
|
-
? customK
|
|
265
|
-
: new BigNumber_js_1.default(drbg.generate(bytes), 16);
|
|
266
|
-
if (k != null) {
|
|
267
|
-
k = truncateToN(k, true);
|
|
109
|
+
let s = k.invm(curve.n).mul(r.mul(key).iadd(msg));
|
|
110
|
+
s = s.umod(curve.n);
|
|
111
|
+
if (s.cmpn(0) === 0) {
|
|
112
|
+
if (BigNumber_js_1.default.isBN(customK)) {
|
|
113
|
+
throw new Error('Invalid fixed custom K value (when used with the key, it cannot create a zero value for S)');
|
|
268
114
|
}
|
|
269
115
|
else {
|
|
270
|
-
|
|
116
|
+
continue;
|
|
271
117
|
}
|
|
272
|
-
if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) {
|
|
273
|
-
if (BigNumber_js_1.default.isBN(customK)) {
|
|
274
|
-
throw new Error('Invalid fixed custom K value (must be more than 1 and less than N-1)');
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
continue;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
const kp = curve.g.mul(k);
|
|
281
|
-
if (kp.isInfinity()) {
|
|
282
|
-
if (BigNumber_js_1.default.isBN(customK)) {
|
|
283
|
-
throw new Error('Invalid fixed custom K value (must not create a point at infinity when multiplied by the generator point)');
|
|
284
|
-
}
|
|
285
|
-
else {
|
|
286
|
-
continue;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
const kpX = kp.getX();
|
|
290
|
-
const r = kpX.umod(curve.n);
|
|
291
|
-
if (r.cmpn(0) === 0) {
|
|
292
|
-
if (BigNumber_js_1.default.isBN(customK)) {
|
|
293
|
-
throw new Error('Invalid fixed custom K value (when multiplied by G, the resulting x coordinate mod N must not be zero)');
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
continue;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
let s = k.invm(curve.n).mul(r.mul(key).iadd(msg));
|
|
300
|
-
s = s.umod(curve.n);
|
|
301
|
-
if (s.cmpn(0) === 0) {
|
|
302
|
-
if (BigNumber_js_1.default.isBN(customK)) {
|
|
303
|
-
throw new Error('Invalid fixed custom K value (when used with the key, it cannot create a zero value for S)');
|
|
304
|
-
}
|
|
305
|
-
else {
|
|
306
|
-
continue;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
// Use complement of `s`, if it is > `n / 2`
|
|
310
|
-
if (forceLowS && s.cmp(curve.n.ushrn(1)) > 0) {
|
|
311
|
-
s = curve.n.sub(s);
|
|
312
|
-
}
|
|
313
|
-
return new Signature_js_1.default(r, s);
|
|
314
118
|
}
|
|
119
|
+
// Use complement of `s`, if it is > `n / 2`
|
|
120
|
+
if (forceLowS && s.cmp(curve.n.ushrn(1)) > 0) {
|
|
121
|
+
s = curve.n.sub(s);
|
|
122
|
+
}
|
|
123
|
+
return new Signature_js_1.default(r, s);
|
|
315
124
|
}
|
|
316
|
-
throw new Error('Failed to generate a valid signature');
|
|
317
125
|
};
|
|
318
126
|
exports.sign = sign;
|
|
319
127
|
/**
|
|
@@ -335,174 +143,144 @@ exports.sign = sign;
|
|
|
335
143
|
* const isVerified = verify(msg, sig, key)
|
|
336
144
|
*/
|
|
337
145
|
const verify = (msg, sig, key) => {
|
|
338
|
-
//
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
const pointAdd = (P, Q) => {
|
|
387
|
-
if (P.Z === zero)
|
|
388
|
-
return Q;
|
|
389
|
-
if (Q.Z === zero)
|
|
390
|
-
return P;
|
|
391
|
-
const Z1Z1 = modMul(P.Z, P.Z, p);
|
|
392
|
-
const Z2Z2 = modMul(Q.Z, Q.Z, p);
|
|
393
|
-
const U1 = modMul(P.X, Z2Z2, p);
|
|
394
|
-
const U2 = modMul(Q.X, Z1Z1, p);
|
|
395
|
-
const S1 = modMul(P.Y, modMul(Z2Z2, Q.Z, p), p);
|
|
396
|
-
const S2 = modMul(Q.Y, modMul(Z1Z1, P.Z, p), p);
|
|
397
|
-
const H = modSub(U2, U1, p);
|
|
398
|
-
const r = modSub(S2, S1, p);
|
|
399
|
-
if (H === zero) {
|
|
400
|
-
if (r === zero) {
|
|
401
|
-
// P == Q
|
|
402
|
-
return pointDouble(P);
|
|
403
|
-
}
|
|
404
|
-
else {
|
|
405
|
-
// Point at infinity
|
|
406
|
-
return { X: zero, Y: one, Z: zero };
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
const HH = modMul(H, H, p);
|
|
410
|
-
const HHH = modMul(H, HH, p);
|
|
411
|
-
const V = modMul(U1, HH, p);
|
|
412
|
-
const X3 = modSub(modSub(modMul(r, r, p), HHH, p), modMul(two, V, p), p);
|
|
413
|
-
const Y3 = modSub(modMul(r, modSub(V, X3, p), p), modMul(S1, HHH, p), p);
|
|
414
|
-
const Z3 = modMul(H, modMul(P.Z, Q.Z, p), p);
|
|
415
|
-
return { X: X3, Y: Y3, Z: Z3 };
|
|
416
|
-
};
|
|
417
|
-
// Scalar Multiplication
|
|
418
|
-
const scalarMultiply = (k, P) => {
|
|
419
|
-
const N = { X: P.x, Y: P.y, Z: one };
|
|
420
|
-
let Q = { X: zero, Y: one, Z: zero }; // Point at infinity
|
|
421
|
-
const kBin = k.toString(2);
|
|
422
|
-
for (let i = 0; i < kBin.length; i++) {
|
|
423
|
-
Q = pointDouble(Q);
|
|
424
|
-
if (kBin[i] === '1') {
|
|
425
|
-
Q = pointAdd(Q, N);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
146
|
+
// Curve parameters for secp256k1
|
|
147
|
+
const zero = BigInt(0);
|
|
148
|
+
const one = BigInt(1);
|
|
149
|
+
const two = BigInt(2);
|
|
150
|
+
const three = BigInt(3);
|
|
151
|
+
const p = BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'); // Field prime
|
|
152
|
+
const n = BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'); // Order of the curve
|
|
153
|
+
const G = {
|
|
154
|
+
x: BigInt('0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'),
|
|
155
|
+
y: BigInt('0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8')
|
|
156
|
+
};
|
|
157
|
+
// Modular arithmetic functions
|
|
158
|
+
const mod = (a, m) => ((a % m) + m) % m;
|
|
159
|
+
const modInv = (a, m) => {
|
|
160
|
+
// Extended Euclidean Algorithm for modular inverse
|
|
161
|
+
let [oldr, r] = [a, m];
|
|
162
|
+
let [olds, s] = [BigInt(1), BigInt(0)];
|
|
163
|
+
while (r !== zero) {
|
|
164
|
+
const q = oldr / r;
|
|
165
|
+
[oldr, r] = [r, oldr - q * r];
|
|
166
|
+
[olds, s] = [s, olds - q * s];
|
|
167
|
+
}
|
|
168
|
+
if (oldr > one)
|
|
169
|
+
return zero; // No inverse
|
|
170
|
+
return mod(olds, m);
|
|
171
|
+
};
|
|
172
|
+
const modMul = (a, b, m) => mod(a * b, m);
|
|
173
|
+
const modSub = (a, b, m) => mod(a - b, m);
|
|
174
|
+
// Define constants
|
|
175
|
+
const four = BigInt(4);
|
|
176
|
+
const eight = BigInt(8);
|
|
177
|
+
// Point Doubling
|
|
178
|
+
const pointDouble = (P) => {
|
|
179
|
+
const { X: X1, Y: Y1, Z: Z1 } = P;
|
|
180
|
+
if (Y1 === zero) {
|
|
181
|
+
return { X: zero, Y: one, Z: zero }; // Point at infinity
|
|
182
|
+
}
|
|
183
|
+
const Y1sq = modMul(Y1, Y1, p); // Y1^2
|
|
184
|
+
const S = modMul(four, modMul(X1, Y1sq, p), p); // S = 4 * X1 * Y1^2
|
|
185
|
+
const M = modMul(three, modMul(X1, X1, p), p); // M = 3 * X1^2
|
|
186
|
+
const X3 = modSub(modMul(M, M, p), modMul(two, S, p), p); // X3 = M^2 - 2 * S
|
|
187
|
+
const Y3 = modSub(modMul(M, modSub(S, X3, p), p), modMul(eight, modMul(Y1sq, Y1sq, p), p), p); // Y3 = M * (S - X3) - 8 * Y1^4
|
|
188
|
+
const Z3 = modMul(two, modMul(Y1, Z1, p), p); // Z3 = 2 * Y1 * Z1
|
|
189
|
+
return { X: X3, Y: Y3, Z: Z3 };
|
|
190
|
+
};
|
|
191
|
+
// Point Addition
|
|
192
|
+
const pointAdd = (P, Q) => {
|
|
193
|
+
if (P.Z === zero)
|
|
428
194
|
return Q;
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
195
|
+
if (Q.Z === zero)
|
|
196
|
+
return P;
|
|
197
|
+
const Z1Z1 = modMul(P.Z, P.Z, p);
|
|
198
|
+
const Z2Z2 = modMul(Q.Z, Q.Z, p);
|
|
199
|
+
const U1 = modMul(P.X, Z2Z2, p);
|
|
200
|
+
const U2 = modMul(Q.X, Z1Z1, p);
|
|
201
|
+
const S1 = modMul(P.Y, modMul(Z2Z2, Q.Z, p), p);
|
|
202
|
+
const S2 = modMul(Q.Y, modMul(Z1Z1, P.Z, p), p);
|
|
203
|
+
const H = modSub(U2, U1, p);
|
|
204
|
+
const r = modSub(S2, S1, p);
|
|
205
|
+
if (H === zero) {
|
|
206
|
+
if (r === zero) {
|
|
207
|
+
// P == Q
|
|
208
|
+
return pointDouble(P);
|
|
441
209
|
}
|
|
442
|
-
|
|
443
|
-
const u2 = modMul(r, w, n);
|
|
444
|
-
// Compute point R = u1 * G + u2 * Q
|
|
445
|
-
const RG = scalarMultiply(u1, G);
|
|
446
|
-
const RQ = scalarMultiply(u2, publicKey);
|
|
447
|
-
const R = pointAdd(RG, RQ);
|
|
448
|
-
if (R.Z === zero) {
|
|
210
|
+
else {
|
|
449
211
|
// Point at infinity
|
|
450
|
-
return
|
|
212
|
+
return { X: zero, Y: one, Z: zero };
|
|
451
213
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
214
|
+
}
|
|
215
|
+
const HH = modMul(H, H, p);
|
|
216
|
+
const HHH = modMul(H, HH, p);
|
|
217
|
+
const V = modMul(U1, HH, p);
|
|
218
|
+
const X3 = modSub(modSub(modMul(r, r, p), HHH, p), modMul(two, V, p), p);
|
|
219
|
+
const Y3 = modSub(modMul(r, modSub(V, X3, p), p), modMul(S1, HHH, p), p);
|
|
220
|
+
const Z3 = modMul(H, modMul(P.Z, Q.Z, p), p);
|
|
221
|
+
return { X: X3, Y: Y3, Z: Z3 };
|
|
222
|
+
};
|
|
223
|
+
// Scalar Multiplication
|
|
224
|
+
const scalarMultiply = (k, P) => {
|
|
225
|
+
const N = { X: P.x, Y: P.y, Z: one };
|
|
226
|
+
let Q = { X: zero, Y: one, Z: zero }; // Point at infinity
|
|
227
|
+
const kBin = k.toString(2);
|
|
228
|
+
for (let i = 0; i < kBin.length; i++) {
|
|
229
|
+
Q = pointDouble(Q);
|
|
230
|
+
if (kBin[i] === '1') {
|
|
231
|
+
Q = pointAdd(Q, N);
|
|
456
232
|
}
|
|
457
|
-
const ZInv2 = modMul(ZInv, ZInv, p);
|
|
458
|
-
const x1affine = modMul(R.X, ZInv2, p);
|
|
459
|
-
// Compute v = x1_affine mod n
|
|
460
|
-
const v = mod(x1affine, n);
|
|
461
|
-
// Signature is valid if v == r mod n
|
|
462
|
-
return v === r;
|
|
463
|
-
};
|
|
464
|
-
// Convert inputs to BigInt
|
|
465
|
-
const hash = BigInt('0x' + msg.toString(16));
|
|
466
|
-
if ((key.x == null) || (key.y == null)) {
|
|
467
|
-
throw new Error('Invalid public key: missing coordinates.');
|
|
468
233
|
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
return verifyECDSA(hash, publicKey, signature);
|
|
478
|
-
}
|
|
479
|
-
else {
|
|
480
|
-
const curve = new Curve_js_1.default();
|
|
481
|
-
msg = truncateToN(msg);
|
|
482
|
-
// Perform primitive values validation
|
|
483
|
-
const r = sig.r;
|
|
484
|
-
const s = sig.s;
|
|
485
|
-
if (r.cmpn(1) < 0 || r.cmp(curve.n) >= 0) {
|
|
234
|
+
return Q;
|
|
235
|
+
};
|
|
236
|
+
// Verify Function Using Jacobian Coordinates
|
|
237
|
+
const verifyECDSA = (hash, publicKey, signature) => {
|
|
238
|
+
const { r, s } = signature;
|
|
239
|
+
const z = hash;
|
|
240
|
+
// Check r and s are in [1, n - 1]
|
|
241
|
+
if (r <= zero || r >= n || s <= zero || s >= n) {
|
|
486
242
|
return false;
|
|
487
243
|
}
|
|
488
|
-
|
|
489
|
-
|
|
244
|
+
const w = modInv(s, n); // w = s^-1 mod n
|
|
245
|
+
if (w === zero) {
|
|
246
|
+
return false; // No inverse exists
|
|
490
247
|
}
|
|
491
|
-
|
|
492
|
-
const
|
|
493
|
-
|
|
494
|
-
const
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
248
|
+
const u1 = modMul(z, w, n);
|
|
249
|
+
const u2 = modMul(r, w, n);
|
|
250
|
+
// Compute point R = u1 * G + u2 * Q
|
|
251
|
+
const RG = scalarMultiply(u1, G);
|
|
252
|
+
const RQ = scalarMultiply(u2, publicKey);
|
|
253
|
+
const R = pointAdd(RG, RQ);
|
|
254
|
+
if (R.Z === zero) {
|
|
255
|
+
// Point at infinity
|
|
499
256
|
return false;
|
|
500
257
|
}
|
|
501
|
-
//
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
258
|
+
// Compute affine x-coordinate x1 = X / Z^2 mod p
|
|
259
|
+
const ZInv = modInv(R.Z, p);
|
|
260
|
+
if (ZInv === zero) {
|
|
261
|
+
return false; // No inverse exists
|
|
262
|
+
}
|
|
263
|
+
const ZInv2 = modMul(ZInv, ZInv, p);
|
|
264
|
+
const x1affine = modMul(R.X, ZInv2, p);
|
|
265
|
+
// Compute v = x1_affine mod n
|
|
266
|
+
const v = mod(x1affine, n);
|
|
267
|
+
// Signature is valid if v == r mod n
|
|
268
|
+
return v === r;
|
|
269
|
+
};
|
|
270
|
+
// Convert inputs to BigInt
|
|
271
|
+
const hash = BigInt('0x' + msg.toString(16));
|
|
272
|
+
if ((key.x == null) || (key.y == null)) {
|
|
273
|
+
throw new Error('Invalid public key: missing coordinates.');
|
|
505
274
|
}
|
|
275
|
+
const publicKey = {
|
|
276
|
+
x: BigInt('0x' + key.x.toString(16)),
|
|
277
|
+
y: BigInt('0x' + key.y.toString(16))
|
|
278
|
+
};
|
|
279
|
+
const signature = {
|
|
280
|
+
r: BigInt('0x' + sig.r.toString(16)),
|
|
281
|
+
s: BigInt('0x' + sig.s.toString(16))
|
|
282
|
+
};
|
|
283
|
+
return verifyECDSA(hash, publicKey, signature);
|
|
506
284
|
};
|
|
507
285
|
exports.verify = verify;
|
|
508
286
|
//# sourceMappingURL=ECDSA.js.map
|