ECPair: extract WIF to 3rd party module
This commit is contained in:
parent
e5e24256fd
commit
efacd387be
5 changed files with 31 additions and 56 deletions
|
@ -51,7 +51,8 @@
|
||||||
"create-hmac": "^1.1.3",
|
"create-hmac": "^1.1.3",
|
||||||
"ecurve": "^1.0.0",
|
"ecurve": "^1.0.0",
|
||||||
"randombytes": "^2.0.1",
|
"randombytes": "^2.0.1",
|
||||||
"typeforce": "^1.3.0"
|
"typeforce": "^1.3.0",
|
||||||
|
"wif": "^1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"async": "^0.9.0",
|
"async": "^0.9.0",
|
||||||
|
|
|
@ -5,6 +5,7 @@ var ecurve = require('ecurve')
|
||||||
var randomBytes = require('randombytes')
|
var randomBytes = require('randombytes')
|
||||||
var typeforce = require('typeforce')
|
var typeforce = require('typeforce')
|
||||||
var types = require('./types')
|
var types = require('./types')
|
||||||
|
var wif = require('wif')
|
||||||
|
|
||||||
var NETWORKS = require('./networks')
|
var NETWORKS = require('./networks')
|
||||||
var BigInteger = require('bigi')
|
var BigInteger = require('bigi')
|
||||||
|
@ -57,46 +58,25 @@ ECPair.fromPublicKeyBuffer = function (buffer, network) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
ECPair.fromWIF = function (string, networks) {
|
ECPair.fromWIF = function (string, network) {
|
||||||
var payload = bs58check.decode(string)
|
network = network || NETWORKS.bitcoin
|
||||||
var version = payload.readUInt8(0)
|
var buffer = bs58check.decode(string)
|
||||||
var compressed
|
|
||||||
|
|
||||||
if (payload.length === 34) {
|
if (types.Array(network)) {
|
||||||
if (payload[33] !== 0x01) throw new Error('Invalid compression flag')
|
var version = buffer[0]
|
||||||
|
|
||||||
// truncate the version/compression bytes
|
network = network.filter(function (network) {
|
||||||
payload = payload.slice(1, -1)
|
|
||||||
compressed = true
|
|
||||||
|
|
||||||
// no compression flag
|
|
||||||
} else {
|
|
||||||
if (payload.length !== 33) throw new Error('Invalid WIF payload length')
|
|
||||||
|
|
||||||
// Truncate the version byte
|
|
||||||
payload = payload.slice(1)
|
|
||||||
compressed = false
|
|
||||||
}
|
|
||||||
|
|
||||||
var network
|
|
||||||
|
|
||||||
// list of networks?
|
|
||||||
if (Array.isArray(networks)) {
|
|
||||||
network = networks.filter(function (network) {
|
|
||||||
return version === network.wif
|
return version === network.wif
|
||||||
}).pop() || {}
|
}).pop() || {}
|
||||||
|
|
||||||
// otherwise, assume a network object (or default to bitcoin)
|
if (version !== network.wif) throw new Error('Invalid network version')
|
||||||
} else {
|
|
||||||
network = networks || NETWORKS.bitcoin
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version !== network.wif) throw new Error('Invalid network')
|
var decoded = wif.decodeRaw(network.wif, buffer)
|
||||||
|
var d = BigInteger.fromBuffer(decoded.d)
|
||||||
var d = BigInteger.fromBuffer(payload)
|
|
||||||
|
|
||||||
return new ECPair(d, null, {
|
return new ECPair(d, null, {
|
||||||
compressed: compressed,
|
compressed: decoded.compressed,
|
||||||
network: network
|
network: network
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -114,22 +94,6 @@ ECPair.makeRandom = function (options) {
|
||||||
return new ECPair(d, null, options)
|
return new ECPair(d, null, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
ECPair.prototype.toWIF = function () {
|
|
||||||
if (!this.d) throw new Error('Missing private key')
|
|
||||||
|
|
||||||
var bufferLen = this.compressed ? 34 : 33
|
|
||||||
var buffer = new Buffer(bufferLen)
|
|
||||||
|
|
||||||
buffer.writeUInt8(this.network.wif, 0)
|
|
||||||
this.d.toBuffer(32).copy(buffer, 1)
|
|
||||||
|
|
||||||
if (this.compressed) {
|
|
||||||
buffer.writeUInt8(0x01, 33)
|
|
||||||
}
|
|
||||||
|
|
||||||
return bs58check.encode(buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
ECPair.prototype.getAddress = function () {
|
ECPair.prototype.getAddress = function () {
|
||||||
var pubKey = this.getPublicKeyBuffer()
|
var pubKey = this.getPublicKeyBuffer()
|
||||||
var pubKeyHash = bcrypto.hash160(pubKey)
|
var pubKeyHash = bcrypto.hash160(pubKey)
|
||||||
|
@ -151,6 +115,12 @@ ECPair.prototype.sign = function (hash) {
|
||||||
return ecdsa.sign(secp256k1, hash, this.d)
|
return ecdsa.sign(secp256k1, hash, this.d)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ECPair.prototype.toWIF = function () {
|
||||||
|
if (!this.d) throw new Error('Missing private key')
|
||||||
|
|
||||||
|
return wif.encode(this.network.wif, this.d.toBuffer(32), this.compressed)
|
||||||
|
}
|
||||||
|
|
||||||
ECPair.prototype.verify = function (hash, signature) {
|
ECPair.prototype.verify = function (hash, signature) {
|
||||||
return ecdsa.verify(secp256k1, hash, signature, this.Q)
|
return ecdsa.verify(secp256k1, hash, signature, this.Q)
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ describe('Bitcoin-core', function () {
|
||||||
it('throws on ' + string, function () {
|
it('throws on ' + string, function () {
|
||||||
assert.throws(function () {
|
assert.throws(function () {
|
||||||
bitcoin.ECPair.fromWIF(string, allowedNetworks)
|
bitcoin.ECPair.fromWIF(string, allowedNetworks)
|
||||||
}, /(Invalid|Unknown) (checksum|compression flag|network|WIF payload)/)
|
}, /(Invalid|Unknown) (checksum|compression flag|network version|WIF length)/)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -129,9 +129,9 @@ describe('ECPair', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
fixtures.invalid.fromWIF.forEach(function (f) {
|
fixtures.invalid.fromWIF.forEach(function (f) {
|
||||||
it('throws on ' + f.string, function () {
|
it('throws on ' + f.WIF, function () {
|
||||||
assert.throws(function () {
|
assert.throws(function () {
|
||||||
ECPair.fromWIF(f.string)
|
ECPair.fromWIF(f.WIF)
|
||||||
}, new RegExp(f.exception))
|
}, new RegExp(f.exception))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
14
test/fixtures/ecpair.json
vendored
14
test/fixtures/ecpair.json
vendored
|
@ -85,17 +85,21 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fromWIF": [
|
"fromWIF": [
|
||||||
|
{
|
||||||
|
"exception": "Invalid network version",
|
||||||
|
"WIF": "92Qba5hnyWSn5Ffcka56yMQauaWY6ZLd91Vzxbi4a9CCetaHtYj"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"exception": "Invalid compression flag",
|
"exception": "Invalid compression flag",
|
||||||
"string": "ju9rooVsmagsb4qmNyTysUSFB1GB6MdpD7eoGjUTPmZRAApJxRz"
|
"WIF": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sfZr2ym"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"exception": "Invalid WIF payload length",
|
"exception": "Invalid WIF length",
|
||||||
"string": "7ZEtRQLhCsDQrd6ZKfmcESdXgas8ggZPN24ByEi5ey6VJW"
|
"WIF": "3tq8Vmhh9SN5XhjTGSWgx8iKk59XbKG6UH4oqpejRuJhfYD"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"exception": "Invalid WIF payload length",
|
"exception": "Invalid WIF length",
|
||||||
"string": "5qibUKwsnMo1qDiNp3prGaQkD2JfVJa8F8Na87H2CkMHvuVg6uKhw67Rh"
|
"WIF": "38uMpGARR2BJy5p4dNFKYg9UsWNoBtkpbdrXDjmfvz8krCtw3T1W92ZDSR"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue