keypair improvements.

This commit is contained in:
Christopher Jeffrey 2016-02-04 03:30:12 -08:00
parent 1ee4e556b0
commit 99fac69127
4 changed files with 146 additions and 110 deletions

View File

@ -129,8 +129,8 @@ Address.prototype.removeKey = function removeKey(key) {
key = utils.toBuffer(key); key = utils.toBuffer(key);
var index = this.keys.map(function(pub, i) { var index = this.keys.map(function(k, i) {
return utils.isEqual(pub, key) ? i : null; return utils.isEqual(k, key) ? i : null;
}).filter(function(i) { }).filter(function(i) {
return i !== null; return i !== null;
})[0]; })[0];
@ -157,12 +157,12 @@ Address.prototype.getPrivateKey = function getPrivateKey(enc) {
return this.key.getPrivate(enc); return this.key.getPrivate(enc);
}; };
Address.toSecret = function toSecret(priv, compressed) { Address.toSecret = function toSecret(privateKey, compressed) {
return bcoin.keypair.toSecret(priv, compressed); return bcoin.keypair.toSecret(privateKey, compressed);
}; };
Address.fromSecret = function fromSecret(priv) { Address.fromSecret = function fromSecret(privateKey) {
return bcoin.keypair.fromSecret(priv); return bcoin.keypair.fromSecret(privateKey);
}; };
Address.prototype.getScript = function getScript() { Address.prototype.getScript = function getScript() {
@ -406,7 +406,7 @@ Address.prototype.ownInput = function ownInput(tx, index) {
Address.prototype.scriptInputs = function scriptInputs(tx) { Address.prototype.scriptInputs = function scriptInputs(tx) {
var self = this; var self = this;
var pub = this.getPublicKey(); var publicKey = this.getPublicKey();
var redeem = this.getScript(); var redeem = this.getScript();
return tx.inputs.reduce(function(total, input, i) { return tx.inputs.reduce(function(total, input, i) {
@ -416,7 +416,7 @@ Address.prototype.scriptInputs = function scriptInputs(tx) {
if (!self.ownOutput(input.prevout.tx, input.prevout.index)) if (!self.ownOutput(input.prevout.tx, input.prevout.index))
return total; return total;
if (tx.scriptInput(i, pub, redeem)) if (tx.scriptInput(i, publicKey, redeem))
total++; total++;
return total; return total;
@ -428,7 +428,7 @@ Address.prototype.signInputs = function signInputs(tx, type) {
var key = this.key; var key = this.key;
var total = 0; var total = 0;
if (!key.priv) if (!key.privateKey)
return 0; return 0;
return tx.inputs.reduce(function(total, input, i) { return tx.inputs.reduce(function(total, input, i) {
@ -447,11 +447,11 @@ Address.prototype.signInputs = function signInputs(tx, type) {
Address.prototype.sign = function sign(tx, type) { Address.prototype.sign = function sign(tx, type) {
var self = this; var self = this;
var pub = this.getPublicKey(); var publicKey = this.getPublicKey();
var redeem = this.getScript(); var redeem = this.getScript();
var key = this.key; var key = this.key;
if (!key.priv) if (!key.privateKey)
return 0; return 0;
// Add signature script to each input // Add signature script to each input
@ -463,7 +463,7 @@ Address.prototype.sign = function sign(tx, type) {
if (!self.ownOutput(input.prevout.tx, input.prevout.index)) if (!self.ownOutput(input.prevout.tx, input.prevout.index))
return total; return total;
if (tx.scriptSig(i, key, pub, redeem, type)) if (tx.scriptSig(i, key, publicKey, redeem, type))
total++; total++;
return total; return total;
@ -526,7 +526,7 @@ Address.prototype.toJSON = function toJSON(encrypt) {
}; };
Address.fromJSON = function fromJSON(json, decrypt) { Address.fromJSON = function fromJSON(json, decrypt) {
var priv, pub, xprivkey, multisig, compressed, key, w; var w;
assert.equal(json.v, 1); assert.equal(json.v, 1);
assert.equal(json.name, 'address'); assert.equal(json.name, 'address');
@ -538,7 +538,6 @@ Address.fromJSON = function fromJSON(json, decrypt) {
label: json.label, label: json.label,
change: json.change, change: json.change,
key: bcoin.keypair.fromJSON(json.key, decrypt), key: bcoin.keypair.fromJSON(json.key, decrypt),
multisig: multisig,
type: json.type, type: json.type,
subtype: json.subtype, subtype: json.subtype,
redeem: json.redeem ? utils.toArray(json.redeem, 'hex') : null, redeem: json.redeem ? utils.toArray(json.redeem, 'hex') : null,

View File

@ -1003,11 +1003,13 @@ HDPublicKey.prototype.deriveString = function deriveString(path) {
return this.pair.validate.apply(this.pair, arguments); return this.pair.validate.apply(this.pair, arguments);
}; };
HD.prototype.getPublic = function getPublic() { HD.prototype.getPublic =
HD.prototype.getPublicKey = function getPublicKey() {
return this.pair.getPublic.apply(this.pair, arguments); return this.pair.getPublic.apply(this.pair, arguments);
}; };
HD.prototype.getPrivate = function getPrivate() { HD.prototype.getPrivate =
HD.prototype.getPrivateKey = function getPrivateKey() {
return this.pair.getPrivate.apply(this.pair, arguments); return this.pair.getPrivate.apply(this.pair, arguments);
}; };
@ -1028,6 +1030,14 @@ HDPublicKey.prototype.deriveString = function deriveString(path) {
}); });
}); });
HDPrivateKey.prototype.toSecret = function toSecret() {
return bcoin.keypair.toSecret(this.privateKey, true);
};
HDPrivateKey.fromSecret = function fromSecret(privateKey) {
return bcoin.keypair.fromSecret(privateKey);
};
/** /**
* Helpers * Helpers
*/ */

View File

@ -25,12 +25,8 @@ function KeyPair(options) {
if (options instanceof KeyPair) if (options instanceof KeyPair)
return options; return options;
if (options.key instanceof KeyPair) if (options instanceof bcoin.ecdsa.keypair)
return options.key; options = { pair: options };
this.options = options;
this.pair = null;
this.compressed = options.compressed !== false;
if (options.key) if (options.key)
options.pair = options.key; options.pair = options.key;
@ -41,6 +37,13 @@ function KeyPair(options) {
if (options.pub) if (options.pub)
options.publicKey = options.pub; options.publicKey = options.pub;
if (options.key instanceof KeyPair)
return options.key;
this.options = options;
this.pair = null;
this.compressed = options.compressed !== false;
if (options.passphrase) if (options.passphrase)
options.entropy = utils.sha256(options.passphrase); options.entropy = utils.sha256(options.passphrase);
@ -48,6 +51,10 @@ function KeyPair(options) {
this.pair = options.privateKey.pair; this.pair = options.privateKey.pair;
} else if (options.publicKey instanceof bcoin.hd.publicKey) { } else if (options.publicKey instanceof bcoin.hd.publicKey) {
this.pair = options.publicKey.pair; this.pair = options.publicKey.pair;
} else if (options.pair instanceof bcoin.hd.privateKey) {
this.pair = options.pair.pair;
} else if (options.pair instanceof bcoin.hd.publicKey) {
this.pair = options.pair.pair;
} else if (options.pair) { } else if (options.pair) {
assert(options.pair instanceof bcoin.ecdsa.keypair); assert(options.pair instanceof bcoin.ecdsa.keypair);
this.pair = options.pair; this.pair = options.pair;
@ -65,65 +72,79 @@ function KeyPair(options) {
} }
KeyPair.prototype.__defineGetter__('priv', function() { KeyPair.prototype.__defineGetter__('priv', function() {
return this.pair.getPrivate(); return this.pair.priv;
}); });
KeyPair.prototype.__defineGetter__('pub', function() { KeyPair.prototype.__defineGetter__('pub', function() {
return this.pair.getPublic(); return this.pair.pub;
}); });
KeyPair.prototype.__defineGetter__('privateKey', function() { KeyPair.prototype.__defineGetter__('privateKey', function() {
return this.pair.getPrivate(); return this.getPrivateKey();
}); });
KeyPair.prototype.__defineGetter__('publicKey', function() { KeyPair.prototype.__defineGetter__('publicKey', function() {
return this.pair.getPublic(); return this.getPublicKey();
}); });
KeyPair.prototype.getPrivate = function getPrivate(enc) { KeyPair.prototype.validate = function validate() {
var priv = this.pair.getPrivate(); return this.pair.validate.apply(this.pair, arguments);
if (!priv)
return;
priv = priv.toArray();
if (enc === 'base58')
return KeyPair.toSecret(priv, this.compressed);
if (enc === 'hex')
return utils.toHex(priv);
return priv;
}; };
KeyPair.prototype.getPublic = function getPublic(enc) { KeyPair.prototype.sign = function sign(msg) {
var pub = this.pair.getPublic(this.compressed, 'array'); return this.pair.sign.apply(this.pair, arguments);
};
KeyPair.prototype.verify = function verify(msg, signature) {
return this.pair.verify.apply(this.pair, arguments);
};
KeyPair.prototype.getPrivate =
KeyPair.prototype.getPrivateKey = function getPrivateKey(enc) {
var privateKey = this.pair.getPrivate();
if (!privateKey)
return;
privateKey = privateKey.toArray();
if (enc === 'base58') if (enc === 'base58')
return utils.toBase58(pub); return KeyPair.toSecret(privateKey, this.compressed);
if (enc === 'hex') if (enc === 'hex')
return utils.toHex(pub); return utils.toHex(privateKey);
return pub; return privateKey;
};
KeyPair.prototype.getPublic =
KeyPair.prototype.getPublicKey = function getPublicKey(enc) {
var publicKey = this.pair.getPublic(this.compressed, 'array');
if (enc === 'base58')
return utils.toBase58(publicKey);
if (enc === 'hex')
return utils.toHex(publicKey);
return publicKey;
}; };
KeyPair.prototype.toSecret = function toSecret() { KeyPair.prototype.toSecret = function toSecret() {
return KeyPair.toSecret(this.getPrivate(), this.compressed); return KeyPair.toSecret(this.getPrivate(), this.compressed);
}; };
KeyPair.toSecret = function toSecret(priv, compressed) { KeyPair.toSecret = function toSecret(privateKey, compressed) {
var arr, chk; var arr, chk;
// We'll be using ncompressed public key as an address // We'll be using ncompressed public key as an address
arr = [network.prefixes.privkey]; arr = [network.prefixes.privkey];
// 0-pad key // 0-pad key
while (arr.length + priv.length < 33) while (arr.length + privateKey.length < 33)
arr.push(0); arr.push(0);
arr = arr.concat(priv); arr = arr.concat(privateKey);
if (compressed !== false) if (compressed !== false)
arr.push(1); arr.push(1);
@ -133,29 +154,41 @@ KeyPair.toSecret = function toSecret(priv, compressed) {
return utils.toBase58(arr.concat(chk)); return utils.toBase58(arr.concat(chk));
}; };
KeyPair.fromSecret = function fromSecret(priv) { KeyPair.fromSecret = function fromSecret(privateKey) {
var key, compressed; var key, compressed;
key = utils.fromBase58(priv); key = utils.fromBase58(privateKey);
assert(utils.isEqual(key.slice(-4), utils.checksum(key.slice(0, -4)))); assert(utils.isEqual(key.slice(-4), utils.checksum(key.slice(0, -4))));
assert.equal(key[0], network.prefixes.privkey); assert.equal(key[0], network.prefixes.privkey);
key = key.slice(0, -4); key = key.slice(0, -4);
if (key.length === 34) { if (key.length === 34) {
assert.equal(key[33], 1); assert.equal(key[33], 1);
priv = key.slice(1, -1); privateKey = key.slice(1, -1);
compressed = true; compressed = true;
} else { } else {
priv = key.slice(1); privateKey = key.slice(1);
compressed = false; compressed = false;
} }
return new KeyPair({ return new KeyPair({
privateKey: priv, privateKey: privateKey,
compressed: compressed compressed: compressed
}); });
}; };
KeyPair.verify = function verify(msg, sig, key) {
try {
return bcoin.ecdsa.verify(msg, sig, key);
} catch (e) {
return false;
}
};
KeyPair.sign = function sign(msg, key) {
return bcoin.ecdsa.sign(msg, key.priv);
};
KeyPair.prototype.toJSON = function toJSON(encrypt) { KeyPair.prototype.toJSON = function toJSON(encrypt) {
var json = { var json = {
v: 1, v: 1,
@ -164,19 +197,19 @@ KeyPair.prototype.toJSON = function toJSON(encrypt) {
}; };
if (this.pair.priv) { if (this.pair.priv) {
json.priv = encrypt json.privateKey = encrypt
? encrypt(this.getPrivate('base58')) ? encrypt(this.toSecret())
: this.getPrivate('base58'); : this.toSecret();
return json; return json;
} }
json.pub = this.getPublic('hex'); json.publicKey = this.getPublicKey('base58');
return json; return json;
}; };
KeyPair.fromJSON = function fromJSON(json, decrypt) { KeyPair.fromJSON = function fromJSON(json, decrypt) {
var key, priv, pub, compressed, xprivkey; var privateKey, publicKey, compressed;
var path = {};
assert.equal(json.v, 1); assert.equal(json.v, 1);
assert.equal(json.name, 'keypair'); assert.equal(json.name, 'keypair');
@ -184,25 +217,18 @@ KeyPair.fromJSON = function fromJSON(json, decrypt) {
if (json.encrypted && !decrypt) if (json.encrypted && !decrypt)
throw new Error('Cannot decrypt address'); throw new Error('Cannot decrypt address');
if (json.priv) { if (json.privateKey) {
priv = json.priv; privateKey = json.privateKey;
if (json.encrypted) if (json.encrypted)
priv = decrypt(priv); privateKey = decrypt(privateKey);
return KeyPair.fromSecret(privateKey);
key = KeyPair.fromSecret(json.priv);
priv = key.priv;
compressed = key.compressed;
return new KeyPair({
privateKey: priv,
compressed: compressed
});
} }
if (json.pub) { if (json.publicKey) {
pub = bcoin.utils.toArray(json.pub, 'hex'); publicKey = utils.fromBase58(json.publicKey);
compressed = pub[0] !== 0x04; compressed = publicKey[0] !== 0x04;
return new KeyPair({ return new KeyPair({
publicKey: pub, publicKey: publicKey,
compressed: compressed compressed: compressed
}); });
} }

View File

@ -33,8 +33,8 @@ function Wallet(options) {
if (options.hd) { if (options.hd) {
options.master = options.hd !== true options.master = options.hd !== true
? bcoin.hd.priv(options.hd) ? bcoin.hd.privateKey(options.hd)
: bcoin.hd.priv(); : bcoin.hd.privateKey();
delete options.hd; delete options.hd;
} }
@ -177,7 +177,8 @@ function Wallet(options) {
// Generate the last known receiving address // Generate the last known receiving address
key = this.createKey(false, Math.max(0, this.addressDepth - 1)); key = this.createKey(false, Math.max(0, this.addressDepth - 1));
this.current = bcoin.address({ this.current = bcoin.address({
priv: key.priv, privateKey: key.privateKey,
publicKey: key.publicKey,
type: this.type, type: this.type,
subtype: this.subtype, subtype: this.subtype,
m: this.m, m: this.m,
@ -201,7 +202,7 @@ function Wallet(options) {
key = this.createKey(); key = this.createKey();
this._firstKey = key; this._firstKey = key;
this.current = bcoin.address({ this.current = bcoin.address({
priv: key.priv, privateKey: key.privateKey,
type: this.type, type: this.type,
subtype: this.subtype, subtype: this.subtype,
m: this.m, m: this.m,
@ -238,7 +239,7 @@ Wallet.prototype.getID = function() {
return this.addresses[0].getKeyAddress(); return this.addresses[0].getKeyAddress();
if (this._firstKey) if (this._firstKey)
return bcoin.address.key2addr(this._firstKey.pub); return bcoin.address.key2addr(this._firstKey.publicKey);
assert(false); assert(false);
}; };
@ -290,18 +291,18 @@ Wallet.prototype._initAddresses = function() {
Wallet.prototype.addKey = function addKey(key) { Wallet.prototype.addKey = function addKey(key) {
var hdKey, has, i; var hdKey, has, i;
if (bcoin.hd.priv.isExtended(key)) if (bcoin.hd.privateKey.isExtended(key))
key = bcoin.hd.priv(key); key = bcoin.hd.privateKey(key);
else if (bcoin.hd.pub.isExtended(key)) else if (bcoin.hd.publicKey.isExtended(key))
key = bcoin.hd.pub(key); key = bcoin.hd.publicKey(key);
if (key instanceof bcoin.keypair) if (key instanceof bcoin.keypair)
key = key.hd; key = key.hd;
if (key instanceof bcoin.hd.priv) if (key instanceof bcoin.hd.privateKey)
key = key.hdpub; key = key.hdpub;
if (key instanceof bcoin.hd.pub) { if (key instanceof bcoin.hd.publicKey) {
hdKey = key; hdKey = key;
key = hdKey.publicKey; key = hdKey.publicKey;
} }
@ -310,8 +311,8 @@ Wallet.prototype.addKey = function addKey(key) {
if (!hdKey || !hdKey.isPurpose45()) if (!hdKey || !hdKey.isPurpose45())
throw new Error('Must add HD purpose keys to BIP45 wallet.'); throw new Error('Must add HD purpose keys to BIP45 wallet.');
has = this.purposeKeys.some(function(pub) { has = this.purposeKeys.some(function(k) {
return pub.xpubkey === hdKey.xpubkey; return k.xpubkey === hdKey.xpubkey;
}); });
if (has) if (has)
@ -383,18 +384,18 @@ Wallet.prototype.removeKey = function removeKey(key) {
assert(!this._keysFinalized); assert(!this._keysFinalized);
if (bcoin.hd.priv.isExtended(key)) if (bcoin.hd.privateKey.isExtended(key))
key = bcoin.hd.priv(key); key = bcoin.hd.privateKey(key);
else if (bcoin.hd.pub.isExtended(key)) else if (bcoin.hd.publicKey.isExtended(key))
key = bcoin.hd.pub(key); key = bcoin.hd.publicKey(key);
if (key instanceof bcoin.keypair) if (key instanceof bcoin.keypair)
key = key.hd; key = key.hd;
if (key instanceof bcoin.hd.priv) if (key instanceof bcoin.hd.privateKey)
key = key.hdpub; key = key.hdpub;
if (key instanceof bcoin.hd.pub) { if (key instanceof bcoin.hd.publicKey) {
hdKey = key; hdKey = key;
key = hd.publicKey; key = hd.publicKey;
} }
@ -403,8 +404,8 @@ Wallet.prototype.removeKey = function removeKey(key) {
if (!hdKey || !hdKey.isPurpose45()) if (!hdKey || !hdKey.isPurpose45())
throw new Error('Must add HD purpose keys to BIP45 wallet.'); throw new Error('Must add HD purpose keys to BIP45 wallet.');
index = this.purposeKeys.map(function(pub, i) { index = this.purposeKeys.map(function(k, i) {
return pub.xpubkey === hdKey.xpubkey ? i : null; return k.xpubkey === hdKey.xpubkey ? i : null;
}).filter(function(i) { }).filter(function(i) {
return i !== null; return i !== null;
})[0]; })[0];
@ -419,8 +420,8 @@ Wallet.prototype.removeKey = function removeKey(key) {
key = utils.toBuffer(key); key = utils.toBuffer(key);
index = this.keys.map(function(pub, i) { index = this.keys.map(function(k, i) {
return utils.isEqual(pub, key) ? i : null; return utils.isEqual(k, key) ? i : null;
}).filter(function(i) { }).filter(function(i) {
return i !== null; return i !== null;
})[0]; })[0];
@ -514,8 +515,8 @@ Wallet.prototype.createAddress = function createAddress(change, index) {
assert(this._initialized); assert(this._initialized);
var options = { var options = {
priv: key.priv, privateKey: key.privateKey,
pub: key.pub, publicKey: key.publicKey,
type: this.type, type: this.type,
subtype: this.subtype, subtype: this.subtype,
m: this.m, m: this.m,
@ -549,7 +550,7 @@ Wallet.prototype.createAddress = function createAddress(change, index) {
if (i !== this.cosignerIndex) if (i !== this.cosignerIndex)
options.keys.push(key); options.keys.push(key);
}, this); }, this);
options.keys.push(key.pub); options.keys.push(key.publicKey);
} }
address = this.addAddress(options); address = this.addAddress(options);
@ -671,8 +672,8 @@ Wallet.prototype.createKey = function createKey(change, index) {
} }
key = bcoin.ecdsa.genKeyPair(); key = bcoin.ecdsa.genKeyPair();
return { return {
priv: key.getPrivate().toArray(), privateKey: key.getPrivate().toArray(),
pub: key.getPublic(true, 'array') publicKey: key.getPublic(true, 'array')
}; };
} }
@ -691,8 +692,8 @@ Wallet.prototype.createKey = function createKey(change, index) {
} }
return { return {
priv: key.privateKey, privateKey: key.privateKey,
pub: key.publicKey publicKey: key.publicKey
}; };
}; };
@ -959,7 +960,7 @@ Wallet.prototype.toJSON = function toJSON(encrypt) {
}; };
Wallet.fromJSON = function fromJSON(json, decrypt) { Wallet.fromJSON = function fromJSON(json, decrypt) {
var priv, pub, xprivkey, multisig, compressed, key, w, i; var w;
assert.equal(json.v, 3); assert.equal(json.v, 3);
assert.equal(json.name, 'wallet'); assert.equal(json.name, 'wallet');
@ -991,12 +992,12 @@ Wallet.fromJSON = function fromJSON(json, decrypt) {
}; };
// Compat - Legacy // Compat - Legacy
Wallet.toSecret = function toSecret(priv, compressed) { Wallet.toSecret = function toSecret(privateKey, compressed) {
return bcoin.keypair.toSecret(priv, compressed); return bcoin.keypair.toSecret(privateKey, compressed);
}; };
Wallet.fromSecret = function fromSecret(priv) { Wallet.fromSecret = function fromSecret(privateKey) {
return bcoin.keypair.fromSecret(priv); return bcoin.keypair.fromSecret(privateKey);
}; };
Wallet.key2hash = function key2hash(key) { Wallet.key2hash = function key2hash(key) {