@exodus/bitcoinjs-lib-forks 0.0.3 → 0.0.5-rc.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/package.json +7 -10
- package/src/address.js +1 -2
- package/src/crypto.js +4 -9
- package/src/ecsignature.js +5 -2
- package/src/index.js +0 -3
- package/src/script.js +0 -1
- package/src/script_number.js +0 -2
- package/src/templates/multisig/input.js +0 -1
- package/src/templates/scripthash/input.js +0 -1
- package/src/templates/witnesscommitment/output.js +0 -1
- package/src/transaction.js +0 -1
- package/src/transaction_builder.js +36 -16
- package/CHANGELOG.md +0 -11
- package/src/block.js +0 -177
- package/src/ecdsa.js +0 -161
- package/src/ecpair.js +0 -131
- package/src/hdnode.js +0 -316
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/bitcoinjs-lib-forks",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5-rc.0",
|
|
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
|
-
|
|
1
|
+
const { hashSync } = require('@exodus/crypto/hash')
|
|
2
2
|
|
|
3
3
|
function ripemd160 (buffer) {
|
|
4
|
-
return
|
|
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
|
|
8
|
+
return hashSync('sha256', buffer, 'buffer')
|
|
13
9
|
}
|
|
14
10
|
|
|
15
11
|
function hash160 (buffer) {
|
|
16
|
-
return
|
|
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
|
}
|
package/src/ecsignature.js
CHANGED
|
@@ -77,10 +77,13 @@ ECSignature.prototype.toDER = function () {
|
|
|
77
77
|
return bip66.encode(r, s)
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
|
|
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
|
|
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
package/src/script_number.js
CHANGED
package/src/transaction.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
@@ -708,22 +711,22 @@ function canSign (input) {
|
|
|
708
711
|
)
|
|
709
712
|
}
|
|
710
713
|
|
|
711
|
-
TransactionBuilder.prototype.
|
|
714
|
+
TransactionBuilder.prototype._prepareForSigning = function (vin, keyPair, redeemScript, hashType, witnessValue, witnessScript) {
|
|
712
715
|
// TODO: remove keyPair.network matching in 4.0.0
|
|
713
716
|
if (keyPair.network && keyPair.network !== this.network) throw new TypeError('Inconsistent network')
|
|
714
717
|
if (!this.inputs[vin]) throw new Error('No input at index: ' + vin)
|
|
715
718
|
hashType = hashType || Transaction.SIGHASH_ALL
|
|
716
719
|
|
|
717
|
-
|
|
720
|
+
let input = this.inputs[vin]
|
|
718
721
|
|
|
719
722
|
// if redeemScript was previously provided, enforce consistency
|
|
720
723
|
if (input.redeemScript !== undefined &&
|
|
721
|
-
|
|
722
|
-
|
|
724
|
+
redeemScript &&
|
|
725
|
+
!input.redeemScript.equals(redeemScript)) {
|
|
723
726
|
throw new Error('Inconsistent redeemScript')
|
|
724
727
|
}
|
|
725
728
|
|
|
726
|
-
|
|
729
|
+
let kpPubKey = keyPair.publicKey || keyPair.getPublicKeyBuffer()
|
|
727
730
|
if (!canSign(input)) {
|
|
728
731
|
if (witnessValue !== undefined) {
|
|
729
732
|
if (input.value !== undefined && input.value !== witnessValue) throw new Error('Input didn\'t match witnessValue')
|
|
@@ -736,7 +739,7 @@ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashTy
|
|
|
736
739
|
}
|
|
737
740
|
|
|
738
741
|
// ready to sign
|
|
739
|
-
|
|
742
|
+
let signatureHash
|
|
740
743
|
if (this.bitcoinGold) {
|
|
741
744
|
signatureHash = this.tx.hashForGoldSignature(vin, input.signScript, witnessValue, hashType, input.witness)
|
|
742
745
|
} else if (this.bitcoinCash) {
|
|
@@ -750,20 +753,37 @@ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashTy
|
|
|
750
753
|
}
|
|
751
754
|
|
|
752
755
|
// enforce in order signing of public keys
|
|
753
|
-
|
|
756
|
+
const index = input.pubKeys.findIndex(function (pubKey, i) {
|
|
754
757
|
if (!kpPubKey.equals(pubKey)) return false
|
|
755
758
|
if (input.signatures[i]) throw new Error('Signature already exists')
|
|
756
759
|
if (kpPubKey.length !== 33 &&
|
|
757
760
|
input.signType === scriptTypes.P2WPKH) throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH')
|
|
758
761
|
|
|
759
|
-
var signature = keyPair.sign(signatureHash)
|
|
760
|
-
if (Buffer.isBuffer(signature)) signature = ECSignature.fromRSBuffer(signature)
|
|
761
|
-
|
|
762
|
-
input.signatures[i] = signature.toScriptSignature(hashType)
|
|
763
762
|
return true
|
|
764
763
|
})
|
|
765
764
|
|
|
766
|
-
if (
|
|
765
|
+
if (index === -1) throw new Error('Key pair cannot sign for this input')
|
|
766
|
+
|
|
767
|
+
return { input, index, signatureHash, hashType }
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
TransactionBuilder.prototype.signAsync = async function (vin, signer, redeemScript, suppliedHashType, witnessValue, witnessScript) {
|
|
771
|
+
if (!signer || !signer.publicKey || !signer.sign) throw new TypeError('signer must have sign and publicKey props')
|
|
772
|
+
const { input, index, signatureHash, hashType } = this._prepareForSigning(vin, signer, redeemScript, suppliedHashType, witnessValue, witnessScript)
|
|
773
|
+
|
|
774
|
+
let signature = await signer.sign(signatureHash)
|
|
775
|
+
if (Buffer.isBuffer(signature)) signature = ECSignature.fromRSBuffer(signature)
|
|
776
|
+
|
|
777
|
+
input.signatures[index] = signature.toScriptSignature(hashType)
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, suppliedHashType, witnessValue, witnessScript) {
|
|
781
|
+
const { input, index, signatureHash, hashType } = this._prepareForSigning(vin, keyPair, redeemScript, suppliedHashType, witnessValue, witnessScript)
|
|
782
|
+
|
|
783
|
+
let signature = keyPair.sign(signatureHash)
|
|
784
|
+
if (Buffer.isBuffer(signature)) signature = ECSignature.fromRSBuffer(signature)
|
|
785
|
+
|
|
786
|
+
input.signatures[index] = signature.toScriptSignature(hashType)
|
|
767
787
|
}
|
|
768
788
|
|
|
769
789
|
function signatureHashType (buffer) {
|
package/CHANGELOG.md
DELETED
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
|