@exodus/bitcoinjs-lib-forks 0.0.4 → 0.0.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/bitcoinjs-lib-forks",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Client-side Bitcoin Forks JavaScript library",
5
5
  "main": "./src/index.js",
6
6
  "engines": {
@@ -33,21 +33,15 @@
33
33
  "src"
34
34
  ],
35
35
  "dependencies": {
36
+ "@exodus/crypto": "^1.0.0-rc.27",
36
37
  "bech32": "0.0.3",
37
38
  "bigi": "^1.4.0",
38
39
  "bip66": "^1.1.0",
39
40
  "bitcoin-ops": "^1.3.0",
40
- "bs58check": "^2.0.0",
41
- "create-hash": "^1.1.0",
42
- "create-hmac": "^1.1.3",
43
- "ecurve": "^1.0.0",
44
- "merkle-lib": "^2.0.10",
45
41
  "pushdata-bitcoin": "^1.0.1",
46
- "randombytes": "^2.0.1",
47
42
  "safe-buffer": "^5.0.1",
48
43
  "typeforce": "^1.11.3",
49
- "varuint-bitcoin": "^1.0.4",
50
- "wif": "^2.0.1"
44
+ "varuint-bitcoin": "^1.0.4"
51
45
  },
52
46
  "devDependencies": {
53
47
  "async": "^2.0.1",
@@ -56,12 +50,15 @@
56
50
  "cb-http-client": "^0.2.0",
57
51
  "coinselect": "^3.1.1",
58
52
  "dhttp": "^2.3.5",
53
+ "ecurve": "^1.0.0",
59
54
  "minimaldata": "^1.0.2",
60
55
  "mocha": "^3.1.0",
61
56
  "nyc": "^10.2.0",
62
57
  "proxyquire": "^1.4.0",
58
+ "randombytes": "^2.0.1",
63
59
  "sinon": "^1.12.2",
64
- "standard": "^9.0.2"
60
+ "standard": "^9.0.2",
61
+ "wif": "^2.0.1"
65
62
  },
66
63
  "license": "MIT"
67
64
  }
package/src/address.js CHANGED
@@ -1,4 +1,3 @@
1
- var Buffer = require('safe-buffer').Buffer
2
1
  var bech32 = require('bech32')
3
2
  var bs58check = require('bs58check')
4
3
  var bscript = require('./script')
@@ -8,7 +7,7 @@ var typeforce = require('typeforce')
8
7
  var types = require('./types')
9
8
 
