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