Merge pull request #829 from eordano/review/keys

PrivateKey, PublicKey, Network linted
This commit is contained in:
Manuel Aráoz 2014-12-19 16:24:47 -03:00
commit 58f68ba8d2
6 changed files with 321 additions and 204 deletions

View File

@ -79,12 +79,22 @@ _.each(_.values(testnet), function(value) {
* @member Network#getNetwork
* Retrieves the network associated with a magic number or string.
* @param {string|number|Network} arg
* @param {string} key - if set, only check if the magic number associated with this name matches
* @return Network
*/
function getNetwork(arg) {
function getNetwork(arg, key) {
if (arg === livenet || arg === testnet) {
return arg;
}
if (key) {
var networks = [livenet, testnet];
for (var index in networks) {
if (networks[index][key] === arg) {
return networks[index];
}
}
return undefined;
}
return networkMaps[arg];
}

View File

@ -15,7 +15,6 @@ var Random = require('./crypto/random');
*
* @example
* ```javascript
*
* // generate a new random key
* var key = PrivateKey();
*
@ -29,12 +28,14 @@ var Random = require('./crypto/random');
* var imported = PrivateKey.fromWIF(exported);
* ```
*
* @param {String} data - The encoded data in various formats
* @param {String} [network] - Either "livenet" or "testnet"
* @param {string} data - The encoded data in various formats
* @param {Network|string} [network] - a {@link Network} object, or a string with the network name
* @returns {PrivateKey} A new valid instance of an PrivateKey
* @constructor
*/
var PrivateKey = function PrivateKey(data, network) {
/* jshint maxstatements: 20 */
/* jshint maxcomplexity: 8 */
if (!(this instanceof PrivateKey)) {
return new PrivateKey(data, network);
@ -43,29 +44,7 @@ var PrivateKey = function PrivateKey(data, network) {
return data;
}
var info = {
compressed: true,
network: network ? Networks.get(network) : Networks.defaultNetwork
};
// detect type of data
if (_.isUndefined(data)){
info.bn = PrivateKey._getRandomBN();
} else if (data instanceof BN) {
info.bn = data;
} else if (data instanceof Buffer || data instanceof Uint8Array) {
info = PrivateKey._transformBuffer(data, network);
} else if (PrivateKey._isJSON(data)){
info = PrivateKey._transformJSON(data);
} else if (typeof(data) === 'string'){
if (JSUtil.isHexa(data)) {
info.bn = BN(new Buffer(data, 'hex'));
} else {
info = PrivateKey._transformWIF(data, network);
}
} else {
throw new TypeError('First argument is an unrecognized data type.');
}
var info = this._classifyArguments(data, network);
// validation
if (!info.bn || info.bn.cmp(0) === 0){
@ -103,7 +82,43 @@ var PrivateKey = function PrivateKey(data, network) {
};
/**
* Internal function to get a random BN
* Internal helper to instantiate PrivateKey internal `info` object from
* different kinds of arguments passed to the constructor.
*
* @param {*} data
* @param {Network|string} [network] - a {@link Network} object, or a string with the network name
* @return {Object}
*/
PrivateKey.prototype._classifyArguments = function(data, network) {
/* jshint maxcomplexity: 10 */
var info = {
compressed: true,
network: network ? Networks.get(network) : Networks.defaultNetwork
};
// detect type of data
if (_.isUndefined(data)){
info.bn = PrivateKey._getRandomBN();
} else if (data instanceof BN) {
info.bn = data;
} else if (data instanceof Buffer || data instanceof Uint8Array) {
info = PrivateKey._transformBuffer(data, network);
} else if (PrivateKey._isJSON(data)){
info = PrivateKey._transformJSON(data);
} else if (typeof(data) === 'string'){
if (JSUtil.isHexa(data)) {
info.bn = BN(new Buffer(data, 'hex'));
} else {
info = PrivateKey._transformWIF(data, network);
}
} else {
throw new TypeError('First argument is an unrecognized data type.');
}
return info;
};
/**
* Internal function to get a random Big Number (BN)
*
* @returns {BN} A new randomly generated BN
* @private
@ -127,14 +142,14 @@ PrivateKey._getRandomBN = function(){
* @private
*/
PrivateKey._isJSON = function(json) {
return JSUtil.isValidJSON(json) || (json.bn && json.network && json.compressed);
return JSUtil.isValidJSON(json) || (json.bn && json.network);
};
/**
* Internal function to transform a WIF Buffer into a private key
*
* @param {Buffer} buf - An WIF string
* @param {String} [network] - Either "livenet" or "testnet"
* @param {Network|string} [network] - a {@link Network} object, or a string with the network name
* @returns {Object} An object with keys: bn, network and compressed
* @private
*/
@ -150,6 +165,7 @@ PrivateKey._transformBuffer = function(buf, network) {
throw new Error('Length of buffer must be 33 (uncompressed) or 34 (compressed)');
}
info.network = Networks.get(buf[0], 'privatekey');
if (buf[0] === Networks.livenet.privatekey) {
info.network = Networks.livenet;
} else if (buf[0] === Networks.testnet.privatekey) {
@ -210,7 +226,7 @@ PrivateKey._transformJSON = function(json) {
bn: bn,
network: json.network,
compressed: json.compressed
}
};
};
/**
@ -245,6 +261,7 @@ PrivateKey.fromRandom = function(network) {
PrivateKey.getValidationError = function(data, network) {
var error;
try {
/* jshint nonew: false */
new PrivateKey(data, network);
} catch (e) {
error = e;

View File

@ -9,11 +9,13 @@ var _ = require('lodash');
var $ = require('./util/preconditions');
/**
* Instantiate a PublicKey from a 'PrivateKey', 'Point', 'string', 'Buffer'.
* Instantiate a PublicKey from a {@link PrivateKey}, {@link Point}, `string`, or `Buffer`.
*
* There are two internal properties, `network` and `compressed`, that deal with importing
* a PublicKey from a PrivateKey in WIF format. More details described on {@link PrivateKey}
*
* @example
* ```javascript
*
* // instantiate from a private key
* var key = PublicKey(privateKey, true);
*
@ -45,25 +47,7 @@ var PublicKey = function PublicKey(data, extra) {
}
extra = extra || {};
var info = {
compressed: _.isUndefined(extra.compressed) || extra.compressed,
network: _.isUndefined(extra.network) ? undefined : Network.get(extra.network)
};
// detect type of data
if (data instanceof Point) {
info.point = data;
} else if (PublicKey._isJSON(data)) {
info = PublicKey._transformJSON(data);
} else if (typeof(data) === 'string') {
info = PublicKey._transformDER(new Buffer(data, 'hex'));
} else if (PublicKey._isBuffer(data)) {
info = PublicKey._transformDER(data);
} else if (PublicKey._isPrivateKey(data)) {
info = PublicKey._transformPrivateKey(data);
} else {
throw new TypeError('First argument is an unrecognized data format.');
}
var info = this._classifyArgs(data, extra);
// validation
info.point.validate();
@ -88,7 +72,36 @@ var PublicKey = function PublicKey(data, extra) {
};
/**
* Internal function to detect if an object is a PrivateKey
* Internal function to differentiate between arguments passed to the constructor
* @param {*} data
* @param {Object} extra
*/
PublicKey.prototype._classifyArgs = function(data, extra) {
/* jshint maxcomplexity: 10 */
var info = {
compressed: _.isUndefined(extra.compressed) || extra.compressed,
network: _.isUndefined(extra.network) ? undefined : Network.get(extra.network)
};
// detect type of data
if (data instanceof Point) {
info.point = data;
} else if (PublicKey._isJSON(data)) {
info = PublicKey._transformJSON(data);
} else if (typeof(data) === 'string') {
info = PublicKey._transformDER(new Buffer(data, 'hex'));
} else if (PublicKey._isBuffer(data)) {
info = PublicKey._transformDER(data);
} else if (PublicKey._isPrivateKey(data)) {
info = PublicKey._transformPrivateKey(data);
} else {
throw new TypeError('First argument is an unrecognized data format.');
}
return info;
};
/**
* Internal function to detect if an object is a {@link PrivateKey}
*
* @param {*} param - object to test
* @returns {boolean}
@ -147,6 +160,8 @@ PublicKey._transformPrivateKey = function(privkey) {
* @private
*/
PublicKey._transformDER = function(buf, strict) {
/* jshint maxstatements: 30 */
/* jshint maxcomplexity: 12 */
$.checkArgument(PublicKey._isBuffer(buf), new TypeError('Must be a hex buffer of DER encoded public key'));
var info = {};
@ -165,7 +180,7 @@ PublicKey._transformDER = function(buf, strict) {
}
x = BN(xbuf);
y = BN(ybuf);
info.point = Point(x, y);
info.point = new Point(x, y);
info.compressed = false;
} else if (buf[0] === 0x03) {
xbuf = buf.slice(1);
@ -314,6 +329,7 @@ PublicKey.fromX = function(odd, x) {
PublicKey.getValidationError = function(data) {
var error;
try {
/* jshint nonew: false */
new PublicKey(data);
} catch (e) {
error = e;

View File

@ -1,5 +1,6 @@
'use strict';
var expect = require('chai').expect;
var should = require('chai').should();
var bitcore = require('..');
var networks = bitcore.Networks;
@ -21,4 +22,13 @@ describe('Networks', function() {
});
});
it('tests only for the specified key', function() {
expect(networks.get(0x6f, 'pubkeyhash')).to.equal(networks.testnet);
expect(networks.get(0x6f, 'privatekey')).to.equal(undefined);
});
it('converts to string using the "name" property', function() {
networks.livenet.toString().should.equal('livenet');
});
});

View File

@ -17,10 +17,10 @@ var invalidbase58 = require('./data/bitcoind/base58_keys_invalid.json');
describe('PrivateKey', function() {
var hex = '96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a';
var buf = new Buffer(hex, 'hex');
var enctestnet = 'cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG';
var enctu = '92jJzK4tbURm1C7udQXxeCBvXHoHJstDXRxAMouPG1k1XUaXdsu';
var enclivenet = 'L2Gkw3kKJ6N24QcDuH4XDqt9cTqsKTVNDGz1CRZhk9cq4auDUbJy';
var encmu = '5JxgQaFM1FMd38cd14e3mbdxsdSa9iM2BV6DHBYsvGzxkTNQ7Un';
var wifTestnet = 'cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG';
var wifTestnetUncompressed = '92jJzK4tbURm1C7udQXxeCBvXHoHJstDXRxAMouPG1k1XUaXdsu';
var wifLivenet = 'L2Gkw3kKJ6N24QcDuH4XDqt9cTqsKTVNDGz1CRZhk9cq4auDUbJy';
var wifLivenetUncompressed = '5JxgQaFM1FMd38cd14e3mbdxsdSa9iM2BV6DHBYsvGzxkTNQ7Un';
it('should create a new random private key', function() {
var a = new PrivateKey();
@ -66,75 +66,82 @@ describe('PrivateKey', function() {
});
});
it('should not be able to instantiate private key greater than N', function() {
expect(function() {
var n = Point.getN();
var a = new PrivateKey(n);
}).to.throw('Number must be less than N');
});
describe('instantiation', function() {
it('should not be able to instantiate private key greater than N', function() {
expect(function() {
return new PrivateKey(Point.getN());
}).to.throw('Number must be less than N');
});
it('should not be able to instantiate private key because of network mismatch', function() {
expect(function() {
var a = new PrivateKey('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m', 'testnet');
}).to.throw('Private key network mismatch');
});
it('should not be able to instantiate private key because of network mismatch', function() {
expect(function() {
return new PrivateKey('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m', 'testnet');
}).to.throw('Private key network mismatch');
});
it('should not be able to instantiate private key WIF is too long', function() {
expect(function() {
var buf = base58check.decode('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
var buf2 = Buffer.concat([buf, new Buffer(0x01)]);
var a = new PrivateKey(buf2);
}).to.throw('Length of buffer must be 33 (uncompressed) or 34 (compressed');
});
it('should not be able to instantiate private key WIF is too long', function() {
expect(function() {
var buf = base58check.decode('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
var buf2 = Buffer.concat([buf, new Buffer(0x01)]);
return new PrivateKey(buf2);
}).to.throw('Length of buffer must be 33 (uncompressed) or 34 (compressed');
});
it('should not be able to instantiate private key WIF because of unknown network byte', function() {
expect(function() {
var buf = base58check.decode('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
var buf2 = Buffer.concat([new Buffer('ff', 'hex'), buf.slice(1, 33)]);
var a = new PrivateKey(buf2);
}).to.throw('Invalid network');
});
it('should not be able to instantiate private key WIF because of unknown network byte', function() {
expect(function() {
var buf = base58check.decode('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
var buf2 = Buffer.concat([new Buffer('ff', 'hex'), buf.slice(1, 33)]);
return new PrivateKey(buf2);
}).to.throw('Invalid network');
});
it('can be instantiated from a hex string', function() {
var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
var pubhex = '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc';
var privkey = new PrivateKey(privhex);
privkey.publicKey.toString().should.equal(pubhex);
});
it('can be instantiated from a hex string', function() {
var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
var pubhex = '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc';
var privkey = new PrivateKey(privhex);
privkey.publicKey.toString().should.equal(pubhex);
});
it('should not be able to instantiate because of unrecognized data', function() {
expect(function() {
var a = new PrivateKey(new Error());
}).to.throw('First argument is an unrecognized data type.');
});
it('should not be able to instantiate because of unrecognized data', function() {
expect(function() {
return new PrivateKey(new Error());
}).to.throw('First argument is an unrecognized data type.');
});
it('should not be able to instantiate with unknown network', function() {
expect(function() {
var a = new PrivateKey(BN(2), 'unknown');
}).to.throw('Must specify the network ("livenet" or "testnet")');
});
it('should not be able to instantiate with unknown network', function() {
expect(function() {
return new PrivateKey(BN(2), 'unknown');
}).to.throw('Must specify the network ("livenet" or "testnet")');
});
it('should not create a zero private key', function() {
expect(function() {
var bn = BN(0);
var privkey = new PrivateKey(bn);
}).to.throw(TypeError);
});
it('should not create a zero private key', function() {
expect(function() {
var bn = BN(0);
return new PrivateKey(bn);
}).to.throw(TypeError);
});
it('should create a livenet private key', function() {
var privkey = new PrivateKey(BN.fromBuffer(buf), 'livenet');
privkey.toString().should.equal(enclivenet);
});
it('should create a livenet private key', function() {
var privkey = new PrivateKey(BN.fromBuffer(buf), 'livenet');
privkey.toString().should.equal(wifLivenet);
});
it('should create a default network private key', function() {
var a = new PrivateKey(BN.fromBuffer(buf));
a.network.should.equal(Networks.livenet);
// change the default
Networks.defaultNetwork = Networks.testnet;
var b = new PrivateKey(BN.fromBuffer(buf));
b.network.should.equal(Networks.testnet);
// restore the default
Networks.defaultNetwork = Networks.livenet;
});
it('returns the same instance if a PrivateKey is provided (immutable)', function() {
var privkey = new PrivateKey();
new PrivateKey(privkey).should.equal(privkey);
});
it('should create a default network private key', function() {
var a = new PrivateKey(BN.fromBuffer(buf));
a.network.should.equal(Networks.livenet);
// change the default
Networks.defaultNetwork = Networks.testnet;
var b = new PrivateKey(BN.fromBuffer(buf));
b.network.should.equal(Networks.testnet);
// restore the default
Networks.defaultNetwork = Networks.livenet;
});
describe('#json', function() {
@ -148,13 +155,37 @@ describe('PrivateKey', function() {
PrivateKey.fromJSON(json).toJSON().should.deep.equal(json);
});
it('an object with private key info can be also used as argument for "fromJSON"', function() {
expect(PrivateKey._isJSON({bn: true, network: true})).to.equal(true);
});
it('fails on invalid argument', function() {
expect(function() {
return PrivateKey.fromJSON('¹');
}).to.throw();
});
it('also accepts an object as argument', function() {
expect(function() {
return PrivateKey.fromJSON(new PrivateKey().toObject());
}).to.not.throw();
});
});
it('coverage: public key cache', function() {
expect(function() {
var privateKey = new PrivateKey();
/* jshint unused: false */
var publicKey = privateKey.publicKey;
return privateKey.publicKey;
}).to.not.throw();
});
describe('#toString', function() {
it('should output this address correctly', function() {
var privkey = PrivateKey.fromWIF(encmu);
privkey.toString().should.equal(encmu);
var privkey = PrivateKey.fromWIF(wifLivenetUncompressed);
privkey.toString().should.equal(wifLivenetUncompressed);
});
});
@ -177,14 +208,22 @@ describe('PrivateKey', function() {
describe('#inspect', function() {
it('should output known livenet address for console', function() {
var privkey = PrivateKey.fromWIF('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
privkey.inspect().should.equal('<PrivateKey: L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m, network: livenet>');
privkey.inspect().should.equal(
'<PrivateKey: L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m, network: livenet>'
);
});
it('should output known testnet address for console', function() {
var privkey = PrivateKey.fromWIF('cR4qogdN9UxLZJXCNFNwDRRZNeLRWuds9TTSuLNweFVjiaE4gPaq');
privkey.inspect().should.equal('<PrivateKey: cR4qogdN9UxLZJXCNFNwDRRZNeLRWuds9TTSuLNweFVjiaE4gPaq, network: testnet>');
privkey.inspect().should.equal(
'<PrivateKey: cR4qogdN9UxLZJXCNFNwDRRZNeLRWuds9TTSuLNweFVjiaE4gPaq, network: testnet>'
);
});
it('outputs "uncompressed" for uncompressed imported WIFs', function() {
var privkey = PrivateKey.fromWIF(wifLivenetUncompressed);
privkey.inspect().should.equal('<PrivateKey: ' + wifLivenetUncompressed + ', network: livenet, uncompressed>');
});
});
describe('#getValidationError', function(){
@ -210,7 +249,7 @@ describe('PrivateKey', function() {
describe('#toBuffer', function() {
it('should output known buffer', function() {
var privkey = new PrivateKey(BN.fromBuffer(buf), 'livenet');
var b = privkey.toBuffer().toString('hex').should.equal(buf.toString('hex'));
privkey.toBuffer().toString('hex').should.equal(buf.toString('hex'));
});
});
@ -237,8 +276,8 @@ describe('PrivateKey', function() {
describe('#fromWIF', function() {
it('should parse this compressed testnet address correctly', function() {
var privkey = PrivateKey.fromWIF(enclivenet);
privkey.toWIF().should.equal(enclivenet);
var privkey = PrivateKey.fromWIF(wifLivenet);
privkey.toWIF().should.equal(wifLivenet);
});
});
@ -246,8 +285,8 @@ describe('PrivateKey', function() {
describe('#toWIF', function() {
it('should parse this compressed testnet address correctly', function() {
var privkey = PrivateKey.fromWIF(enctestnet);
privkey.toWIF().should.equal(enctestnet);
var privkey = PrivateKey.fromWIF(wifTestnet);
privkey.toWIF().should.equal(wifTestnet);
});
});
@ -255,8 +294,8 @@ describe('PrivateKey', function() {
describe('#fromString', function() {
it('should parse this uncompressed testnet address correctly', function() {
var privkey = PrivateKey.fromString(enctu);
privkey.toWIF().should.equal(enctu);
var privkey = PrivateKey.fromString(wifTestnetUncompressed);
privkey.toWIF().should.equal(wifTestnetUncompressed);
});
});
@ -264,13 +303,13 @@ describe('PrivateKey', function() {
describe('#toString', function() {
it('should parse this uncompressed livenet address correctly', function() {
var privkey = PrivateKey.fromString(encmu);
privkey.toString().should.equal(encmu);
var privkey = PrivateKey.fromString(wifLivenetUncompressed);
privkey.toString().should.equal(wifLivenetUncompressed);
});
});
describe("#toPublicKey", function() {
describe('#toPublicKey', function() {
it('should convert this known PrivateKey to known PublicKey', function() {
var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
@ -304,12 +343,12 @@ describe('PrivateKey', function() {
});
it('creates an address as expected from WIF, livenet', function() {
var privkey = new PrivateKey('5J2NYGstJg7aJQEqNwYp4enG5BSfFdKXVTtBLvHicnRGD5kjxi6')
var privkey = new PrivateKey('5J2NYGstJg7aJQEqNwYp4enG5BSfFdKXVTtBLvHicnRGD5kjxi6');
privkey.publicKey.toAddress().toString().should.equal('135bwugFCmhmNU3SeCsJeTqvo5ViymgwZ9');
});
it('creates an address as expected from WIF, testnet', function() {
var privkey = new PrivateKey('92VYMmwFLXRwXn5688edGxYYgMFsc3fUXYhGp17WocQhU6zG1kd')
var privkey = new PrivateKey('92VYMmwFLXRwXn5688edGxYYgMFsc3fUXYhGp17WocQhU6zG1kd');
privkey.publicKey.toAddress().toString().should.equal('moiAvLUw16qgrwhFGo1eDnXHC2wPMYiv7Y');
});

View File

@ -1,83 +1,94 @@
'use strict';
var should = require('chai').should();
var expect = require('chai').expect;
var bitcore = require('..');
var Point = bitcore.crypto.Point;
var BN = bitcore.crypto.BN;
var PublicKey = bitcore.PublicKey;
var PrivateKey = bitcore.PrivateKey;
// DER uncompressed format
/* jshint maxlen: 200 */
describe('PublicKey', function() {
/* jshint maxstatements: 30 */
var invalidPoint = '0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000';
it('should error because of missing data', function() {
(function() {
var pk = new PublicKey();
}).should.throw('First argument is required, please include public key data.');
describe('validating errors on creation', function() {
it('errors if data is missing', function() {
(function() {
return new PublicKey();
}).should.throw('First argument is required, please include public key data.');
});
it('errors if an invalid point is provided', function() {
(function() {
return new PublicKey(invalidPoint);
}).should.throw('Invalid x,y value for curve, cannot equal 0.');
});
it('errors if a point not on the secp256k1 curve is provided', function() {
(function() {
return new PublicKey(new Point(1000, 1000));
}).should.throw('Invalid y value for curve.');
});
it('errors if the argument is of an unrecognized type', function() {
(function() {
return new PublicKey(new Error());
}).should.throw('First argument is an unrecognized data format.');
});
});
it('should error because of an invalid point', function() {
(function() {
var pk = new PublicKey(invalidPoint);
}).should.throw('Invalid x,y value for curve, cannot equal 0.');
describe('instantiation', function() {
it('from a private key', function() {
var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
var pubhex = '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc';
var privkey = new PrivateKey(BN(new Buffer(privhex, 'hex')));
var pk = new PublicKey(privkey);
pk.toString().should.equal(pubhex);
});
it('from a compressed public key', function() {
var publicKeyHex = '031ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a';
var publicKey = new PublicKey(publicKeyHex);
publicKey.toString().should.equal(publicKeyHex);
});
it('from another publicKey', function() {
var publicKeyHex = '031ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a';
var publicKey = new PublicKey(publicKeyHex);
var publicKey2 = new PublicKey(publicKey);
publicKey.should.equal(publicKey2);
});
it('from a hex encoded DER string', function() {
var pk = new PublicKey('041ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341');
should.exist(pk.point);
pk.point.getX().toString(16).should.equal('1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a');
});
it('from a hex encoded DER buffer', function() {
var pk = new PublicKey(new Buffer('041ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341', 'hex'));
should.exist(pk.point);
pk.point.getX().toString(16).should.equal('1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a');
});
it('from a point', function() {
var p = new Point('86a80a5a2bfc48dddde2b0bd88bd56b0b6ddc4e6811445b175b90268924d7d48',
'3b402dfc89712cfe50963e670a0598e6b152b3cd94735001cdac6794975d3afd');
var a = new PublicKey(p);
should.exist(a.point);
a.point.toString().should.equal(p.toString());
var c = new PublicKey(p);
should.exist(c.point);
c.point.toString().should.equal(p.toString());
});
});
it('should error because of an invalid public key point, not on the secp256k1 curve', function() {
(function() {
var pk = new PublicKey(Point(1000, 1000));
}).should.throw('Invalid y value for curve.');
});
it('should error because of an unrecognized data type', function() {
(function() {
var pk = new PublicKey(new Error());
}).should.throw('First argument is an unrecognized data format.');
});
it('should instantiate from a private key', function() {
var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
var pubhex = '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc';
var privkey = new PrivateKey(BN(new Buffer(privhex, 'hex')));
var pk = new PublicKey(privkey);
pk.toString().should.equal(pubhex);
});
it('should instantiate from a compressed public key', function() {
var publicKeyHex = '031ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a';
var publicKey = new PublicKey(publicKeyHex);
publicKey.toString().should.equal(publicKeyHex);
});
it('should instantiate from another publicKey', function() {
var publicKeyHex = '031ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a';
var publicKey = new PublicKey(publicKeyHex);
var publicKey2 = new PublicKey(publicKey);
publicKey.should.equal(publicKey2);
});
it('should instantiate from a hex encoded DER string', function() {
var pk = new PublicKey('041ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341');
should.exist(pk.point);
pk.point.getX().toString(16).should.equal('1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a');
});
it('should instantiate from a hex encoded DER buffer', function() {
var pk = new PublicKey(new Buffer('041ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341', 'hex'));
should.exist(pk.point);
pk.point.getX().toString(16).should.equal('1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a');
});
it('should create a public key with a point', function() {
var p = Point('86a80a5a2bfc48dddde2b0bd88bd56b0b6ddc4e6811445b175b90268924d7d48',
'3b402dfc89712cfe50963e670a0598e6b152b3cd94735001cdac6794975d3afd');
var a = new PublicKey(p);
should.exist(a.point);
a.point.toString().should.equal(p.toString());
var c = PublicKey(p);
should.exist(c.point);
c.point.toString().should.equal(p.toString());
});
describe('#getValidationError', function(){
@ -107,8 +118,8 @@ describe('PublicKey', function() {
describe('#fromPoint', function() {
it('should instantiate from a point', function() {
var p = Point('86a80a5a2bfc48dddde2b0bd88bd56b0b6ddc4e6811445b175b90268924d7d48',
'3b402dfc89712cfe50963e670a0598e6b152b3cd94735001cdac6794975d3afd');
var p = new Point('86a80a5a2bfc48dddde2b0bd88bd56b0b6ddc4e6811445b175b90268924d7d48',
'3b402dfc89712cfe50963e670a0598e6b152b3cd94735001cdac6794975d3afd');
var b = PublicKey.fromPoint(p);
should.exist(b.point);
b.point.toString().should.equal(p.toString());
@ -132,6 +143,18 @@ describe('PublicKey', function() {
PublicKey.fromJSON(json).toJSON().should.deep.equal(json);
});
it('fails if "y" is not provided', function() {
expect(function() {
return PublicKey.fromJSON('{"x": "1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a"}');
}).to.throw();
});
it('fails if invalid JSON is provided', function() {
expect(function() {
return PublicKey._transformJSON('¹');
}).to.throw();
});
});
describe('#fromPrivateKey', function() {
@ -227,7 +250,7 @@ describe('PublicKey', function() {
it('should error because odd was not included as a param', function() {
var x = BN.fromBuffer(new Buffer('1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a', 'hex'));
(function() {
var pk = PublicKey.fromX(null, x);
return PublicKey.fromX(null, x);
}).should.throw('Must specify whether y is odd or not (true or false)');
});
@ -312,26 +335,28 @@ describe('PublicKey', function() {
it('should not have an error if pubkey is valid', function() {
var hex = '031ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a';
var pk = PublicKey.fromString(hex);
expect(function() {
return PublicKey.fromString(hex);
}).to.not.throw();
});
it('should throw an error if pubkey is invalid', function() {
var hex = '041ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a0000000000000000000000000000000000000000000000000000000000000000';
(function() {
var pk = PublicKey.fromString(hex);
return PublicKey.fromString(hex);
}).should.throw('Invalid x,y value for curve, cannot equal 0.');
});
it('should throw an error if pubkey is invalid', function() {
var hex = '041ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a00000000000000000000000000000000000000000000000000000000000000FF';
(function() {
var pk = PublicKey.fromString(hex);
return PublicKey.fromString(hex);
}).should.throw('Invalid y value for curve.');
});
it('should throw an error if pubkey is infinity', function() {
(function() {
var pk = new PublicKey(Point.getG().mul(Point.getN()));
return new PublicKey(Point.getG().mul(Point.getN()));
}).should.throw('Point cannot be equal to Infinity');
});