bitcoinjs-lib/src/eckey.js

135 lines
3.4 KiB
JavaScript
Raw Normal View History

var assert = require('assert')
var base58check = require('./base58check')
var ecdsa = require('./ecdsa')
var networks = require('./networks')
2014-04-17 19:08:16 +10:00
var secureRandom = require('secure-random')
2014-04-17 19:08:16 +10:00
var Address = require('./address')
var crypto = require('./crypto')
2014-04-22 02:19:30 +10:00
var sec = require('./sec')
2014-04-18 06:17:41 +10:00
var ecparams = sec('secp256k1')
2014-05-03 10:04:54 +08:00
var BigInteger = require('bigi')
2014-04-22 02:19:30 +10:00
var ECPointFp = require('./ec').ECPointFp
2014-04-17 19:08:16 +10:00
function ECKey(D, compressed) {
2014-04-18 06:17:41 +10:00
assert(D.compareTo(BigInteger.ZERO) > 0, 'Private key must be greater than 0')
assert(D.compareTo(ecparams.getN()) < 0, 'Private key must be less than the curve order')
2014-04-17 19:08:16 +10:00
var Q = ecparams.getG().multiply(D)
2014-04-17 19:08:16 +10:00
this.D = D
this.pub = new ECPubKey(Q, compressed)
}
2014-04-17 19:08:16 +10:00
// Static constructors
ECKey.fromBuffer = function(buffer, compressed) {
2014-04-18 06:17:41 +10:00
assert(Buffer.isBuffer(buffer), 'First argument must be a Buffer')
assert.strictEqual(buffer.length, 32, 'Invalid buffer length')
2014-04-22 02:19:30 +10:00
var D = BigInteger.fromBuffer(buffer)
2014-04-17 19:08:16 +10:00
return new ECKey(D, compressed)
}
2014-04-17 19:08:16 +10:00
ECKey.fromHex = function(hex, compressed) {
return ECKey.fromBuffer(new Buffer(hex, 'hex'), compressed)
}
2014-04-17 19:08:16 +10:00
ECKey.fromWIF = function(string) {
var decode = base58check.decode(string)
2014-03-22 18:17:54 +11:00
2014-04-17 19:08:16 +10:00
var payload = decode.payload
if (payload.length === 33) {
2014-04-18 06:17:41 +10:00
assert.strictEqual(payload[32], 0x01, 'Invalid WIF string')
2014-04-17 19:08:16 +10:00
return ECKey.fromBuffer(payload.slice(0, 32), true)
}
return ECKey.fromBuffer(payload, false)
}
2014-04-17 19:08:16 +10:00
ECKey.makeRandom = function(compressed, rng) {
rng = rng || secureRandom
2014-04-17 19:08:16 +10:00
var buffer = new Buffer(rng(32))
2014-04-22 02:19:30 +10:00
var D = BigInteger.fromBuffer(buffer)
2014-04-17 19:08:16 +10:00
D = D.mod(ecparams.getN())
2014-04-17 19:08:16 +10:00
return new ECKey(D, compressed)
2013-11-18 23:47:56 -05:00
}
2014-04-17 19:08:16 +10:00
// Operations
ECKey.prototype.sign = function(hash) {
return ecdsa.sign(hash, this.D)
}
2014-04-17 19:08:16 +10:00
// Export functions
ECKey.prototype.toBuffer = function() {
return this.D.toBuffer(32)
2014-03-25 02:44:43 +11:00
}
2014-04-17 19:08:16 +10:00
ECKey.prototype.toHex = function() {
return this.toBuffer().toString('hex')
}
ECKey.prototype.toWIF = function(version) {
version = version || networks.bitcoin.wif
2014-03-25 02:44:43 +11:00
2014-04-18 06:17:41 +10:00
var buffer = this.toBuffer()
2014-04-17 19:08:16 +10:00
if (this.pub.compressed) {
2014-04-18 06:17:41 +10:00
buffer = Buffer.concat([buffer, new Buffer([0x01])])
}
2014-04-17 19:08:16 +10:00
return base58check.encode(buffer, version)
2014-01-08 17:13:26 -05:00
}
2014-04-17 19:08:16 +10:00
//////////////////////////////////////////////////////
2014-04-17 19:08:16 +10:00
function ECPubKey(Q, compressed) {
2014-04-18 06:17:41 +10:00
assert(Q instanceof ECPointFp, 'Q must be an ECPointFP')
2014-04-17 19:08:16 +10:00
if (compressed == undefined) compressed = true
2014-04-18 06:17:41 +10:00
assert.strictEqual(typeof compressed, 'boolean', 'Invalid compression flag')
2014-04-17 19:08:16 +10:00
this.compressed = compressed
this.Q = Q
}
2014-04-17 19:08:16 +10:00
// Static constructors
ECPubKey.fromBuffer = function(buffer) {
var type = buffer.readUInt8(0)
2014-04-18 06:17:41 +10:00
assert(type >= 0x02 || type <= 0x04, 'Invalid public key')
2014-04-17 19:08:16 +10:00
var compressed = (type !== 0x04)
2014-04-18 06:17:41 +10:00
assert.strictEqual(buffer.length, compressed ? 33 : 65, 'Invalid public key')
var Q = ECPointFp.decodeFrom(ecparams.getCurve(), buffer)
2014-04-17 19:08:16 +10:00
return new ECPubKey(Q, compressed)
}
2014-04-17 19:08:16 +10:00
ECPubKey.fromHex = function(hex) {
return ECPubKey.fromBuffer(new Buffer(hex, 'hex'))
}
2014-04-17 19:08:16 +10:00
// Operations
ECPubKey.prototype.verify = function(hash, sig) {
return ecdsa.verify(hash, sig, this.Q)
2014-01-16 14:02:21 +07:00
}
2014-03-22 18:17:54 +11:00
ECPubKey.prototype.getAddress = function(version) {
version = version || networks.bitcoin.pubKeyHash
return new Address(crypto.hash160(this.toBuffer()), version)
}
2014-04-17 19:08:16 +10:00
// Export functions
ECPubKey.prototype.toBuffer = function() {
2014-04-18 06:17:41 +10:00
return new Buffer(this.Q.getEncoded(this.compressed))
2014-04-17 19:08:16 +10:00
}
ECPubKey.prototype.toHex = function() {
return this.toBuffer().toString('hex')
2014-03-25 02:44:43 +11:00
}
2014-03-22 18:17:54 +11:00
module.exports = {
2014-03-24 03:19:39 +08:00
ECKey: ECKey,
ECPubKey: ECPubKey
2014-03-25 02:44:43 +11:00
}