Merge pull request #713 from braydonf/ref/private-key-network

PrivateKey: Add docs and refactor to use network object
This commit is contained in:
Manuel Aráoz 2014-12-11 17:20:24 -03:00
commit d1b4c25c6f
3 changed files with 87 additions and 49 deletions

56
docs/PrivateKey.md Normal file
View File

@ -0,0 +1,56 @@
# 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('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
```
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
}
```

View File

@ -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} A new randomly generated BN
* @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

View File

@ -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() {