Keys: Refactored to use Pubkey and Privkey and removed Keypair

This commit is contained in:
Braydon Fuller 2014-11-24 12:53:16 -05:00
parent 33d0bc0255
commit 23c1ed3599
7 changed files with 62 additions and 290 deletions

View File

@ -22,7 +22,6 @@ bitcore.Address = require('./lib/address');
bitcore.BIP32 = require('./lib/bip32');
bitcore.Block = require('./lib/block');
bitcore.Blockheader = require('./lib/blockheader');
bitcore.Keypair = require('./lib/keypair');
bitcore.Networks = require('./lib/networks');
bitcore.Opcode = require('./lib/opcode');
bitcore.Privkey = require('./lib/privkey');

View File

@ -6,7 +6,6 @@ var Hash = require('./crypto/hash');
var Point = require('./crypto/point');
var Random = require('./crypto/random');
var BN = require('./crypto/bn');
var Keypair = require('./keypair');
var Pubkey = require('./pubkey');
var Privkey = require('./privkey');
@ -27,7 +26,6 @@ BIP32.prototype.set = function(obj) {
this.parentfingerprint = obj.parentfingerprint || this.parentfingerprint;
this.childindex = obj.childindex || this.childindex;
this.chaincode = obj.chaincode || this.chaincode;
this.keypair = obj.keypair || this.keypair;
this.hasprivkey = typeof obj.hasprivkey !== 'undefined' ? obj.hasprivkey : this.hasprivkey;
this.pubkeyhash = obj.pubkeyhash || this.pubkeyhash;
this.xpubkey = obj.xpubkey || this.xpubkey;
@ -43,9 +41,10 @@ BIP32.prototype.fromRandom = function(networkstr) {
this.parentfingerprint = new Buffer([0, 0, 0, 0]);
this.childindex = new Buffer([0, 0, 0, 0]);
this.chaincode = Random.getRandomBuffer(32);
this.keypair = (new Keypair()).fromRandom();
this.privkey = Privkey().fromRandom();
this.pubkey = new Pubkey().fromPrivkey(this.privkey);
this.hasprivkey = true;
this.pubkeyhash = Hash.sha256ripemd160(this.keypair.pubkey.toBuffer());
this.pubkeyhash = Hash.sha256ripemd160(this.pubkey.toBuffer());
this.buildxpubkey();
this.buildxprivkey();
};
@ -73,11 +72,10 @@ BIP32.prototype.fromSeed = function(bytes, networkstr) {
this.childindex = new Buffer([0, 0, 0, 0]);
this.chaincode = hash.slice(32, 64);
this.version = networks[networkstr].bip32privkey;
this.keypair = new Keypair();
this.keypair.privkey = new Privkey({bn: BN().fromBuffer(hash.slice(0, 32))});
this.keypair.privkey2pubkey();
this.privkey = new Privkey({bn: BN().fromBuffer(hash.slice(0, 32))});
this.pubkey = new Pubkey().fromPrivkey(this.privkey);
this.hasprivkey = true;
this.pubkeyhash = Hash.sha256ripemd160(this.keypair.pubkey.toBuffer());
this.pubkeyhash = Hash.sha256ripemd160(this.pubkey.toBuffer());
this.buildxpubkey();
this.buildxprivkey();
@ -107,15 +105,13 @@ BIP32.prototype.initFromBytes = function(bytes) {
this.version == networks.testnet.bip32pubkey);
if (isPrivate && keyBytes[0] == 0) {
this.keypair = new Keypair();
this.keypair.privkey = new Privkey({bn: BN().fromBuffer(keyBytes.slice(1, 33))});
this.keypair.privkey2pubkey();
this.pubkeyhash = Hash.sha256ripemd160(this.keypair.pubkey.toBuffer());
this.privkey = new Privkey({bn: BN().fromBuffer(keyBytes.slice(1, 33))});
this.pubkey = new Pubkey().fromPrivkey(this.privkey);
this.pubkeyhash = Hash.sha256ripemd160(this.pubkey.toBuffer());
this.hasprivkey = true;
} else if (isPublic && (keyBytes[0] == 0x02 || keyBytes[0] == 0x03)) {
this.keypair = new Keypair();
this.keypair.pubkey = (new Pubkey()).fromDER(keyBytes);
this.pubkeyhash = Hash.sha256ripemd160(this.keypair.pubkey.toBuffer());
this.pubkey = (new Pubkey()).fromDER(keyBytes);
this.pubkeyhash = Hash.sha256ripemd160(this.pubkey.toBuffer());
this.hasprivkey = false;
} else {
throw new Error('Invalid key');
@ -155,7 +151,7 @@ BIP32.prototype.buildxpubkey = function() {
new Buffer([(this.childindex >>> 8) & 0xff]),
new Buffer([this.childindex & 0xff]),
this.chaincode,
this.keypair.pubkey.toBuffer()
this.pubkey.toBuffer()
]);
}
@ -188,7 +184,7 @@ BIP32.prototype.buildxprivkey = function() {
new Buffer([this.childindex & 0xff]),
this.chaincode,
new Buffer([0]),
this.keypair.privkey.bn.toBuffer({size: 32})
this.privkey.bn.toBuffer({size: 32})
]);
}
@ -259,9 +255,9 @@ BIP32.prototype.deriveChild = function(i) {
var data = null;
if (usePrivate) {
data = Buffer.concat([new Buffer([0]), this.keypair.privkey.bn.toBuffer({size: 32}), ib]);
data = Buffer.concat([new Buffer([0]), this.privkey.bn.toBuffer({size: 32}), ib]);
} else {
data = Buffer.concat([this.keypair.pubkey.toBuffer({size: 32}), ib]);
data = Buffer.concat([this.pubkey.toBuffer({size: 32}), ib]);
}
var hash = Hash.sha512hmac(data, this.chaincode);
@ -269,25 +265,24 @@ BIP32.prototype.deriveChild = function(i) {
var ir = hash.slice(32, 64);
// ki = IL + kpar (mod n).
var k = il.add(this.keypair.privkey.bn).mod(Point.getN());
var k = il.add(this.privkey.bn).mod(Point.getN());
ret = new BIP32();
ret.chaincode = ir;
ret.keypair = new Keypair();
ret.keypair.privkey = new Privkey({bn: k});
ret.keypair.privkey2pubkey();
ret.privkey = new Privkey({bn: k});
ret.pubkey = new Pubkey().fromPrivkey(ret.privkey);
ret.hasprivkey = true;
} else {
var data = Buffer.concat([this.keypair.pubkey.toBuffer(), ib]);
var data = Buffer.concat([this.pubkey.toBuffer(), ib]);
var hash = Hash.sha512hmac(data, this.chaincode);
var il = BN().fromBuffer(hash.slice(0, 32));
var ir = hash.slice(32, 64);
// Ki = (IL + kpar)*G = IL*G + Kpar
var ilG = Point.getG().mul(il);
var Kpar = this.keypair.pubkey.point;
var Kpar = this.pubkey.point;
var Ki = ilG.add(Kpar);
var newpub = new Pubkey();
newpub.point = Ki;
@ -295,9 +290,7 @@ BIP32.prototype.deriveChild = function(i) {
ret = new BIP32();
ret.chaincode = ir;
var keypair = new Keypair();
keypair.pubkey = newpub;
ret.keypair = keypair;
ret.pubkey = newpub;
ret.hasprivkey = false;
}
@ -306,7 +299,7 @@ BIP32.prototype.deriveChild = function(i) {
ret.version = this.version;
ret.depth = this.depth + 1;
ret.pubkeyhash = Hash.sha256ripemd160(ret.keypair.pubkey.toBuffer());
ret.pubkeyhash = Hash.sha256ripemd160(ret.pubkey.toBuffer());
ret.buildxpubkey();
ret.buildxprivkey();

View File

@ -4,7 +4,6 @@ var BN = require('./bn');
var Point = require('./point');
var Random = require('./random');
var Pubkey = require('../pubkey');
var Keypair = require('../keypair');
var Signature = require('../signature');
var ECDSA = function ECDSA(obj) {

View File

@ -1,81 +0,0 @@
'use strict';
var Privkey = require('./privkey');
var Pubkey = require('./pubkey');
var Keypair = function Keypair(obj) {
if (!(this instanceof Keypair))
return new Keypair(obj);
// breaks some tests
// TODO: allow keys to be created with simply `new Keypair()` (random gen.)
/*if (!obj) {
var privkey = Privkey().fromRandom();
var obj = this.fromPrivkey( privkey );
}*/
if (obj)
this.set(obj);
};
Keypair.prototype.set = function(obj) {
this.privkey = obj.privkey || this.privkey || undefined;
this.pubkey = obj.pubkey || this.pubkey || undefined;
return this;
};
Keypair.prototype.fromJSON = function(json) {
if (json.privkey)
this.set({privkey: Privkey().fromJSON(json.privkey)});
if (json.pubkey)
this.set({pubkey: Pubkey().fromJSON(json.pubkey)});
return this;
};
Keypair.prototype.toJSON = function() {
var json = {};
if (this.privkey)
json.privkey = this.privkey.toJSON();
if (this.pubkey)
json.pubkey = this.pubkey.toJSON();
return json;
};
Keypair.prototype.fromPrivkey = function(privkey) {
this.privkey = privkey;
this.privkey2pubkey();
return this;
};
Keypair.prototype.fromRandom = function() {
this.privkey = Privkey().fromRandom();
this.privkey2pubkey();
return this;
};
Keypair.prototype.fromString = function(str) {
var obj = JSON.parse(str);
if (obj.privkey) {
this.privkey = new Privkey();
this.privkey.fromString(obj.privkey);
}
if (obj.pubkey) {
this.pubkey = new Pubkey();
this.pubkey.fromString(obj.pubkey);
}
};
Keypair.prototype.privkey2pubkey = function() {
this.pubkey = Pubkey().fromPrivkey(this.privkey);
};
Keypair.prototype.toString = function() {
var obj = {};
if (this.privkey)
obj.privkey = this.privkey.toString();
if (this.pubkey)
obj.pubkey = this.pubkey.toString();
return JSON.stringify(obj);
};
module.exports = Keypair;

View File

@ -5,6 +5,7 @@ var Point = require('./crypto/point');
var Random = require('./crypto/random');
var networks = require('./networks');
var base58check = require('./encoding/base58check');
var Pubkey = require('./pubkey');
var Privkey = function Privkey(bn) {
if (!(this instanceof Privkey))
@ -99,6 +100,10 @@ Privkey.prototype.toString = function() {
return this.toWIF();
};
Privkey.prototype.toPubkey = function() {
return new Pubkey().fromPrivkey(this);
}
Privkey.prototype.fromString = function(str) {
this.fromWIF(str);
};

View File

@ -1,178 +0,0 @@
'use strict';
var should = require('chai').should();
var bitcore = require('..');
var bn = bitcore.crypto.BN;
var Privkey = bitcore.Privkey;
var Pubkey = bitcore.Pubkey;
var Keypair = bitcore.Keypair;
describe('Keypair', function() {
it('should make a blank key', function() {
var key = new Keypair();
should.exist(key);
});
it('should make a key with a priv and pub', function() {
var priv = new Privkey();
var pub = new Pubkey();
var key = new Keypair({
privkey: priv,
pubkey: pub
});
should.exist(key);
should.exist(key.privkey);
should.exist(key.pubkey);
});
describe('#set', function() {
it('should make a new priv and pub', function() {
should.exist(new Keypair().set({
privkey: new Privkey()
}).privkey);
});
});
describe('#fromJSON', function() {
it('should make a keypair from this json', function() {
var privkey = Privkey().fromRandom();
var pubkey = Pubkey().fromPrivkey(privkey);
var keypair = Keypair().fromJSON({
privkey: privkey.toJSON(),
pubkey: pubkey.toJSON()
})
keypair.privkey.toString().should.equal(privkey.toString());
keypair.pubkey.toString().should.equal(pubkey.toString());
});
});
describe('#toJSON', function() {
it('should make json from this keypair', function() {
var json = Keypair().fromRandom().toJSON();
should.exist(json.privkey);
should.exist(json.pubkey);
var keypair = Keypair().fromJSON(json);
keypair.toJSON().privkey.toString().should.equal(json.privkey.toString());
keypair.toJSON().pubkey.toString().should.equal(json.pubkey.toString());
});
});
describe("#fromPrivkey", function() {
it('should make a new key from a privkey', function() {
should.exist(Keypair().fromPrivkey(Privkey().fromRandom()).pubkey);
});
});
describe("#fromRandom", function() {
it('should make a new priv and pub, should be compressed, mainnet', function() {
var key = new Keypair();
key.fromRandom();
should.exist(key.privkey);
should.exist(key.pubkey);
key.privkey.bn.gt(bn(0)).should.equal(true);
key.pubkey.point.getX().gt(bn(0)).should.equal(true);
key.pubkey.point.getY().gt(bn(0)).should.equal(true);
key.privkey.compressed.should.equal(true);
key.privkey.networkstr.should.equal('mainnet');
key.pubkey.compressed.should.equal(true);
});
});
describe("#fromString()", function() {
it('should recover a key creating with toString', function() {
var key = new Keypair();
key.fromRandom();
var priv = key.privkey;
var pub = key.pubkey;
var str = key.toString();
key.fromString(str);
should.exist(key.privkey);
should.exist(key.pubkey);
key.privkey.toString().should.equal(priv.toString());
key.pubkey.toString().should.equal(pub.toString());
});
it('should work with only Privkey set', function() {
var key = new Keypair();
key.fromRandom();
key.pubkey = undefined;
var priv = key.privkey;
var str = key.toString();
key.fromString(str);
should.exist(key.privkey);
key.privkey.toString().should.equal(priv.toString());
});
it('should work with only Pubkey set', function() {
var key = new Keypair();
key.fromRandom();
key.privkey = undefined;
var pub = key.pubkey;
var str = key.toString();
key.fromString(str);
should.exist(key.pubkey);
key.pubkey.toString().should.equal(pub.toString());
});
});
describe("#privkey2pubkey", function() {
it('should convert this known Privkey to known Pubkey', function() {
var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
var pubhex = '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc';
var key = new Keypair();
key.privkey = new Privkey({
bn: bn(new Buffer(privhex, 'hex'))
});
key.privkey2pubkey();
key.pubkey.toString().should.equal(pubhex);
});
it('should convert this known Privkey to known Pubkey and preserve compressed=true', function() {
var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
var key = new Keypair();
key.privkey = new Privkey({
bn: bn(new Buffer(privhex, 'hex'))
});
key.privkey.compressed = true;
key.privkey2pubkey();
key.pubkey.compressed.should.equal(true);
});
it('should convert this known Privkey to known Pubkey and preserve compressed=true', function() {
var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
var key = new Keypair();
key.privkey = new Privkey({
bn: bn(new Buffer(privhex, 'hex'))
});
key.privkey.compressed = false;
key.privkey2pubkey();
key.pubkey.compressed.should.equal(false);
});
});
describe("#toString()", function() {
it('should exist', function() {
var key = new Keypair();
key.fromRandom();
should.exist(key.toString());
});
});
});

View File

@ -5,6 +5,7 @@ var bitcore = require('..');
var BN = bitcore.crypto.BN;
var Point = bitcore.crypto.Point;
var Privkey = bitcore.Privkey;
var Pubkey = bitcore.Pubkey;
describe('Privkey', function() {
var hex = '96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a';
@ -133,4 +134,38 @@ describe('Privkey', function() {
});
describe("#toPubkey", function() {
it('should convert this known Privkey to known Pubkey', function() {
var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
var pubhex = '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc';
var privkey = new Privkey({
bn: BN(new Buffer(privhex, 'hex'))
});
var pubkey = privkey.toPubkey();
pubkey.toString().should.equal(pubhex);
});
it('should convert this known Privkey to known Pubkey and preserve compressed=true', function() {
var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
var privkey = new Privkey({
bn: BN(new Buffer(privhex, 'hex'))
});
privkey.compressed = true;
var pubkey = privkey.toPubkey();
pubkey.compressed.should.equal(true);
});
it('should convert this known Privkey to known Pubkey and preserve compressed=true', function() {
var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
var privkey = new Privkey({
bn: BN(new Buffer(privhex, 'hex'))
});
privkey.compressed = false;
var pubkey = privkey.toPubkey();
pubkey.compressed.should.equal(false);
});
});
});