@exodus/bitcoinjs-lib-forks 0.0.1
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/CHANGELOG.md +3 -0
- package/LICENSE +21 -0
- package/README.md +207 -0
- package/package.json +67 -0
- package/src/address.js +97 -0
- package/src/block.js +177 -0
- package/src/bufferutils.js +56 -0
- package/src/crypto.js +29 -0
- package/src/ecdsa.js +161 -0
- package/src/ecpair.js +131 -0
- package/src/ecsignature.js +97 -0
- package/src/hdnode.js +316 -0
- package/src/index.js +23 -0
- package/src/networks.js +47 -0
- package/src/script.js +214 -0
- package/src/script_number.js +68 -0
- package/src/templates/index.js +74 -0
- package/src/templates/multisig/index.js +4 -0
- package/src/templates/multisig/input.js +71 -0
- package/src/templates/multisig/output.js +64 -0
- package/src/templates/nulldata.js +34 -0
- package/src/templates/pubkey/index.js +4 -0
- package/src/templates/pubkey/input.js +39 -0
- package/src/templates/pubkey/output.js +33 -0
- package/src/templates/pubkeyhash/index.js +4 -0
- package/src/templates/pubkeyhash/input.js +51 -0
- package/src/templates/pubkeyhash/output.js +42 -0
- package/src/templates/scripthash/index.js +4 -0
- package/src/templates/scripthash/input.js +84 -0
- package/src/templates/scripthash/output.js +34 -0
- package/src/templates/witnesscommitment/index.js +3 -0
- package/src/templates/witnesscommitment/output.js +42 -0
- package/src/templates/witnesspubkeyhash/index.js +4 -0
- package/src/templates/witnesspubkeyhash/input.js +44 -0
- package/src/templates/witnesspubkeyhash/output.js +33 -0
- package/src/templates/witnessscripthash/index.js +4 -0
- package/src/templates/witnessscripthash/input.js +63 -0
- package/src/templates/witnessscripthash/output.js +33 -0
- package/src/transaction.js +547 -0
- package/src/transaction_builder.js +825 -0
- package/src/types.js +53 -0
package/src/ecdsa.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
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
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
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
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
var bip66 = require('bip66')
|
|
2
|
+
var typeforce = require('typeforce')
|
|
3
|
+
var types = require('./types')
|
|
4
|
+
|
|
5
|
+
var BigInteger = require('bigi')
|
|
6
|
+
|
|
7
|
+
function ECSignature (r, s) {
|
|
8
|
+
typeforce(types.tuple(types.BigInt, types.BigInt), arguments)
|
|
9
|
+
|
|
10
|
+
this.r = r
|
|
11
|
+
this.s = s
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
ECSignature.parseCompact = function (buffer) {
|
|
15
|
+
typeforce(types.BufferN(65), buffer)
|
|
16
|
+
|
|
17
|
+
var flagByte = buffer.readUInt8(0) - 27
|
|
18
|
+
if (flagByte !== (flagByte & 7)) throw new Error('Invalid signature parameter')
|
|
19
|
+
|
|
20
|
+
var compressed = !!(flagByte & 4)
|
|
21
|
+
var recoveryParam = flagByte & 3
|
|
22
|
+
var signature = ECSignature.fromRSBuffer(buffer.slice(1))
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
compressed: compressed,
|
|
26
|
+
i: recoveryParam,
|
|
27
|
+
signature: signature
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
ECSignature.fromRSBuffer = function (buffer) {
|
|
32
|
+
typeforce(types.BufferN(64), buffer)
|
|
33
|
+
|
|
34
|
+
var r = BigInteger.fromBuffer(buffer.slice(0, 32))
|
|
35
|
+
var s = BigInteger.fromBuffer(buffer.slice(32, 64))
|
|
36
|
+
return new ECSignature(r, s)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
ECSignature.fromDER = function (buffer) {
|
|
40
|
+
var decode = bip66.decode(buffer)
|
|
41
|
+
var r = BigInteger.fromDERInteger(decode.r)
|
|
42
|
+
var s = BigInteger.fromDERInteger(decode.s)
|
|
43
|
+
|
|
44
|
+
return new ECSignature(r, s)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// BIP62: 1 byte hashType flag (only 0x01, 0x02, 0x03, 0x81, 0x82 and 0x83 are allowed)
|
|
48
|
+
ECSignature.parseScriptSignature = function (buffer) {
|
|
49
|
+
var hashType = buffer.readUInt8(buffer.length - 1)
|
|
50
|
+
var hashTypeMod = hashType & ~0xc0
|
|
51
|
+
|
|
52
|
+
if (hashTypeMod <= 0x00 || hashTypeMod >= 0x04) throw new Error('Invalid hashType ' + hashType)
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
signature: ECSignature.fromDER(buffer.slice(0, -1)),
|
|
56
|
+
hashType: hashType
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
ECSignature.prototype.toCompact = function (i, compressed) {
|
|
61
|
+
if (compressed) {
|
|
62
|
+
i += 4
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
i += 27
|
|
66
|
+
|
|
67
|
+
var buffer = Buffer.alloc(65)
|
|
68
|
+
buffer.writeUInt8(i, 0)
|
|
69
|
+
this.toRSBuffer(buffer, 1)
|
|
70
|
+
return buffer
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
ECSignature.prototype.toDER = function () {
|
|
74
|
+
var r = Buffer.from(this.r.toDERInteger())
|
|
75
|
+
var s = Buffer.from(this.s.toDERInteger())
|
|
76
|
+
|
|
77
|
+
return bip66.encode(r, s)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
ECSignature.prototype.toRSBuffer = function (buffer, offset) {
|
|
81
|
+
buffer = buffer || Buffer.alloc(64)
|
|
82
|
+
this.r.toBuffer(32).copy(buffer, offset)
|
|
83
|
+
this.s.toBuffer(32).copy(buffer, offset + 32)
|
|
84
|
+
return buffer
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
ECSignature.prototype.toScriptSignature = function (hashType) {
|
|
88
|
+
var hashTypeMod = hashType & ~0xc0
|
|
89
|
+
if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType)
|
|
90
|
+
|
|
91
|
+
var hashTypeBuffer = Buffer.alloc(1)
|
|
92
|
+
hashTypeBuffer.writeUInt8(hashType, 0)
|
|
93
|
+
|
|
94
|
+
return Buffer.concat([this.toDER(), hashTypeBuffer])
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
module.exports = ECSignature
|
package/src/hdnode.js
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
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
|