smartledger-bsv 3.0.0
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/LICENSE +36 -0
- package/README.md +305 -0
- package/SECURITY.md +75 -0
- package/bsv-ecies.min.js +12 -0
- package/bsv-message.min.js +10 -0
- package/bsv-mnemonic.min.js +12 -0
- package/bsv.d.ts +440 -0
- package/bsv.min.js +37 -0
- package/ecies/index.js +1 -0
- package/index.js +101 -0
- package/lib/address.js +526 -0
- package/lib/block/block.js +277 -0
- package/lib/block/blockheader.js +294 -0
- package/lib/block/index.js +4 -0
- package/lib/block/merkleblock.js +316 -0
- package/lib/crypto/bn.js +278 -0
- package/lib/crypto/ecdsa.js +330 -0
- package/lib/crypto/elliptic-fixed.js +74 -0
- package/lib/crypto/hash.browser.js +171 -0
- package/lib/crypto/hash.js +2 -0
- package/lib/crypto/hash.node.js +171 -0
- package/lib/crypto/point.js +217 -0
- package/lib/crypto/random.js +37 -0
- package/lib/crypto/signature.js +410 -0
- package/lib/crypto/smartledger_verify.js +109 -0
- package/lib/ecies/bitcore-ecies.js +163 -0
- package/lib/ecies/electrum-ecies.js +175 -0
- package/lib/ecies/errors.js +16 -0
- package/lib/ecies/index.js +1 -0
- package/lib/encoding/base58.js +108 -0
- package/lib/encoding/base58check.js +112 -0
- package/lib/encoding/bufferreader.js +200 -0
- package/lib/encoding/bufferwriter.js +150 -0
- package/lib/encoding/varint.js +71 -0
- package/lib/errors/index.js +57 -0
- package/lib/errors/spec.js +184 -0
- package/lib/hdprivatekey.js +655 -0
- package/lib/hdpublickey.js +509 -0
- package/lib/message/index.js +4 -0
- package/lib/message/message.js +181 -0
- package/lib/mnemonic/errors.js +18 -0
- package/lib/mnemonic/index.js +4 -0
- package/lib/mnemonic/mnemonic.js +304 -0
- package/lib/mnemonic/pbkdf2.js +68 -0
- package/lib/mnemonic/words/chinese.js +5 -0
- package/lib/mnemonic/words/english.js +5 -0
- package/lib/mnemonic/words/french.js +5 -0
- package/lib/mnemonic/words/index.js +8 -0
- package/lib/mnemonic/words/italian.js +5 -0
- package/lib/mnemonic/words/japanese.js +5 -0
- package/lib/mnemonic/words/spanish.js +5 -0
- package/lib/networks.js +392 -0
- package/lib/opcode.js +248 -0
- package/lib/privatekey.js +373 -0
- package/lib/publickey.js +387 -0
- package/lib/script/index.js +3 -0
- package/lib/script/interpreter.js +1807 -0
- package/lib/script/script.js +1153 -0
- package/lib/transaction/index.js +7 -0
- package/lib/transaction/input/index.js +6 -0
- package/lib/transaction/input/input.js +202 -0
- package/lib/transaction/input/multisig.js +220 -0
- package/lib/transaction/input/multisigscripthash.js +189 -0
- package/lib/transaction/input/publickey.js +96 -0
- package/lib/transaction/input/publickeyhash.js +103 -0
- package/lib/transaction/output.js +192 -0
- package/lib/transaction/sighash.js +288 -0
- package/lib/transaction/signature.js +88 -0
- package/lib/transaction/transaction.js +1208 -0
- package/lib/transaction/unspentoutput.js +97 -0
- package/lib/util/_.js +44 -0
- package/lib/util/js.js +91 -0
- package/lib/util/preconditions.js +34 -0
- package/message/index.js +1 -0
- package/mnemonic/index.js +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var BN = require('./bn')
|
|
4
|
+
var Point = require('./point')
|
|
5
|
+
var Signature = require('./signature')
|
|
6
|
+
var PublicKey = require('../publickey')
|
|
7
|
+
var Random = require('./random')
|
|
8
|
+
var Hash = require('./hash')
|
|
9
|
+
var _ = require('../util/_')
|
|
10
|
+
var $ = require('../util/preconditions')
|
|
11
|
+
|
|
12
|
+
var ECDSA = function ECDSA (obj) {
|
|
13
|
+
if (!(this instanceof ECDSA)) {
|
|
14
|
+
return new ECDSA(obj)
|
|
15
|
+
}
|
|
16
|
+
if (obj) {
|
|
17
|
+
this.set(obj)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
ECDSA.prototype.set = function (obj) {
|
|
22
|
+
this.hashbuf = obj.hashbuf || this.hashbuf
|
|
23
|
+
this.endian = obj.endian || this.endian // the endianness of hashbuf
|
|
24
|
+
this.privkey = obj.privkey || this.privkey
|
|
25
|
+
this.pubkey = obj.pubkey || (this.privkey ? this.privkey.publicKey : this.pubkey)
|
|
26
|
+
this.sig = obj.sig || this.sig
|
|
27
|
+
this.k = obj.k || this.k
|
|
28
|
+
this.verified = obj.verified || this.verified
|
|
29
|
+
return this
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
ECDSA.prototype.privkey2pubkey = function () {
|
|
33
|
+
this.pubkey = this.privkey.toPublicKey()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
ECDSA.prototype.calci = function () {
|
|
37
|
+
for (var i = 0; i < 4; i++) {
|
|
38
|
+
this.sig.i = i
|
|
39
|
+
var Qprime
|
|
40
|
+
try {
|
|
41
|
+
Qprime = this.toPublicKey()
|
|
42
|
+
} catch (e) {
|
|
43
|
+
console.error(e)
|
|
44
|
+
continue
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (Qprime.point.eq(this.pubkey.point)) {
|
|
48
|
+
this.sig.compressed = this.pubkey.compressed
|
|
49
|
+
return this
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
this.sig.i = undefined
|
|
54
|
+
throw new Error('Unable to find valid recovery factor')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
ECDSA.fromString = function (str) {
|
|
58
|
+
var obj = JSON.parse(str)
|
|
59
|
+
return new ECDSA(obj)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
ECDSA.prototype.randomK = function () {
|
|
63
|
+
var N = Point.getN()
|
|
64
|
+
var k
|
|
65
|
+
do {
|
|
66
|
+
k = BN.fromBuffer(Random.getRandomBuffer(32))
|
|
67
|
+
} while (!(k.lt(N) && k.gt(BN.Zero)))
|
|
68
|
+
this.k = k
|
|
69
|
+
return this
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// https://tools.ietf.org/html/rfc6979#section-3.2
|
|
73
|
+
ECDSA.prototype.deterministicK = function (badrs) {
|
|
74
|
+
// if r or s were invalid when this function was used in signing,
|
|
75
|
+
// we do not want to actually compute r, s here for efficiency, so,
|
|
76
|
+
// we can increment badrs. explained at end of RFC 6979 section 3.2
|
|
77
|
+
if (_.isUndefined(badrs)) {
|
|
78
|
+
badrs = 0
|
|
79
|
+
}
|
|
80
|
+
var v = Buffer.alloc(32)
|
|
81
|
+
v.fill(0x01)
|
|
82
|
+
var k = Buffer.alloc(32)
|
|
83
|
+
k.fill(0x00)
|
|
84
|
+
var x = this.privkey.bn.toBuffer({
|
|
85
|
+
size: 32
|
|
86
|
+
})
|
|
87
|
+
var hashbuf = this.endian === 'little' ? Buffer.from(this.hashbuf).reverse() : this.hashbuf
|
|
88
|
+
k = Hash.sha256hmac(Buffer.concat([v, Buffer.from([0x00]), x, hashbuf]), k)
|
|
89
|
+
v = Hash.sha256hmac(v, k)
|
|
90
|
+
k = Hash.sha256hmac(Buffer.concat([v, Buffer.from([0x01]), x, hashbuf]), k)
|
|
91
|
+
v = Hash.sha256hmac(v, k)
|
|
92
|
+
v = Hash.sha256hmac(v, k)
|
|
93
|
+
var T = BN.fromBuffer(v)
|
|
94
|
+
var N = Point.getN()
|
|
95
|
+
|
|
96
|
+
// also explained in 3.2, we must ensure T is in the proper range (0, N)
|
|
97
|
+
for (var i = 0; i < badrs || !(T.lt(N) && T.gt(BN.Zero)); i++) {
|
|
98
|
+
k = Hash.sha256hmac(Buffer.concat([v, Buffer.from([0x00])]), k)
|
|
99
|
+
v = Hash.sha256hmac(v, k)
|
|
100
|
+
v = Hash.sha256hmac(v, k)
|
|
101
|
+
T = BN.fromBuffer(v)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
this.k = T
|
|
105
|
+
return this
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Information about public key recovery:
|
|
109
|
+
// https://bitcointalk.org/index.php?topic=6430.0
|
|
110
|
+
// http://stackoverflow.com/questions/19665491/how-do-i-get-an-ecdsa-public-key-from-just-a-bitcoin-signature-sec1-4-1-6-k
|
|
111
|
+
ECDSA.prototype.toPublicKey = function () {
|
|
112
|
+
var i = this.sig.i
|
|
113
|
+
$.checkArgument(i === 0 || i === 1 || i === 2 || i === 3, new Error('i must be equal to 0, 1, 2, or 3'))
|
|
114
|
+
|
|
115
|
+
var e = BN.fromBuffer(this.hashbuf)
|
|
116
|
+
var r = this.sig.r
|
|
117
|
+
var s = this.sig.s
|
|
118
|
+
|
|
119
|
+
// A set LSB signifies that the y-coordinate is odd
|
|
120
|
+
var isYOdd = i & 1
|
|
121
|
+
|
|
122
|
+
// The more significant bit specifies whether we should use the
|
|
123
|
+
// first or second candidate key.
|
|
124
|
+
var isSecondKey = i >> 1
|
|
125
|
+
|
|
126
|
+
var n = Point.getN()
|
|
127
|
+
var G = Point.getG()
|
|
128
|
+
|
|
129
|
+
// 1.1 Let x = r + jn
|
|
130
|
+
var x = isSecondKey ? r.add(n) : r
|
|
131
|
+
var R = Point.fromX(isYOdd, x)
|
|
132
|
+
|
|
133
|
+
// 1.4 Check that nR is at infinity
|
|
134
|
+
var nR = R.mul(n)
|
|
135
|
+
|
|
136
|
+
if (!nR.isInfinity()) {
|
|
137
|
+
throw new Error('nR is not a valid curve point')
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Compute -e from e
|
|
141
|
+
var eNeg = e.neg().umod(n)
|
|
142
|
+
|
|
143
|
+
// 1.6.1 Compute Q = r^-1 (sR - eG)
|
|
144
|
+
// Q = r^-1 (sR + -eG)
|
|
145
|
+
var rInv = r.invm(n)
|
|
146
|
+
|
|
147
|
+
// var Q = R.multiplyTwo(s, G, eNeg).mul(rInv);
|
|
148
|
+
var Q = R.mul(s).add(G.mul(eNeg)).mul(rInv)
|
|
149
|
+
|
|
150
|
+
var pubkey = PublicKey.fromPoint(Q, this.sig.compressed)
|
|
151
|
+
|
|
152
|
+
return pubkey
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
ECDSA.prototype.sigError = function () {
|
|
156
|
+
if (!Buffer.isBuffer(this.hashbuf) || this.hashbuf.length !== 32) {
|
|
157
|
+
return 'hashbuf must be a 32 byte buffer'
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// === SmartLedger Security Patches ===
|
|
161
|
+
// Apply security validation during cryptographic verification
|
|
162
|
+
try {
|
|
163
|
+
// Create a copy to avoid mutating original signature
|
|
164
|
+
var secureSig = {
|
|
165
|
+
r: this.sig.r,
|
|
166
|
+
s: this.sig.s
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Apply security patches to the copy
|
|
170
|
+
var n = Point.getN()
|
|
171
|
+
|
|
172
|
+
// Fix 1 & 2: Enhanced range validation (maintains original message for compatibility)
|
|
173
|
+
if (secureSig.r.isZero() || secureSig.s.isZero() ||
|
|
174
|
+
secureSig.r.gte(n) || secureSig.s.gte(n)) {
|
|
175
|
+
return 'r and s not in range'
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Fix 3: Canonicalize s for verification (non-mutating)
|
|
179
|
+
var nh = n.shrn(1) // n/2
|
|
180
|
+
if (secureSig.s.gt(nh)) {
|
|
181
|
+
secureSig.s = n.sub(secureSig.s)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Use secure signature for verification
|
|
185
|
+
var r = secureSig.r
|
|
186
|
+
var canonicalS = secureSig.s
|
|
187
|
+
} catch (error) {
|
|
188
|
+
return 'Signature security validation failed: ' + error.message
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
var e = BN.fromBuffer(this.hashbuf, this.endian ? {
|
|
192
|
+
endian: this.endian
|
|
193
|
+
} : undefined)
|
|
194
|
+
// Use canonical s for verification
|
|
195
|
+
var sinv = canonicalS.invm(n)
|
|
196
|
+
var u1 = sinv.mul(e).umod(n)
|
|
197
|
+
var u2 = sinv.mul(r).umod(n)
|
|
198
|
+
|
|
199
|
+
var p = Point.getG().mulAdd(u1, this.pubkey.point, u2)
|
|
200
|
+
if (p.isInfinity()) {
|
|
201
|
+
return 'p is infinity'
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (p.getX().umod(n).cmp(r) !== 0) {
|
|
205
|
+
return 'Invalid signature'
|
|
206
|
+
} else {
|
|
207
|
+
return false
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
ECDSA.toLowS = function (s) {
|
|
212
|
+
// enforce low s
|
|
213
|
+
// see BIP 62, "low S values in signatures"
|
|
214
|
+
if (s.gt(BN.fromBuffer(Buffer.from('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex')))) {
|
|
215
|
+
s = Point.getN().sub(s)
|
|
216
|
+
}
|
|
217
|
+
return s
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
ECDSA.prototype._findSignature = function (d, e) {
|
|
221
|
+
var N = Point.getN()
|
|
222
|
+
var G = Point.getG()
|
|
223
|
+
// try different values of k until r, s are valid
|
|
224
|
+
var badrs = 0
|
|
225
|
+
var k, Q, r, s
|
|
226
|
+
do {
|
|
227
|
+
if (!this.k || badrs > 0) {
|
|
228
|
+
this.deterministicK(badrs)
|
|
229
|
+
}
|
|
230
|
+
badrs++
|
|
231
|
+
k = this.k
|
|
232
|
+
Q = G.mul(k)
|
|
233
|
+
r = Q.x.umod(N)
|
|
234
|
+
s = k.invm(N).mul(e.add(d.mul(r))).umod(N)
|
|
235
|
+
} while (r.cmp(BN.Zero) <= 0 || s.cmp(BN.Zero) <= 0)
|
|
236
|
+
|
|
237
|
+
s = ECDSA.toLowS(s)
|
|
238
|
+
return {
|
|
239
|
+
s: s,
|
|
240
|
+
r: r
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
ECDSA.prototype.sign = function () {
|
|
245
|
+
var hashbuf = this.hashbuf
|
|
246
|
+
var privkey = this.privkey
|
|
247
|
+
var d = privkey.bn
|
|
248
|
+
|
|
249
|
+
$.checkState(hashbuf && privkey && d, new Error('invalid parameters'))
|
|
250
|
+
$.checkState(Buffer.isBuffer(hashbuf) && hashbuf.length === 32, new Error('hashbuf must be a 32 byte buffer'))
|
|
251
|
+
|
|
252
|
+
var e = BN.fromBuffer(hashbuf, this.endian ? {
|
|
253
|
+
endian: this.endian
|
|
254
|
+
} : undefined)
|
|
255
|
+
|
|
256
|
+
var obj = this._findSignature(d, e)
|
|
257
|
+
obj.compressed = this.pubkey.compressed
|
|
258
|
+
|
|
259
|
+
this.sig = new Signature(obj)
|
|
260
|
+
return this
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
ECDSA.prototype.signRandomK = function () {
|
|
264
|
+
this.randomK()
|
|
265
|
+
return this.sign()
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
ECDSA.prototype.toString = function () {
|
|
269
|
+
var obj = {}
|
|
270
|
+
if (this.hashbuf) {
|
|
271
|
+
obj.hashbuf = this.hashbuf.toString('hex')
|
|
272
|
+
}
|
|
273
|
+
if (this.privkey) {
|
|
274
|
+
obj.privkey = this.privkey.toString()
|
|
275
|
+
}
|
|
276
|
+
if (this.pubkey) {
|
|
277
|
+
obj.pubkey = this.pubkey.toString()
|
|
278
|
+
}
|
|
279
|
+
if (this.sig) {
|
|
280
|
+
obj.sig = this.sig.toString()
|
|
281
|
+
}
|
|
282
|
+
if (this.k) {
|
|
283
|
+
obj.k = this.k.toString()
|
|
284
|
+
}
|
|
285
|
+
return JSON.stringify(obj)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
ECDSA.prototype.verify = function () {
|
|
289
|
+
if (!this.sigError()) {
|
|
290
|
+
this.verified = true
|
|
291
|
+
} else {
|
|
292
|
+
this.verified = false
|
|
293
|
+
}
|
|
294
|
+
return this
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
ECDSA.sign = function (hashbuf, privkey, endian) {
|
|
298
|
+
return ECDSA().set({
|
|
299
|
+
hashbuf: hashbuf,
|
|
300
|
+
endian: endian,
|
|
301
|
+
privkey: privkey
|
|
302
|
+
}).sign().sig
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
ECDSA.signWithCalcI = function (hashbuf, privkey, endian) {
|
|
306
|
+
return ECDSA().set({
|
|
307
|
+
hashbuf: hashbuf,
|
|
308
|
+
endian: endian,
|
|
309
|
+
privkey: privkey
|
|
310
|
+
}).sign().calci().sig
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
ECDSA.signRandomK = function (hashbuf, privkey, endian) {
|
|
314
|
+
return ECDSA().set({
|
|
315
|
+
hashbuf: hashbuf,
|
|
316
|
+
endian: endian,
|
|
317
|
+
privkey: privkey
|
|
318
|
+
}).signRandomK().sig
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
ECDSA.verify = function (hashbuf, sig, pubkey, endian) {
|
|
322
|
+
return ECDSA().set({
|
|
323
|
+
hashbuf: hashbuf,
|
|
324
|
+
endian: endian,
|
|
325
|
+
sig: sig,
|
|
326
|
+
pubkey: pubkey
|
|
327
|
+
}).verify().verified
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
module.exports = ECDSA
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SmartLedger Elliptic Security Wrapper
|
|
5
|
+
* Patches elliptic library to prevent signature verification vulnerabilities
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { ec: EC } = require('elliptic')
|
|
9
|
+
const ec = new EC('secp256k1')
|
|
10
|
+
|
|
11
|
+
// Store original verify method
|
|
12
|
+
const origVerify = ec.verify.bind(ec)
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Hardened elliptic verify method
|
|
16
|
+
* Rejects invalid signature parameters before calling original verify
|
|
17
|
+
*/
|
|
18
|
+
ec.verify = function (msg, sig, key, enc, opts) {
|
|
19
|
+
// Validate signature components exist
|
|
20
|
+
if (!sig || typeof sig !== 'object') {
|
|
21
|
+
return false
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Check for r and s components
|
|
25
|
+
if (!sig.r || !sig.s) {
|
|
26
|
+
return false
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Convert to BN if needed for comparison
|
|
30
|
+
const r = typeof sig.r.cmp === 'function' ? sig.r : this.curve.n.red ? this.curve.n.fromRed(sig.r) : sig.r
|
|
31
|
+
const s = typeof sig.s.cmp === 'function' ? sig.s : this.curve.n.red ? this.curve.n.fromRed(sig.s) : sig.s
|
|
32
|
+
|
|
33
|
+
// Reject if r or s >= curve order n
|
|
34
|
+
if (r && r.cmp && r.cmp(this.curve.n) >= 0) {
|
|
35
|
+
return false
|
|
36
|
+
}
|
|
37
|
+
if (s && s.cmp && s.cmp(this.curve.n) >= 0) {
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Reject zero values
|
|
42
|
+
if (r && r.isZero && r.isZero()) {
|
|
43
|
+
return false
|
|
44
|
+
}
|
|
45
|
+
if (s && s.isZero && s.isZero()) {
|
|
46
|
+
return false
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Call original verify with validated parameters
|
|
50
|
+
return origVerify(msg, sig, key, enc, opts)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Store original sign method for potential future hardening
|
|
54
|
+
const origSign = ec.sign.bind(ec)
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Hardened elliptic sign method
|
|
58
|
+
* Ensures canonical signatures (s <= n/2)
|
|
59
|
+
*/
|
|
60
|
+
ec.sign = function (msg, key, enc, options) {
|
|
61
|
+
const signature = origSign(msg, key, enc, options)
|
|
62
|
+
|
|
63
|
+
// Canonicalize s value to lower half
|
|
64
|
+
if (signature.s && signature.s.cmp) {
|
|
65
|
+
const halfOrder = this.curve.n.shrn(1)
|
|
66
|
+
if (signature.s.cmp(halfOrder) > 0) {
|
|
67
|
+
signature.s = this.curve.n.sub(signature.s)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return signature
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports = ec
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var hash = require('hash.js')
|
|
4
|
+
var $ = require('../util/preconditions')
|
|
5
|
+
|
|
6
|
+
var Hash = module.exports
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A SHA or SHA1 hash, which is always 160 bits or 20 bytes long.
|
|
10
|
+
*
|
|
11
|
+
* See:
|
|
12
|
+
* https://en.wikipedia.org/wiki/SHA-1
|
|
13
|
+
*
|
|
14
|
+
* @param {Buffer} buf Data, a.k.a. pre-image, which can be any size.
|
|
15
|
+
* @returns {Buffer} The hash in the form of a buffer.
|
|
16
|
+
*/
|
|
17
|
+
Hash.sha1 = function (buf) {
|
|
18
|
+
$.checkArgument(Buffer.isBuffer(buf))
|
|
19
|
+
return Buffer.from(hash.sha1().update(buf).digest('hex'), 'hex')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Hash.sha1.blocksize = 512
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A SHA256 hash, which is always 256 bits or 32 bytes long.
|
|
26
|
+
*
|
|
27
|
+
* See:
|
|
28
|
+
* https://www.movable-type.co.uk/scripts/sha256.html
|
|
29
|
+
*
|
|
30
|
+
* @param {Buffer} buf Data, a.k.a. pre-image, which can be any size.
|
|
31
|
+
* @returns {Buffer} The hash in the form of a buffer.
|
|
32
|
+
*/
|
|
33
|
+
Hash.sha256 = function (buf) {
|
|
34
|
+
$.checkArgument(Buffer.isBuffer(buf))
|
|
35
|
+
return Buffer.from(hash.sha256().update(buf).digest('hex'), 'hex')
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
Hash.sha256.blocksize = 512
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* A double SHA256 hash, which is always 256 bits or 32 bytes bytes long. This
|
|
42
|
+
* hash function is commonly used inside Bitcoin, particularly for the hash of a
|
|
43
|
+
* block and the hash of a transaction.
|
|
44
|
+
*
|
|
45
|
+
* See:
|
|
46
|
+
* https://www.movable-type.co.uk/scripts/sha256.html
|
|
47
|
+
*
|
|
48
|
+
* @param {Buffer} buf Data, a.k.a. pre-image, which can be any size.
|
|
49
|
+
* @returns {Buffer} The hash in the form of a buffer.
|
|
50
|
+
*/
|
|
51
|
+
Hash.sha256sha256 = function (buf) {
|
|
52
|
+
$.checkArgument(Buffer.isBuffer(buf))
|
|
53
|
+
return Hash.sha256(Hash.sha256(buf))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A RIPEMD160 hash, which is always 160 bits or 20 bytes long.
|
|
58
|
+
*
|
|
59
|
+
* See:
|
|
60
|
+
* https://en.wikipedia.org/wiki/RIPEMD
|
|
61
|
+
*
|
|
62
|
+
* @param {Buffer} buf Data, a.k.a. pre-image, which can be any size.
|
|
63
|
+
* @returns {Buffer} The hash in the form of a buffer.
|
|
64
|
+
*/
|
|
65
|
+
Hash.ripemd160 = function (buf) {
|
|
66
|
+
$.checkArgument(Buffer.isBuffer(buf))
|
|
67
|
+
return Buffer.from(hash.ripemd160().update(buf).digest('hex'), 'hex')
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A RIPEMD160 hash of a SHA256 hash, which is always 160 bits or 20 bytes long.
|
|
71
|
+
* This value is commonly used inside Bitcoin, particularly for Bitcoin
|
|
72
|
+
* addresses.
|
|
73
|
+
*
|
|
74
|
+
* See:
|
|
75
|
+
* https://en.wikipedia.org/wiki/RIPEMD
|
|
76
|
+
*
|
|
77
|
+
* @param {Buffer} buf Data, a.k.a. pre-image, which can be any size.
|
|
78
|
+
* @returns {Buffer} The hash in the form of a buffer.
|
|
79
|
+
*/
|
|
80
|
+
Hash.sha256ripemd160 = function (buf) {
|
|
81
|
+
$.checkArgument(Buffer.isBuffer(buf))
|
|
82
|
+
return Hash.ripemd160(Hash.sha256(buf))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* A SHA512 hash, which is always 512 bits or 64 bytes long.
|
|
87
|
+
*
|
|
88
|
+
* See:
|
|
89
|
+
* https://en.wikipedia.org/wiki/SHA-2
|
|
90
|
+
*
|
|
91
|
+
* @param {Buffer} buf Data, a.k.a. pre-image, which can be any size.
|
|
92
|
+
* @returns {Buffer} The hash in the form of a buffer.
|
|
93
|
+
*/
|
|
94
|
+
Hash.sha512 = function (buf) {
|
|
95
|
+
$.checkArgument(Buffer.isBuffer(buf))
|
|
96
|
+
return Buffer.from(hash.sha512().update(buf).digest('hex'), 'hex')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
Hash.sha512.blocksize = 1024
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* A way to do HMAC using any underlying hash function. If you ever find that
|
|
103
|
+
* you want to hash two pieces of data together, you should use HMAC instead of
|
|
104
|
+
* just using a hash function. Rather than doing hash(data1 + data2) you should
|
|
105
|
+
* do HMAC(data1, data2). Actually, rather than use HMAC directly, we recommend
|
|
106
|
+
* you use either sha256hmac or sha515hmac provided below.
|
|
107
|
+
*
|
|
108
|
+
* See:
|
|
109
|
+
* https://en.wikipedia.org/wiki/Length_extension_attack
|
|
110
|
+
* https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks
|
|
111
|
+
*
|
|
112
|
+
* @param {function} hashf Which hash function to use.
|
|
113
|
+
* @param {Buffer} data Data, which can be any size.
|
|
114
|
+
* @param {Buffer} key Key, which can be any size.
|
|
115
|
+
* @returns {Buffer} The HMAC in the form of a buffer.
|
|
116
|
+
*/
|
|
117
|
+
Hash.hmac = function (hashf, data, key) {
|
|
118
|
+
// http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
|
|
119
|
+
// http://tools.ietf.org/html/rfc4868#section-2
|
|
120
|
+
$.checkArgument(Buffer.isBuffer(data))
|
|
121
|
+
$.checkArgument(Buffer.isBuffer(key))
|
|
122
|
+
$.checkArgument(hashf.blocksize)
|
|
123
|
+
|
|
124
|
+
var blocksize = hashf.blocksize / 8
|
|
125
|
+
|
|
126
|
+
if (key.length > blocksize) {
|
|
127
|
+
key = hashf(key)
|
|
128
|
+
} else if (key < blocksize) {
|
|
129
|
+
var fill = Buffer.alloc(blocksize)
|
|
130
|
+
fill.fill(0)
|
|
131
|
+
key.copy(fill)
|
|
132
|
+
key = fill
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
var oKey = Buffer.alloc(blocksize)
|
|
136
|
+
oKey.fill(0x5c)
|
|
137
|
+
|
|
138
|
+
var iKey = Buffer.alloc(blocksize)
|
|
139
|
+
iKey.fill(0x36)
|
|
140
|
+
|
|
141
|
+
var oKeyPad = Buffer.alloc(blocksize)
|
|
142
|
+
var iKeyPad = Buffer.alloc(blocksize)
|
|
143
|
+
for (var i = 0; i < blocksize; i++) {
|
|
144
|
+
oKeyPad[i] = oKey[i] ^ key[i]
|
|
145
|
+
iKeyPad[i] = iKey[i] ^ key[i]
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return hashf(Buffer.concat([oKeyPad, hashf(Buffer.concat([iKeyPad, data]))]))
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* A SHA256 HMAC.
|
|
153
|
+
*
|
|
154
|
+
* @param {Buffer} data Data, which can be any size.
|
|
155
|
+
* @param {Buffer} key Key, which can be any size.
|
|
156
|
+
* @returns {Buffer} The HMAC in the form of a buffer.
|
|
157
|
+
*/
|
|
158
|
+
Hash.sha256hmac = function (data, key) {
|
|
159
|
+
return Hash.hmac(Hash.sha256, data, key)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* A SHA512 HMAC.
|
|
164
|
+
*
|
|
165
|
+
* @param {Buffer} data Data, which can be any size.
|
|
166
|
+
* @param {Buffer} key Key, which can be any size.
|
|
167
|
+
* @returns {Buffer} The HMAC in the form of a buffer.
|
|
168
|
+
*/
|
|
169
|
+
Hash.sha512hmac = function (data, key) {
|
|
170
|
+
return Hash.hmac(Hash.sha512, data, key)
|
|
171
|
+
}
|