var Address = require('./address') var assert = require('assert') var base58check = require('./base58check') var BigInteger = require('./jsbn/jsbn') var convert = require('./convert') var crypto = require('./crypto') var ecdsa = require('./ecdsa') var ECPointFp = require('./jsbn/ec').ECPointFp var sec = require('./jsbn/sec') var Network = require('./network') 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()) : Array.isArray(input) ? fromBin(input.slice(0, 32)) : typeof input != "string" ? null : input.length == 44 ? fromBin(convert.base64ToBytes(input)) : input.length == 51 && input[0] == '5' ? fromBin(base58check.decode(input).payload) : input.length == 51 && input[0] == '9' ? fromBin(base58check.decode(input).payload) : input.length == 52 && has('LK', input[0]) ? fromBin(base58check.decode(input).payload.slice(0, 32)) : input.length == 52 && input[0] == 'c' ? fromBin(base58check.decode(input).payload.slice(0, 32)) : has([64,65],input.length) ? fromBin(convert.hexToBytes(input.slice(0, 64))) : null assert(this.priv !== null) this.compressed = compressed !== undefined ? compressed : input instanceof ECKey ? input.compressed : input instanceof BigInteger ? false : Array.isArray(input) ? false : typeof input != "string" ? null : input.length == 44 ? false : input.length == 51 && input[0] == '5' ? false : input.length == 51 && input[0] == '9' ? false : input.length == 52 && has('LK', input[0]) ? true : input.length == 52 && input[0] == 'c' ? true : input.length == 64 ? false : input.length == 65 ? true : null assert(this.compressed !== null) } ECKey.prototype.getPub = function(compressed) { if (compressed === undefined) compressed = this.compressed return ECPubKey(ecparams.getG().multiply(this.priv), compressed) } ECKey.prototype.toBin = function() { return convert.bytesToString(this.toBytes()) } ECKey.version_bytes = { 0: 128, 111: 239 } ECKey.prototype.toWif = function(version) { version = version || Network.mainnet.addressVersion return base58check.encode(this.toBytes(), ECKey.version_bytes[version]) } ECKey.prototype.toHex = function() { return convert.bytesToHex(this.toBytes()) } ECKey.prototype.toBytes = function() { var bytes = this.priv.toByteArrayUnsigned() if (this.compressed) bytes.push(1) return bytes } ECKey.prototype.toBase64 = function() { return convert.bytesToBase64(this.toBytes()) } ECKey.prototype.toString = ECKey.prototype.toHex ECKey.prototype.getAddress = function(version) { return this.getPub().getAddress(version) } 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) } ECKey.prototype.sign = function(hash) { return ecdsa.sign(hash, this.priv) } ECKey.prototype.verify = function(hash, sig) { return this.getPub().verify(hash, sig) } var ECPubKey = function(input, compressed) { if (!(this instanceof ECPubKey)) { return new ECPubKey(input, compressed) } 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(convert.hexToBytes(input)) : Array.isArray(input) ? decode(input) : null assert(this.pub !== null) this.compressed = compressed ? 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.toBytes = function(compressed) { if (compressed === undefined) compressed = this.compressed return this.pub.getEncoded(compressed) } ECPubKey.prototype.toHex = function(compressed) { return convert.bytesToHex(this.toBytes(compressed)) } ECPubKey.prototype.toBin = function(compressed) { return convert.bytesToString(this.toBytes(compressed)) } ECPubKey.prototype.toWif = function(version) { version = version || Network.mainnet.addressVersion return base58check.encode(this.toBytes(), version) } ECPubKey.prototype.toString = ECPubKey.prototype.toHex ECPubKey.prototype.getAddress = function(version) { version = version || Network.mainnet.addressVersion return new Address(crypto.hash160(this.toBytes()), version) } ECPubKey.prototype.verify = function(hash, sig) { return ecdsa.verify(hash, sig, this.toBytes()) } module.exports = { ECKey: ECKey, ECPubKey: ECPubKey }