From d4d3d4ab4a0b876b5dd6d2e25937b26823927835 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 11 Dec 2014 11:25:02 -0500 Subject: [PATCH 1/3] PrivateKey: Add documentation and refactor to use network object as a parameter. --- docs/PrivateKey.md | 57 +++++++++++++++++++++++++++++++++++++ lib/privatekey.js | 70 +++++++++++++++++----------------------------- test/privatekey.js | 10 +++---- 3 files changed, 88 insertions(+), 49 deletions(-) create mode 100644 docs/PrivateKey.md diff --git a/docs/PrivateKey.md b/docs/PrivateKey.md new file mode 100644 index 000000000..691177190 --- /dev/null +++ b/docs/PrivateKey.md @@ -0,0 +1,57 @@ +# Private Key + +Represents a bitcoin private key and is needed to be able to spend bitcoin and sign transactions. See the official [Bitcoin Wiki](https://en.bitcoin.it/wiki/Private_key) for more information about private keys. A PrivateKey in Bitcore is an immutable object that has methods to import and export into a variety of formats including [Wallet Import Format](https://en.bitcoin.it/wiki/Wallet_import_format). + +## Instantiate a Private Key + +Here is how to create a new private key. It will generate a new random number using `window.crypto` or the Node.js 'crypto' library. + +```javascript + +var PrivateKey = require('bitcore/lib/privatekey'); +var privateKey = new PrivateKey(); + +``` + +To export and import a private key, you can do the following: + +```javascript + +// encode into wallet export format +var exported = privateKey.toWIF(); + +// instantiate from the exported (and saved) private key +var imported = PrivateKey.fromWIF(exported); + +``` + +Note: The WIF (Wallet Import Format) includes information about the network and if the associated public key is compressed or uncompressed (thus the same bitcoin address will be generated by using this format). + +To generate an Address or PublicKey from a PrivateKey: + +```javascript + +var address = privateKey.toAddress(); +var publicKey = privateKey.toPublicKey(); + +``` + +## Validating a Private Key + +The code to do these validations looks like this: + +```javascript + +// validate an address +if (PrivateKey.isValid(input){ + ... +} + +// get the specific validation error that can occurred +var error = PrivateKey.getValidationError(input, Networks.livenet); + if (error) { + // handle the error + } +} + +``` diff --git a/lib/privatekey.js b/lib/privatekey.js index 0a75d1c9a..0ed943857 100644 --- a/lib/privatekey.js +++ b/lib/privatekey.js @@ -1,16 +1,15 @@ 'use strict'; -var BN = require('./crypto/bn'); -var Point = require('./crypto/point'); -var Random = require('./crypto/random'); -var networks = require('./networks'); -var base58check = require('./encoding/base58check'); var Address = require('./address'); -var PublicKey = require('./publickey'); +var base58check = require('./encoding/base58check'); +var BN = require('./crypto/bn'); var jsUtil = require('./util/js'); +var Networks = require('./networks'); +var Point = require('./crypto/point'); +var PublicKey = require('./publickey'); +var Random = require('./crypto/random'); /** - * * Instantiate a PrivateKey from a BN, Buffer and WIF. * * @example @@ -21,12 +20,12 @@ var jsUtil = require('./util/js'); * // get the associated address * var address = key.toAddress(); * - * // encode into wallet export format - * var exported = key.toWIF(); - * + * // encode into wallet export format + * var exported = key.toWIF(); + * * // instantiate from the exported (and saved) private key * var imported = PrivateKey.fromWIF(exported); - * + * * @param {String} data - The encoded data in various formats * @param {String} [network] - Either "livenet" or "testnet" * @param {Boolean} [compressed] - If the key is in compressed format @@ -41,7 +40,7 @@ var PrivateKey = function PrivateKey(data, network, compressed) { var info = { compressed: typeof(compressed) !== 'undefined' ? compressed : true, - network: network || networks.defaultNetwork.name + network: network ? Networks.get(network) : Networks.defaultNetwork }; // detect type of data @@ -65,7 +64,7 @@ var PrivateKey = function PrivateKey(data, network, compressed) { if (!info.bn.lt(Point.getN())) { throw new TypeError('Number must be less than N'); } - if (typeof(networks[info.network]) === 'undefined') { + if (typeof(info.network) === 'undefined') { throw new TypeError('Must specify the network ("livenet" or "testnet")'); } if (typeof(info.compressed) !== 'boolean') { @@ -102,10 +101,9 @@ var PrivateKey = function PrivateKey(data, network, compressed) { }; /** - * * Internal function to get a random BN * - * @returns {Object} An object with keys: bn, network and compressed + * @returns {BN} An object with keys: bn, network and compressed * @private */ PrivateKey._getRandomBN = function(){ @@ -120,10 +118,9 @@ PrivateKey._getRandomBN = function(){ }; /** + * Internal function to transform a WIF Buffer into a private key * - * Internal function to transform a WIF Buffer into a private key - * - * @param {Buffer} buf - An WIF string + * @param {Buffer} buf - An WIF string * @param {String} [network] - Either "livenet" or "testnet" * @param {String} [compressed] - If the private key is compressed * @returns {Object} An object with keys: bn, network and compressed @@ -141,22 +138,22 @@ PrivateKey._transformBuffer = function(buf, network, compressed) { throw new Error('Length of buffer must be 33 (uncompressed) or 34 (compressed)'); } - if (buf[0] === networks.livenet.privatekey) { - info.network = networks.livenet.name; - } else if (buf[0] === networks.testnet.privatekey) { - info.network = networks.testnet.name; + if (buf[0] === Networks.livenet.privatekey) { + info.network = Networks.livenet; + } else if (buf[0] === Networks.testnet.privatekey) { + info.network = Networks.testnet; } else { throw new Error('Invalid network'); } - if (network && networks.get(info.network) !== networks.get(network)) { + if (network && info.network !== Networks.get(network)) { throw TypeError('Private key network mismatch'); } if (typeof(compressed) !== 'undefined' && info.compressed !== compressed){ throw TypeError('Private key compression mismatch'); } - + info.bn = BN.fromBuffer(buf.slice(1, 32 + 1)); return info; @@ -164,10 +161,9 @@ PrivateKey._transformBuffer = function(buf, network, compressed) { }; /** + * Internal function to transform a WIF string into a private key * - * Internal function to transform a WIF string into a private key - * - * @param {String} buf - An WIF string + * @param {String} buf - An WIF string * @returns {Object} An object with keys: bn, network and compressed * @private */ @@ -176,7 +172,6 @@ PrivateKey._transformWIF = function(str, network, compressed) { }; /** - * * Instantiate a PrivateKey from a WIF string * * @param {String} str - The WIF encoded private key string @@ -188,7 +183,6 @@ PrivateKey.fromWIF = function(str) { }; /** - * * Instantiate a PrivateKey from a WIF JSON string * * @param {String} str - The WIF encoded private key string @@ -200,7 +194,6 @@ PrivateKey.fromJSON = function(json) { }; /** - * * Instantiate a PrivateKey from random bytes * * @param {String} [network] - Either "livenet" or "testnet" @@ -213,7 +206,6 @@ PrivateKey.fromRandom = function(network, compressed) { }; /** - * * Instantiate a PrivateKey from a WIF string * * @param {String} str - The WIF encoded private key string @@ -225,7 +217,6 @@ PrivateKey.fromString = function(str) { }; /** - * * Check if there would be any errors when initializing a PrivateKey * * @param {String} data - The encoded data in various formats @@ -245,7 +236,6 @@ PrivateKey.getValidationError = function(data, network, compressed) { }; /** - * * Check if the parameters are valid * * @param {String} data - The encoded data in various formats @@ -258,7 +248,6 @@ PrivateKey.isValid = function(data, network, compressed){ }; /** - * * Will output the PrivateKey to a WIF string * * @returns {String} A WIP representation of the private key @@ -269,11 +258,11 @@ PrivateKey.prototype.toWIF = function() { var buf; if (compressed) { - buf = Buffer.concat([new Buffer([networks[network].privatekey]), - this.bn.toBuffer({size: 32}), + buf = Buffer.concat([new Buffer([network.privatekey]), + this.bn.toBuffer({size: 32}), new Buffer([0x01])]); } else { - buf = Buffer.concat([new Buffer([networks[network].privatekey]), + buf = Buffer.concat([new Buffer([network.privatekey]), this.bn.toBuffer({size: 32})]); } @@ -281,7 +270,6 @@ PrivateKey.prototype.toWIF = function() { }; /** - * * Will return the private key as a BN instance * * @returns {BN} A BN instance of the private key @@ -291,7 +279,6 @@ PrivateKey.prototype.toBigNumber = function(){ }; /** - * * Will return the private key as a BN buffer * * @returns {Buffer} A buffer of the private key @@ -301,7 +288,6 @@ PrivateKey.prototype.toBuffer = function(){ }; /** - * * Will return the corresponding public key * * @returns {PublicKey} A public key generated from the private key @@ -311,7 +297,6 @@ PrivateKey.prototype.toPublicKey = function(){ }; /** - * * Will return an address for the private key * * @returns {Address} An address generated from the private key @@ -322,7 +307,6 @@ PrivateKey.prototype.toAddress = function() { }; /** - * * Will output the PrivateKey to a WIF string * * @returns {String} A WIF representation of the private key @@ -332,7 +316,6 @@ PrivateKey.prototype.toJSON = function() { }; /** - * * Will output the PrivateKey to a WIF string * * @returns {String} A WIF representation of the private key @@ -342,7 +325,6 @@ PrivateKey.prototype.toString = function() { }; /** - * * Will return a string formatted for the console * * @returns {String} Private key diff --git a/test/privatekey.js b/test/privatekey.js index 77c38f074..e2cf3a442 100644 --- a/test/privatekey.js +++ b/test/privatekey.js @@ -5,7 +5,7 @@ var bitcore = require('..'); var BN = bitcore.crypto.BN; var Point = bitcore.crypto.Point; var PrivateKey = bitcore.PrivateKey; -var networks = bitcore.Networks; +var Networks = bitcore.Networks; var base58check = bitcore.encoding.Base58Check; describe('PrivateKey', function() { @@ -110,13 +110,13 @@ describe('PrivateKey', function() { it('should create a default network private key', function() { var a = new PrivateKey(BN.fromBuffer(buf)); - a.network.should.equal('livenet'); + a.network.should.equal(Networks.livenet); // change the default - networks.defaultNetwork = networks.testnet; + Networks.defaultNetwork = Networks.testnet; var b = new PrivateKey(BN.fromBuffer(buf)); - b.network.should.equal('testnet'); + b.network.should.equal(Networks.testnet); // restore the default - networks.defaultNetwork = networks.livenet; + Networks.defaultNetwork = Networks.livenet; }); it('should create an uncompressed testnet private key', function() { From 5b0bedee6c1c710dcbd398470da12bf56b1aa6aa Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 11 Dec 2014 13:29:21 -0500 Subject: [PATCH 2/3] PrivateKey: Fixed documentation --- docs/PrivateKey.md | 7 +++---- lib/privatekey.js | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/PrivateKey.md b/docs/PrivateKey.md index 691177190..bbf51b390 100644 --- a/docs/PrivateKey.md +++ b/docs/PrivateKey.md @@ -21,7 +21,7 @@ To export and import a private key, you can do the following: var exported = privateKey.toWIF(); // instantiate from the exported (and saved) private key -var imported = PrivateKey.fromWIF(exported); +var imported = PrivateKey.fromWIF('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m'); ``` @@ -49,9 +49,8 @@ if (PrivateKey.isValid(input){ // get the specific validation error that can occurred var error = PrivateKey.getValidationError(input, Networks.livenet); - if (error) { - // handle the error - } +if (error) { + // handle the error } ``` diff --git a/lib/privatekey.js b/lib/privatekey.js index 0ed943857..e2a95a203 100644 --- a/lib/privatekey.js +++ b/lib/privatekey.js @@ -103,7 +103,7 @@ var PrivateKey = function PrivateKey(data, network, compressed) { /** * Internal function to get a random BN * - * @returns {BN} An object with keys: bn, network and compressed + * @returns {BN} A new randomly generated BN * @private */ PrivateKey._getRandomBN = function(){ From 01069be8d89d77c0789b68160016e6d00c2ad730 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 11 Dec 2014 13:34:12 -0500 Subject: [PATCH 3/3] PrivateKey: Fix typo --- docs/PrivateKey.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/PrivateKey.md b/docs/PrivateKey.md index bbf51b390..4b6cf7be1 100644 --- a/docs/PrivateKey.md +++ b/docs/PrivateKey.md @@ -43,7 +43,7 @@ The code to do these validations looks like this: ```javascript // validate an address -if (PrivateKey.isValid(input){ +if (PrivateKey.isValid(input)){ ... }