10
9
  function fromBase58Check (address) {
11
- var payload = bs58check.decode(address)
10
+ var payload = Buffer.from(bs58check.decode(address))
12
11
 
13
12
  // TODO: 4.0.0, move to "toOutputScript"
14
13
  if (payload.length < 21) throw new TypeError(address + ' is too short')
package/src/crypto.js CHANGED
@@ -1,19 +1,15 @@
1
- var createHash = require('create-hash')
1
+ const { hashSync } = require('@exodus/crypto/hash')
2
2
 
3
3
  function ripemd160 (buffer) {
4
- return createHash('ripemd160').update(buffer).digest()
5
- }
6
-
7
- function sha1 (buffer) {
8
- return createHash('sha1').update(buffer).digest()
4
+ return hashSync('ripemd160', buffer, 'buffer')
9
5
  }
10
6
 
11
7
  function sha256 (buffer) {
12
- return createHash('sha256').update(buffer).digest()
8
+ return hashSync('sha256', buffer, 'buffer')
13
9
  }
14
10
 
15
11
  function hash160 (buffer) {
16
- return ripemd160(sha256(buffer))
12
+ return hashSync('hash160', buffer, 'buffer')
17
13
  }
18
14
 
19
15
  function hash256 (buffer) {
@@ -24,6 +20,5 @@ module.exports = {
24
20
  hash160: hash160,
25
21
  hash256: hash256,
26
22
  ripemd160: ripemd160,
27
- sha1: sha1,
28
23
  sha256: sha256
29
24
  }
@@ -77,10 +77,13 @@ ECSignature.prototype.toDER = function () {
77
77
  return bip66.encode(r, s)
78
78
  }
79
79
 
80
- ECSignature.prototype.toRSBuffer = function (buffer, offset) {
80
+ const N = BigInteger.fromHex('ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551')
81
+ ECSignature.prototype.toRSBuffer = function (buffer, offset, { canonical } = {}) {
81
82
  buffer = buffer || Buffer.alloc(64)
82
83
  this.r.toBuffer(32).copy(buffer, offset)
83
- this.s.toBuffer(32).copy(buffer, offset + 32)
84
+ let s = this.s
85
+ if (canonical && s.compareTo(N) >= 0) s = N.subtract(s)
86
+ s.toBuffer(32).copy(buffer, offset + 32)
84
87
  return buffer
85
88
  }
86
89
 
package/src/index.js CHANGED
@@ -8,10 +8,7 @@ for (var key in templates) {
8
8
  module.exports = {
9
9
  bufferutils: require('./bufferutils'), // TODO: remove in 4.0.0
10
10
 
11
- Block: require('./block'),
12
- ECPair: require('./ecpair'),
13
11
  ECSignature: require('./ecsignature'),
14
- HDNode: require('./hdnode'),
15
12
  Transaction: require('./transaction'),
16
13
  TransactionBuilder: require('./transaction_builder'),
17
14
 
package/src/script.js CHANGED
@@ -1,4 +1,3 @@
1
- var Buffer = require('safe-buffer').Buffer
2
1
  var bip66 = require('bip66')
3
2
  var pushdata = require('pushdata-bitcoin')
4
3
  var typeforce = require('typeforce')
@@ -1,5 +1,3 @@
1
- var Buffer = require('safe-buffer').Buffer
2
-
3
1
  function decode (buffer, maxLength, minimal) {
4
2
  maxLength = maxLength || 4
5
3
  minimal = minimal === undefined ? true : minimal
@@ -1,6 +1,5 @@
1
1
  // OP_0 [signatures ...]
2
2
 
3
- var Buffer = require('safe-buffer').Buffer
4
3
  var bscript = require('../../script')
5
4
  var p2mso = require('./output')
6
5
  var typeforce = require('typeforce')
@@ -1,6 +1,5 @@
1
1
  // <scriptSig> {serialized scriptPubKey script}
2
2
 
3
- var Buffer = require('safe-buffer').Buffer
4
3
  var bscript = require('../../script')
5
4
  var typeforce = require('typeforce')
6
5
 
@@ -1,6 +1,5 @@
1
1
  // OP_RETURN {aa21a9ed} {commitment}
2
2
 
3
- var Buffer = require('safe-buffer').Buffer
4
3
  var bscript = require('../../script')
5
4
  var types = require('../../types')
6
5
  var typeforce = require('typeforce')
@@ -1,4 +1,3 @@
1
- var Buffer = require('safe-buffer').Buffer
2
1
  var bcrypto = require('./crypto')
3
2
  var bscript = require('./script')
4
3
  var bufferutils = require('./bufferutils')
@@ -1,4 +1,3 @@
1
- var Buffer = require('safe-buffer').Buffer
2
1
  var baddress = require('./address')
3
2
  var bcrypto = require('./crypto')
4
3
  var bscript = require('./script')
@@ -11,9 +10,9 @@ var scriptTypes = btemplates.types
11
10
  var SIGNABLE = [btemplates.types.P2PKH, btemplates.types.P2PK, btemplates.types.MULTISIG]
12
11
  var P2SH = SIGNABLE.concat([btemplates.types.P2WPKH, btemplates.types.P2WSH])
13
12
 
14
- var ECPair = require('./ecpair')
15
13
  var ECSignature = require('./ecsignature')
16
14
  var Transaction = require('./transaction')
15
+ const { ecdsaVerifyHashSync } = require('@exodus/crypto/secp256k1')
17
16
 
18
17
  function supportedType (type) {
19
18
  return SIGNABLE.indexOf(type) !== -1
@@ -181,7 +180,6 @@ function fixMultisigOrder (input, transaction, vin, value, forkId) {
181
180
  var unmatched = input.signatures.concat()
182
181
 
183
182
  input.signatures = input.pubKeys.map(function (pubKey) {
184
- var keyPair = ECPair.fromPublicKeyBuffer(pubKey)
185
183
  var match
186
184
 
187
185
  // check for a signature
@@ -209,7 +207,12 @@ function fixMultisigOrder (input, transaction, vin, value, forkId) {
209
207
  }
210
208
 
211
209
  // skip if signature does not match pubKey
212
- if (!keyPair.verify(hash, parsed.signature)) return false
210
+ // Allow non-normalized though
211
+ if (!ecdsaVerifyHashSync({
212
+ signature: parsed.signature.toRSBuffer(null, 0, { canonical: true }),
213
+ hash,
214
+ publicKey: pubKey
215
+ })) return false
213
216
 
214
217
  // remove matched signature from unmatched
215
218
  unmatched[i] = undefined
package/src/block.js DELETED
@@ -1,177 +0,0 @@
1
- var Buffer = require('safe-buffer').Buffer
2
- var bcrypto = require('./crypto')
3
- var fastMerkleRoot = require('merkle-lib/fastRoot')
4
- var typeforce = require('typeforce')
5
- var types = require('./types')
6
- var varuint = require('varuint-bitcoin')
7
-
8
- var Transaction = require('./transaction')
9
-
10
- function Block () {
11
- this.version = 1
12
- this.prevHash = null
13
- this.merkleRoot = null
14
- this.timestamp = 0
15
- this.bits = 0
16
- this.nonce = 0
17
- }
18
-
19
- Block.fromBuffer = function (buffer) {
20
- if (buffer.length < 80) throw new Error('Buffer too small (< 80 bytes)')
21
-
22
- var offset = 0
23
- function readSlice (n) {
24
- offset += n
25
- return buffer.slice(offset - n, offset)
26
- }
27
-
28
- function readUInt32 () {
29
- var i = buffer.readUInt32LE(offset)
30
- offset += 4
31
- return i
32
- }
33
-
34
- function readInt32 () {
35
- var i = buffer.readInt32LE(offset)
36
- offset += 4
37
- return i
38
- }
39
-
40
- var block = new Block()
41
- block.version = readInt32()
42
- block.prevHash = readSlice(32)
43
- block.merkleRoot = readSlice(32)
44
- block.timestamp = readUInt32()
45
- block.bits = readUInt32()
46
- block.nonce = readUInt32()
47
-
48
- if (buffer.length === 80) return block
49
-
50
- function readVarInt () {
51
- var vi = varuint.decode(buffer, offset)
52
- offset += varuint.decode.bytes
53
- return vi
54
- }
55
-
56
- function readTransaction () {
57
- var tx = Transaction.fromBuffer(buffer.slice(offset), true)
58
- offset += tx.byteLength()
59
- return tx
60
- }
61
-
62
- var nTransactions = readVarInt()
63
- block.transactions = []
64
-
65
- for (var i = 0; i < nTransactions; ++i) {
66
- var tx = readTransaction()
67
- block.transactions.push(tx)
68
- }
69
-
70
- return block
71
- }
72
-
73
- Block.prototype.byteLength = function (headersOnly) {
74
- if (headersOnly || !this.transactions) return 80
75
-
76
- return 80 + varuint.encodingLength(this.transactions.length) + this.transactions.reduce(function (a, x) {
77
- return a + x.byteLength()
78
- }, 0)
79
- }
80
-
81
- Block.fromHex = function (hex) {
82
- return Block.fromBuffer(Buffer.from(hex, 'hex'))
83
- }
84
-
85
- Block.prototype.getHash = function () {
86
- return bcrypto.hash256(this.toBuffer(true))
87
- }
88
-
89
- Block.prototype.getId = function () {
90
- return this.getHash().reverse().toString('hex')
91
- }
92
-
93
- Block.prototype.getUTCDate = function () {
94
- var date = new Date(0) // epoch
95
- date.setUTCSeconds(this.timestamp)
96
-
97
- return date
98
- }
99
-
100
- // TODO: buffer, offset compatibility
101
- Block.prototype.toBuffer = function (headersOnly) {
102
- var buffer = Buffer.allocUnsafe(this.byteLength(headersOnly))
103
-
104
- var offset = 0
105
- function writeSlice (slice) {
106
- slice.copy(buffer, offset)
107
- offset += slice.length
108
- }
109
-
110
- function writeInt32 (i) {
111
- buffer.writeInt32LE(i, offset)
112
- offset += 4
113
- }
114
- function writeUInt32 (i) {
115
- buffer.writeUInt32LE(i, offset)
116
- offset += 4
117
- }
118
-
119
- writeInt32(this.version)
120
- writeSlice(this.prevHash)
121
- writeSlice(this.merkleRoot)
122
- writeUInt32(this.timestamp)
123
- writeUInt32(this.bits)
124
- writeUInt32(this.nonce)
125
-
126
- if (headersOnly || !this.transactions) return buffer
127
-
128
- varuint.encode(this.transactions.length, buffer, offset)
129
- offset += varuint.encode.bytes
130
-
131
- this.transactions.forEach(function (tx) {
132
- var txSize = tx.byteLength() // TODO: extract from toBuffer?
133
- tx.toBuffer(buffer, offset)
134
- offset += txSize
135
- })
136
-
137
- return buffer
138
- }
139
-
140
- Block.prototype.toHex = function (headersOnly) {
141
- return this.toBuffer(headersOnly).toString('hex')
142
- }
143
-
144
- Block.calculateTarget = function (bits) {
145
- var exponent = ((bits & 0xff000000) >> 24) - 3
146
- var mantissa = bits & 0x007fffff
147
- var target = Buffer.alloc(32, 0)
148
- target.writeUInt32BE(mantissa, 28 - exponent)
149
- return target
150
- }
151
-
152
- Block.calculateMerkleRoot = function (transactions) {
153
- typeforce([{ getHash: types.Function }], transactions)
154
- if (transactions.length === 0) throw TypeError('Cannot compute merkle root for zero transactions')
155
-
156
- var hashes = transactions.map(function (transaction) {
157
- return transaction.getHash()
158
- })
159
-
160
- return fastMerkleRoot(hashes, bcrypto.hash256)
161
- }
162
-
163
- Block.prototype.checkMerkleRoot = function () {
164
- if (!this.transactions) return false
165
-
166
- var actualMerkleRoot = Block.calculateMerkleRoot(this.transactions)
167
- return this.merkleRoot.compare(actualMerkleRoot) === 0
168
- }
169
-
170
- Block.prototype.checkProofOfWork = function () {
171
- var hash = this.getHash().reverse()
172
- var target = Block.calculateTarget(this.bits)
173
-
174
- return hash.compare(target) <= 0
175
- }
176
-
177
- module.exports = Block
package/src/ecdsa.js DELETED
@@ -1,161 +0,0 @@
1
- var Buffer = require('safe-buffer').Buffer
2
- var createHmac = require('create-hmac')
3
- var typeforce = require('typeforce')
4
- var types = require('./types')
5
-
6
- var BigInteger = require('bigi')
7
- var ECSignature = require('./ecsignature')
8
-
9
- var ZERO = Buffer.alloc(1, 0)
10
- var ONE = Buffer.alloc(1, 1)
11
-
12
- var ecurve = require('ecurve')
13
- var secp256k1 = ecurve.getCurveByName('secp256k1')
14
-
15
- // https://tools.ietf.org/html/rfc6979#section-3.2
16
- function deterministicGenerateK (hash, x, checkSig) {
17
- typeforce(types.tuple(
18
- types.Hash256bit,
19
- types.Buffer256bit,
20
- types.Function
21
- ), arguments)
22
-
23
- // Step A, ignored as hash already provided
24
- // Step B
25
- // Step C
26
- var k = Buffer.alloc(32, 0)
27
- var v = Buffer.alloc(32, 1)
28
-
29
- // Step D
30
- k = createHmac('sha256', k)
31
- .update(v)
32
- .update(ZERO)
33
- .update(x)
34
- .update(hash)
35
- .digest()
36
-
37
- // Step E
38
- v = createHmac('sha256', k).update(v).digest()
39
-
40
- // Step F
41
- k = createHmac('sha256', k)
42
- .update(v)
43
- .update(ONE)
44
- .update(x)
45
- .update(hash)
46
- .digest()
47
-
48
- // Step G
49
- v = createHmac('sha256', k).update(v).digest()
50
-
51
- // Step H1/H2a, ignored as tlen === qlen (256 bit)
52
- // Step H2b
53
- v = createHmac('sha256', k).update(v).digest()
54
-
55
- var T = BigInteger.fromBuffer(v)
56
-
57
- // Step H3, repeat until T is within the interval [1, n - 1] and is suitable for ECDSA
58
- while (T.signum() <= 0 || T.compareTo(secp256k1.n) >= 0 || !checkSig(T)) {
59
- k = createHmac('sha256', k)
60
- .update(v)
61
- .update(ZERO)
62
- .digest()
63
-
64
- v = createHmac('sha256', k).update(v).digest()
65
-
66
- // Step H1/H2a, again, ignored as tlen === qlen (256 bit)
67
- // Step H2b again
68
- v = createHmac('sha256', k).update(v).digest()
69
- T = BigInteger.fromBuffer(v)
70
- }
71
-
72
- return T
73
- }
74
-
75
- var N_OVER_TWO = secp256k1.n.shiftRight(1)
76
-
77
- function sign (hash, d) {
78
- typeforce(types.tuple(types.Hash256bit, types.BigInt), arguments)
79
-
80
- var x = d.toBuffer(32)
81
- var e = BigInteger.fromBuffer(hash)
82
- var n = secp256k1.n
83
- var G = secp256k1.G
84
-
85
- var r, s
86
- deterministicGenerateK(hash, x, function (k) {
87
- var Q = G.multiply(k)
88
-
89
- if (secp256k1.isInfinity(Q)) return false
90
-
91
- r = Q.affineX.mod(n)
92
- if (r.signum() === 0) return false
93
-
94
- s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n)
95
- if (s.signum() === 0) return false
96
-
97
- return true
98
- })
99
-
100
- // enforce low S values, see bip62: 'low s values in signatures'
101
- if (s.compareTo(N_OVER_TWO) > 0) {
102
- s = n.subtract(s)
103
- }
104
-
105
- return new ECSignature(r, s)
106
- }
107
-
108
- function verify (hash, signature, Q) {
109
- typeforce(types.tuple(
110
- types.Hash256bit,
111
- types.ECSignature,
112
- types.ECPoint
113
- ), arguments)
114
-
115
- var n = secp256k1.n
116
- var G = secp256k1.G
117
-
118
- var r = signature.r
119
- var s = signature.s
120
-
121
- // 1.4.1 Enforce r and s are both integers in the interval [1, n − 1]
122
- if (r.signum() <= 0 || r.compareTo(n) >= 0) return false
123
- if (s.signum() <= 0 || s.compareTo(n) >= 0) return false
124
-
125
- // 1.4.2 H = Hash(M), already done by the user
126
- // 1.4.3 e = H
127
- var e = BigInteger.fromBuffer(hash)
128
-
129
- // Compute s^-1
130
- var sInv = s.modInverse(n)
131
-
132
- // 1.4.4 Compute u1 = es^−1 mod n
133
- // u2 = rs^−1 mod n
134
- var u1 = e.multiply(sInv).mod(n)
135
- var u2 = r.multiply(sInv).mod(n)
136
-
137
- // 1.4.5 Compute R = (xR, yR)
138
- // R = u1G + u2Q
139
- var R = G.multiplyTwo(u1, Q, u2)
140
-
141
- // 1.4.5 (cont.) Enforce R is not at infinity
142
- if (secp256k1.isInfinity(R)) return false
143
-
144
- // 1.4.6 Convert the field element R.x to an integer
145
- var xR = R.affineX
146
-
147
- // 1.4.7 Set v = xR mod n
148
- var v = xR.mod(n)
149
-
150
- // 1.4.8 If v = r, output "valid", and if v != r, output "invalid"
151
- return v.equals(r)
152
- }
153
-
154
- module.exports = {
155
- deterministicGenerateK: deterministicGenerateK,
156
- sign: sign,
157
- verify: verify,
158
-
159
- // TODO: remove
160
- __curve: secp256k1
161
- }
package/src/ecpair.js DELETED
@@ -1,131 +0,0 @@
1
- var baddress = require('./address')
2
- var bcrypto = require('./crypto')
3
- var ecdsa = require('./ecdsa')
4
- var randomBytes = require('randombytes')
5
- var typeforce = require('typeforce')
6
- var types = require('./types')
7
- var wif = require('wif')
8
-
9
- var NETWORKS = require('./networks')
10
- var BigInteger = require('bigi')
11
-
12
- var ecurve = require('ecurve')
13
- var secp256k1 = ecdsa.__curve
14
-
15
- function ECPair (d, Q, options) {
16
- if (options) {
17
- typeforce({
18
- compressed: types.maybe(types.Boolean),
19
- network: types.maybe(types.Network)
20
- }, options)
21
- }
22
-
23
- options = options || {}
24
-
25
- if (d) {
26
- if (d.signum() <= 0) throw new Error('Private key must be greater than 0')
27
- if (d.compareTo(secp256k1.n) >= 0) throw new Error('Private key must be less than the curve order')
28
- if (Q) throw new TypeError('Unexpected publicKey parameter')
29
-
30
- this.d = d
31
- } else {
32
- typeforce(types.ECPoint, Q)
33
-
34
- this.__Q = Q
35
- }
36
-
37
- this.compressed = options.compressed === undefined ? true : options.compressed
38
- this.network = options.network || NETWORKS.bitcoin
39
- }
40
-
41
- Object.defineProperty(ECPair.prototype, 'Q', {
42
- get: function () {
43
- if (!this.__Q && this.d) {
44
- this.__Q = secp256k1.G.multiply(this.d)
45
- }
46
-
47
- return this.__Q
48
- }
49
- })
50
-
51
- ECPair.fromPublicKeyBuffer = function (buffer, network) {
52
- var Q = ecurve.Point.decodeFrom(secp256k1, buffer)
53
-
54
- return new ECPair(null, Q, {
55
- compressed: Q.compressed,
56
- network: network
57
- })
58
- }
59
-
60
- ECPair.fromWIF = function (string, network) {
61
- var decoded = wif.decode(string)
62
- var version = decoded.version
63
-
64
- // list of networks?
65
- if (types.Array(network)) {
66
- network = network.filter(function (x) {
67
- return version === x.wif
68
- }).pop()
69
-
70
- if (!network) throw new Error('Unknown network version')
71
-
72
- // otherwise, assume a network object (or default to bitcoin)
73
- } else {
74
- network = network || NETWORKS.bitcoin
75
-
76
- if (version !== network.wif) throw new Error('Invalid network version')
77
- }
78
-
79
- var d = BigInteger.fromBuffer(decoded.privateKey)
80
-
81
- return new ECPair(d, null, {
82
- compressed: decoded.compressed,
83
- network: network
84
- })
85
- }
86
-
87
- ECPair.makeRandom = function (options) {
88
- options = options || {}
89
-
90
- var rng = options.rng || randomBytes
91
-
92
- var d
93
- do {
94
- var buffer = rng(32)
95
- typeforce(types.Buffer256bit, buffer)
96
-
97
- d = BigInteger.fromBuffer(buffer)
98
- } while (d.signum() <= 0 || d.compareTo(secp256k1.n) >= 0)
99
-
100
- return new ECPair(d, null, options)
101
- }
102
-
103
- ECPair.prototype.getAddress = function () {
104
- return baddress.toBase58Check(bcrypto.hash160(this.getPublicKeyBuffer()), this.getNetwork().pubKeyHash)
105
- }
106
-
107
- ECPair.prototype.getNetwork = function () {
108
- return this.network
109
- }
110
-
111
- ECPair.prototype.getPublicKeyBuffer = function () {
112
- return this.Q.getEncoded(this.compressed)
113
- }
114
-
115
- ECPair.prototype.sign = function (hash) {
116
- if (!this.d) throw new Error('Missing private key')
117
-
118
- return ecdsa.sign(hash, this.d)
119
- }
120
-
121
- ECPair.prototype.toWIF = function () {
122
- if (!this.d) throw new Error('Missing private key')
123
-
124
- return wif.encode(this.network.wif, this.d.toBuffer(32), this.compressed)
125
- }
126
-
127
- ECPair.prototype.verify = function (hash, signature) {
128
- return ecdsa.verify(hash, signature, this.Q)
129
- }
130
-
131
- module.exports = ECPair
package/src/hdnode.js DELETED
@@ -1,316 +0,0 @@
1
- var Buffer = require('safe-buffer').Buffer
2
- var base58check = require('bs58check')
3
- var bcrypto = require('./crypto')
4
- var createHmac = require('create-hmac')
5
- var typeforce = require('typeforce')
6
- var types = require('./types')
7
- var NETWORKS = require('./networks')
8
-
9
- var BigInteger = require('bigi')
10
- var ECPair = require('./ecpair')
11
-
12
- var ecurve = require('ecurve')
13
- var curve = ecurve.getCurveByName('secp256k1')
14
-
15
- function HDNode (keyPair, chainCode) {
16
- typeforce(types.tuple('ECPair', types.Buffer256bit), arguments)
17
-
18
- if (!keyPair.compressed) throw new TypeError('BIP32 only allows compressed keyPairs')
19
-
20
- this.keyPair = keyPair
21
- this.chainCode = chainCode
22
- this.depth = 0
23
- this.index = 0
24
- this.parentFingerprint = 0x00000000
25
- }
26
-
27
- HDNode.HIGHEST_BIT = 0x80000000
28
- HDNode.LENGTH = 78
29
- HDNode.MASTER_SECRET = Buffer.from('Bitcoin seed', 'utf8')
30
-
31
- HDNode.fromSeedBuffer = function (seed, network) {
32
- typeforce(types.tuple(types.Buffer, types.maybe(types.Network)), arguments)
33
-
34
- if (seed.length < 16) throw new TypeError('Seed should be at least 128 bits')
35
- if (seed.length > 64) throw new TypeError('Seed should be at most 512 bits')
36
-
37
- var I = createHmac('sha512', HDNode.MASTER_SECRET).update(seed).digest()
38
- var IL = I.slice(0, 32)
39
- var IR = I.slice(32)
40
-
41
- // In case IL is 0 or >= n, the master key is invalid
42
- // This is handled by the ECPair constructor
43
- var pIL = BigInteger.fromBuffer(IL)
44
- var keyPair = new ECPair(pIL, null, {
45
- network: network
46
- })
47
-
48
- return new HDNode(keyPair, IR)
49
- }
50
-
51
- HDNode.fromSeedHex = function (hex, network) {
52
- return HDNode.fromSeedBuffer(Buffer.from(hex, 'hex'), network)
53
- }
54
-
55
- HDNode.fromBase58 = function (string, networks) {
56
- var buffer = base58check.decode(string)
57
- if (buffer.length !== 78) throw new Error('Invalid buffer length')
58
-
59
- // 4 bytes: version bytes
60
- var version = buffer.readUInt32BE(0)
61
- var network
62
-
63
- // list of networks?
64
- if (Array.isArray(networks)) {
65
- network = networks.filter(function (x) {
66
- return version === x.bip32.private ||
67
- version === x.bip32.public
68
- }).pop()
69
-
70
- if (!network) throw new Error('Unknown network version')
71
-
72
- // otherwise, assume a network object (or default to bitcoin)
73
- } else {
74
- network = networks || NETWORKS.bitcoin
75
- }
76
-
77
- if (version !== network.bip32.private &&
78
- version !== network.bip32.public) throw new Error('Invalid network version')
79
-
80
- // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ...
81
- var depth = buffer[4]
82
-
83
- // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
84
- var parentFingerprint = buffer.readUInt32BE(5)
85
- if (depth === 0) {
86
- if (parentFingerprint !== 0x00000000) throw new Error('Invalid parent fingerprint')
87
- }
88
-
89
- // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
90
- // This is encoded in MSB order. (0x00000000 if master key)
91
- var index = buffer.readUInt32BE(9)
92
- if (depth === 0 && index !== 0) throw new Error('Invalid index')
93
-
94
- // 32 bytes: the chain code
95
- var chainCode = buffer.slice(13, 45)
96
- var keyPair
97
-
98
- // 33 bytes: private key data (0x00 + k)
99
- if (version === network.bip32.private) {
100
- if (buffer.readUInt8(45) !== 0x00) throw new Error('Invalid private key')
101
-
102
- var d = BigInteger.fromBuffer(buffer.slice(46, 78))
103
- keyPair = new ECPair(d, null, { network: network })
104
-
105
- // 33 bytes: public key data (0x02 + X or 0x03 + X)
106
- } else {
107
- var Q = ecurve.Point.decodeFrom(curve, buffer.slice(45, 78))
108
- // Q.compressed is assumed, if somehow this assumption is broken, `new HDNode` will throw
109
-
110
- // Verify that the X coordinate in the public point corresponds to a point on the curve.
111
- // If not, the extended public key is invalid.
112
- curve.validate(Q)
113
-
114
- keyPair = new ECPair(null, Q, { network: network })
115
- }
116
-
117
- var hd = new HDNode(keyPair, chainCode)
118
- hd.depth = depth
119
- hd.index = index
120
- hd.parentFingerprint = parentFingerprint
121
-
122
- return hd
123
- }
124
-
125
- HDNode.prototype.getAddress = function () {
126
- return this.keyPair.getAddress()
127
- }
128
-
129
- HDNode.prototype.getIdentifier = function () {
130
- return bcrypto.hash160(this.keyPair.getPublicKeyBuffer())
131
- }
132
-
133
- HDNode.prototype.getFingerprint = function () {
134
- return this.getIdentifier().slice(0, 4)
135
- }
136
-
137
- HDNode.prototype.getNetwork = function () {
138
- return this.keyPair.getNetwork()
139
- }
140
-
141
- HDNode.prototype.getPublicKeyBuffer = function () {
142
- return this.keyPair.getPublicKeyBuffer()
143
- }
144
-
145
- HDNode.prototype.neutered = function () {
146
- var neuteredKeyPair = new ECPair(null, this.keyPair.Q, {
147
- network: this.keyPair.network
148
- })
149
-
150
- var neutered = new HDNode(neuteredKeyPair, this.chainCode)
151
- neutered.depth = this.depth
152
- neutered.index = this.index
153
- neutered.parentFingerprint = this.parentFingerprint
154
-
155
- return neutered
156
- }
157
-
158
- HDNode.prototype.sign = function (hash) {
159
- return this.keyPair.sign(hash)
160
- }
161
-
162
- HDNode.prototype.verify = function (hash, signature) {
163
- return this.keyPair.verify(hash, signature)
164
- }
165
-
166
- HDNode.prototype.toBase58 = function (__isPrivate) {
167
- if (__isPrivate !== undefined) throw new TypeError('Unsupported argument in 2.0.0')
168
-
169
- // Version
170
- var network = this.keyPair.network
171
- var version = (!this.isNeutered()) ? network.bip32.private : network.bip32.public
172
- var buffer = Buffer.allocUnsafe(78)
173
-
174
- // 4 bytes: version bytes
175
- buffer.writeUInt32BE(version, 0)
176
-
177
- // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ....
178
- buffer.writeUInt8(this.depth, 4)
179
-
180
- // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
181
- buffer.writeUInt32BE(this.parentFingerprint, 5)
182
-
183
- // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
184
- // This is encoded in big endian. (0x00000000 if master key)
185
- buffer.writeUInt32BE(this.index, 9)
186
-
187
- // 32 bytes: the chain code
188
- this.chainCode.copy(buffer, 13)
189
-
190
- // 33 bytes: the public key or private key data
191
- if (!this.isNeutered()) {
192
- // 0x00 + k for private keys
193
- buffer.writeUInt8(0, 45)
194
- this.keyPair.d.toBuffer(32).copy(buffer, 46)
195
-
196
- // 33 bytes: the public key
197
- } else {
198
- // X9.62 encoding for public keys
199
- this.keyPair.getPublicKeyBuffer().copy(buffer, 45)
200
- }
201
-
202
- return base58check.encode(buffer)
203
- }
204
-
205
- // https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#child-key-derivation-ckd-functions
206
- HDNode.prototype.derive = function (index) {
207
- typeforce(types.UInt32, index)
208
-
209
- var isHardened = index >= HDNode.HIGHEST_BIT
210
- var data = Buffer.allocUnsafe(37)
211
-
212
- // Hardened child
213
- if (isHardened) {
214
- if (this.isNeutered()) throw new TypeError('Could not derive hardened child key')
215
-
216
- // data = 0x00 || ser256(kpar) || ser32(index)
217
- data[0] = 0x00
218
- this.keyPair.d.toBuffer(32).copy(data, 1)
219
- data.writeUInt32BE(index, 33)
220
-
221
- // Normal child
222
- } else {
223
- // data = serP(point(kpar)) || ser32(index)
224
- // = serP(Kpar) || ser32(index)
225
- this.keyPair.getPublicKeyBuffer().copy(data, 0)
226
- data.writeUInt32BE(index, 33)
227
- }
228
-
229
- var I = createHmac('sha512', this.chainCode).update(data).digest()
230
- var IL = I.slice(0, 32)
231
- var IR = I.slice(32)
232
-
233
- var pIL = BigInteger.fromBuffer(IL)
234
-
235
- // In case parse256(IL) >= n, proceed with the next value for i
236
- if (pIL.compareTo(curve.n) >= 0) {
237
- return this.derive(index + 1)
238
- }
239
-
240
- // Private parent key -> private child key
241
- var derivedKeyPair
242
- if (!this.isNeutered()) {
243
- // ki = parse256(IL) + kpar (mod n)
244
- var ki = pIL.add(this.keyPair.d).mod(curve.n)
245
-
246
- // In case ki == 0, proceed with the next value for i
247
- if (ki.signum() === 0) {
248
- return this.derive(index + 1)
249
- }
250
-
251
- derivedKeyPair = new ECPair(ki, null, {
252
- network: this.keyPair.network
253
- })
254
-
255
- // Public parent key -> public child key
256
- } else {
257
- // Ki = point(parse256(IL)) + Kpar
258
- // = G*IL + Kpar
259
- var Ki = curve.G.multiply(pIL).add(this.keyPair.Q)
260
-
261
- // In case Ki is the point at infinity, proceed with the next value for i
262
- if (curve.isInfinity(Ki)) {
263
- return this.derive(index + 1)
264
- }
265
-
266
- derivedKeyPair = new ECPair(null, Ki, {
267
- network: this.keyPair.network
268
- })
269
- }
270
-
271
- var hd = new HDNode(derivedKeyPair, IR)
272
- hd.depth = this.depth + 1
273
- hd.index = index
274
- hd.parentFingerprint = this.getFingerprint().readUInt32BE(0)
275
-
276
- return hd
277
- }
278
-
279
- HDNode.prototype.deriveHardened = function (index) {
280
- typeforce(types.UInt31, index)
281
-
282
- // Only derives hardened private keys by default
283
- return this.derive(index + HDNode.HIGHEST_BIT)
284
- }
285
-
286
- // Private === not neutered
287
- // Public === neutered
288
- HDNode.prototype.isNeutered = function () {
289
- return !(this.keyPair.d)
290
- }
291
-
292
- HDNode.prototype.derivePath = function (path) {
293
- typeforce(types.BIP32Path, path)
294
-
295
- var splitPath = path.split('/')
296
- if (splitPath[0] === 'm') {
297
- if (this.parentFingerprint) {
298
- throw new Error('Not a master node')
299
- }
300
-
301
- splitPath = splitPath.slice(1)
302
- }
303
-
304
- return splitPath.reduce(function (prevHd, indexStr) {
305
- var index
306
- if (indexStr.slice(-1) === "'") {
307
- index = parseInt(indexStr.slice(0, -1), 10)
308
- return prevHd.deriveHardened(index)
309
- } else {
310
- index = parseInt(indexStr, 10)
311
- return prevHd.derive(index)
312
- }
313
- }, this)
314
- }
315
-
316
- module.exports = HDNode