|
|
|
var BigInteger = require('./jsbn/jsbn');
|
|
|
|
var sec = require('./jsbn/sec');
|
|
|
|
var base58 = require('./base58');
|
|
|
|
var Crypto = require('./crypto-js/crypto');
|
|
|
|
var util = require('./util');
|
|
|
|
var conv = require('./convert');
|
|
|
|
var Address = require('./address');
|
|
|
|
var ecdsa = require('./ecdsa');
|
|
|
|
var ECPointFp = require('./jsbn/ec').ECPointFp;
|
|
|
|
|
|
|
|
var ecparams = sec("secp256k1");
|
|
|
|
|
|
|
|
// input can be nothing, array of bytes, hex string, or base58 string
|
|
|
|
var ECKey = function (input,compressed) {
|
|
|
|
if (!(this instanceof ECKey)) { return new ECKey(input,compressed); }
|
|
|
|
if (!input) {
|
|
|
|
// Generate new key
|
|
|
|
var n = ecparams.getN();
|
|
|
|
this.priv = ecdsa.getBigRandom(n);
|
|
|
|
this.compressed = compressed || false;
|
|
|
|
}
|
|
|
|
else this.import(input,compressed)
|
|
|
|
};
|
|
|
|
|
|
|
|
ECKey.prototype.import = function (input,compressed) {
|
|
|
|
function has(li,v) { return li.indexOf(v) >= 0 }
|
|
|
|
function fromBin(x) { return BigInteger.fromByteArrayUnsigned(x) }
|
|
|
|
this.priv =
|
|
|
|
input instanceof ECKey ? input.priv
|
|
|
|
: input instanceof BigInteger ? input.mod(ecparams.getN())
|
|
|
|
: util.isArray(input) ? fromBin(input.slice(0,32))
|
|
|
|
: typeof input != "string" ? null
|
|
|
|
: input.length == 44 ? fromBin(conv.base64ToBytes(input))
|
|
|
|
: input.length == 51 && input[0] == '5' ? fromBin(base58.checkDecode(input))
|
|
|
|
: input.length == 52 && has('LK',input[0]) ? fromBin(base58.checkDecode(input).slice(0,32))
|
|
|
|
: has([64,65],input.length) ? fromBin(conv.hexToBytes(input.slice(0,64)))
|
|
|
|
: null
|
|
|
|
|
|
|
|
this.compressed =
|
|
|
|
compressed !== undefined ? compressed
|
|
|
|
: input instanceof ECKey ? input.compressed
|
|
|
|
: input instanceof BigInteger ? false
|
|
|
|
: util.isArray(input) ? false
|
|
|
|
: typeof input != "string" ? null
|
|
|
|
: input.length == 44 ? false
|
|
|
|
: input.length == 51 && input[0] == '5' ? false
|
|
|
|
: input.length == 52 && has('LK',input[0]) ? true
|
|
|
|
: input.length == 64 ? false
|
|
|
|
: input.length == 65 ? true
|
|
|
|
: null
|
|
|
|
};
|
|
|
|
|
|
|
|
ECKey.prototype.getPub = function(compressed) {
|
|
|
|
if (compressed === undefined) compressed = this.compressed
|
|
|
|
return ECPubKey(ecparams.getG().multiply(this.priv),compressed)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @deprecated Reserved keyword, factory pattern. Use toHex, toBytes, etc.
|
|
|
|
*/
|
|
|
|
ECKey.prototype['export'] = function(format) {
|
|
|
|
format || (format = 'hex')
|
|
|
|
return this['to' + format.substr(0, 1).toUpperCase() + format.substr(1)]()
|
|
|
|
};
|
|
|
|
|
|
|
|
ECKey.prototype.toBin = function() {
|
|
|
|
return conv.bytesToString(this.toBytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
ECKey.prototype.toBase58 = function() {
|
|
|
|
return base58.checkEncode(this.toBytes(), 128)
|
|
|
|
}
|
|
|
|
|
|
|
|
ECKey.prototype.toWif = ECKey.prototype.toBase58
|
|
|
|
|
|
|
|
ECKey.prototype.toHex = function() {
|
|
|
|
return conv.bytesToHex(this.toBytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
ECKey.prototype.toBytes = function() {
|
|
|
|
var bytes = this.priv.toByteArrayUnsigned();
|
|
|
|
if (this.compressed) bytes.push(1)
|
|
|
|
return bytes
|
|
|
|
}
|
|
|
|
|
|
|
|
ECKey.prototype.toString = ECKey.prototype.toBase58
|
|
|
|
|
|
|
|
ECKey.prototype.getBitcoinAddress = function(v) {
|
|
|
|
return this.getPub().getBitcoinAddress(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
ECKey.prototype.add = function(key) {
|
|
|
|
return ECKey(this.priv.add(ECKey(key).priv),this.compressed)
|
|
|
|
}
|
|
|
|
|
|
|
|
ECKey.prototype.multiply = function(key) {
|
|
|
|
return ECKey(this.priv.multiply(ECKey(key).priv),this.compressed)
|
|
|
|
}
|
|
|
|
|
|
|
|
var ECPubKey = function(input,compressed) {
|
|
|
|
if (!(this instanceof ECPubKey)) { return new ECPubKey(input,compressed); }
|
|
|
|
if (!input) {
|
|
|
|
// Generate new key
|
|
|
|
var n = ecparams.getN();
|
|
|
|
this.pub = ecparams.getG().multiply(ecdsa.getBigRandom(n))
|
|
|
|
this.compressed = compressed || false;
|
|
|
|
}
|
|
|
|
else this.import(input,compressed)
|
|
|
|
}
|
|
|
|
|
|
|
|
ECPubKey.prototype.import = function(input,compressed) {
|
|
|
|
var decode = function(x) { return ECPointFp.decodeFrom(ecparams.getCurve(), x) }
|
|
|
|
this.pub =
|
|
|
|
input instanceof ECPointFp ? input
|
|
|
|
: input instanceof ECKey ? ecparams.getG().multiply(input.priv)
|
|
|
|
: input instanceof ECPubKey ? input.pub
|
|
|
|
: typeof input == "string" ? decode(conv.hexToBytes(input))
|
|
|
|
: util.isArray(input) ? decode(input)
|
|
|
|
: ecparams.getG().multiply(ecdsa.getBigRandom(ecparams.getN()))
|
|
|
|
|
|
|
|
this.compressed =
|
|
|
|
arguments.length > 1 ? compressed
|
|
|
|
: input instanceof ECPointFp ? input.compressed
|
|
|
|
: input instanceof ECPubKey ? input.compressed
|
|
|
|
: (this.pub[0] < 4)
|
|
|
|
}
|
|
|
|
|
|
|
|
ECPubKey.prototype.add = function(key) {
|
|
|
|
return ECPubKey(this.pub.add(ECPubKey(key).pub),this.compressed)
|
|
|
|
}
|
|
|
|
|
|
|
|
ECPubKey.prototype.multiply = function(key) {
|
|
|
|
return ECPubKey(this.pub.multiply(ECKey(key).priv),this.compressed)
|
|
|
|
}
|
|
|
|
|
|
|
|
ECPubKey.prototype['export'] = function(format) {
|
|
|
|
format || (format = 'hex')
|
|
|
|
return this['to' + format.substr(0, 1).toUpperCase() + format.substr(1)]()
|
|
|
|
}
|
|
|
|
|
|
|
|
ECPubKey.prototype.toBytes = function(compressed) {
|
|
|
|
if (compressed === undefined) compressed = this.compressed
|
|
|
|
return this.pub.getEncoded(compressed)
|
|
|
|
}
|
|
|
|
|
|
|
|
ECPubKey.prototype.toHex = function() {
|
|
|
|
return conv.bytesToHex(this.toBytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
ECPubKey.prototype.toBin = function() {
|
|
|
|
return conv.bytesToString(this.toBytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
ECPubKey.prototype.toBase58 = function() {
|
|
|
|
return base58.checkEncode(this.toBytes(), 128)
|
|
|
|
}
|
|
|
|
|
|
|
|
ECPubKey.prototype.toWif = ECPubKey.prototype.toBase58
|
|
|
|
|
|
|
|
ECPubKey.prototype.toString = function() {
|
|
|
|
return this.getBitcoinAddress().toString()
|
|
|
|
}
|
|
|
|
|
|
|
|
ECPubKey.prototype.getBitcoinAddress = function(v) {
|
|
|
|
return new Address(util.sha256ripe160(this.toBytes()), v);
|
|
|
|
}
|
|
|
|
|
|
|
|
ECKey.prototype.sign = function (hash) {
|
|
|
|
return ecdsa.sign(hash, this.priv);
|
|
|
|
};
|
|
|
|
|
|
|
|
ECKey.prototype.verify = function (hash, sig) {
|
|
|
|
return ecdsa.verify(hash, sig, this.getPub()['export']('bytes'));
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parse an exported private key contained in a string.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
module.exports = { ECKey: ECKey, ECPubKey: ECPubKey };
|