ethereumjs-wallet
Advanced tools
Comparing version 0.4.0 to 0.5.0
70
index.js
@@ -5,2 +5,4 @@ var ethUtil = require('ethereumjs-util') | ||
var uuid = require('uuid') | ||
var secp256k1 = require('secp256k1') | ||
var bs58check = require('bs58check') | ||
@@ -17,6 +19,35 @@ function assert (val, msg) { | ||
var Wallet = function (priv) { | ||
this.privKey = priv | ||
var Wallet = function (priv, pub) { | ||
if (priv && pub) { | ||
throw new Error('Cannot supply both a private and a public key to the constructor') | ||
} | ||
if (priv && !ethUtil.isValidPrivate(priv)) { | ||
throw new Error('Private key does not satisfy the curve requirements (ie. it is invalid)') | ||
} | ||
if (pub && pub.length !== 64) { | ||
throw new Error('Invalid public key') | ||
} | ||
this._privKey = priv | ||
this._pubKey = pub | ||
} | ||
Object.defineProperty(Wallet.prototype, 'privKey', { | ||
get: function () { | ||
assert(this._privKey, 'This is a public key only wallet') | ||
return this._privKey | ||
} | ||
}) | ||
Object.defineProperty(Wallet.prototype, 'pubKey', { | ||
get: function () { | ||
if (!this._pubKey) { | ||
this._pubKey = ethUtil.privateToPublic(this.privKey) | ||
} | ||
return this._pubKey | ||
} | ||
}) | ||
Wallet.generate = function (icapDirect) { | ||
@@ -40,19 +71,19 @@ if (icapDirect) { | ||
Wallet.prototype.getPrivateKeyString = function () { | ||
return '0x' + this.getPrivateKey().toString('hex') | ||
return ethUtil.bufferToHex(this.getPrivateKey()) | ||
} | ||
Wallet.prototype.getPublicKey = function () { | ||
return ethUtil.privateToPublic(this.privKey) | ||
return this.pubKey | ||
} | ||
Wallet.prototype.getPublicKeyString = function () { | ||
return '0x' + this.getPublicKey().toString('hex') | ||
return ethUtil.bufferToHex(this.getPublicKey()) | ||
} | ||
Wallet.prototype.getAddress = function () { | ||
return ethUtil.privateToAddress(this.privKey) | ||
return ethUtil.publicToAddress(this.pubKey) | ||
} | ||
Wallet.prototype.getAddressString = function () { | ||
return '0x' + this.getAddress().toString('hex') | ||
return ethUtil.bufferToHex(this.getAddress()) | ||
} | ||
@@ -66,2 +97,4 @@ | ||
Wallet.prototype.toV3 = function (password, opts) { | ||
assert(this._privKey, 'This is a public key only wallet') | ||
opts = opts || {} | ||
@@ -144,2 +177,18 @@ var salt = opts.salt || crypto.randomBytes(32) | ||
Wallet.fromPublicKey = function (pub, nonStrict) { | ||
// FIXME: duplicate from ethUtil.publicToAddress(), maybe it could be factored out? | ||
if ((pub.length !== 64) && nonStrict) { | ||
pub = secp256k1.publicKeyConvert(pub, false).slice(1) | ||
} | ||
assert(pub.length === 64, 'Invalid public key') | ||
return new Wallet(null, pub) | ||
} | ||
Wallet.fromExtendedPublicKey = function (pub) { | ||
assert(pub.slice(0, 4) === 'xpub', 'Not an extended public key') | ||
pub = bs58check.decode(pub).slice(45) | ||
// Convert to an Ethereum public key | ||
return Wallet.fromPublicKey(pub, true) | ||
} | ||
Wallet.fromPrivateKey = function (priv) { | ||
@@ -149,2 +198,9 @@ return new Wallet(priv) | ||
Wallet.fromExtendedPrivateKey = function (priv) { | ||
assert(priv.slice(0, 4) === 'xprv', 'Not an extended private key') | ||
var tmp = bs58check.decode(priv) | ||
assert(tmp[45] === 0, 'Invalid extended private key') | ||
return Wallet.fromPrivateKey(tmp.slice(46)) | ||
} | ||
// https://github.com/ethereum/go-ethereum/wiki/Passphrase-protected-key-store-spec | ||
@@ -151,0 +207,0 @@ Wallet.fromV1 = function (input, password) { |
{ | ||
"name": "ethereumjs-wallet", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "Utilities for handling Ethereum keys", | ||
@@ -9,3 +9,3 @@ "main": "index.js", | ||
"prepublish": "npm run lint && npm run test", | ||
"test": "mocha ./test/index.js" | ||
"test": "mocha ./test/index.js && mocha ./test/hdkey.js" | ||
}, | ||
@@ -29,4 +29,7 @@ "repository": { | ||
"aes-js": "^0.2.3", | ||
"ethereumjs-util": "^4.1.0", | ||
"bs58check": "^1.0.8", | ||
"ethereumjs-util": "^4.3.0", | ||
"hdkey": "^0.7.0", | ||
"scrypt.js": "^0.1.0", | ||
"secp256k1": "^3.0.1", | ||
"uuid": "^2.0.1", | ||
@@ -33,0 +36,0 @@ "utf8": "^2.1.1" |
@@ -15,2 +15,3 @@ # ethereumjs-wallet | ||
- support import/export between various wallet formats | ||
- support BIP32 HD keys | ||
@@ -21,3 +22,3 @@ Features not supported: | ||
## API | ||
## Wallet API | ||
@@ -27,3 +28,6 @@ Constructors: | ||
* `generate([icap])` - create an instance based on a new random key (setting `icap` to true will generate an address suitable for the `ICAP Direct mode`) | ||
* `fromPrivateKey(input)` - create an instance based on a raw key | ||
* `fromPrivateKey(input)` - create an instance based on a raw private key | ||
* `fromExtendedPrivateKey(input)` - create an instance based on a BIP32 xprv | ||
* `fromPublicKey(input, [nonStrict])` - create an instance based on a public key (certain methods will not be available) | ||
* `fromExtendedPublicKey(input)` - create an instance based on a BIP32 xpub | ||
* `fromV1(input, password)` - import a wallet (Version 1 of the Ethereum wallet format) | ||
@@ -35,13 +39,4 @@ * `fromV3(input, password, [nonStrict])` - import a wallet (Version 3 of the Ethereum wallet format). Set `nonStrict` true to accept files with mixed-caps. | ||
Third party imports: | ||
Note: `fromPublicKey()` only accepts uncompressed Ethereum-style public keys, unless the `nonStrict` flag is set to true. | ||
* `fromEtherCamp(passphrase)` - import a brain wallet used by Ether.Camp | ||
* `fromEtherWallet(input, password)` - import a wallet generated by EtherWallet | ||
* `fromKryptoKit(seed)` - import a wallet from a KryptoKit seed | ||
* `fromQuorumWallet(passphrase, userid)` - import a brain wallet used by Quorum Wallet | ||
To use these, first import the appropriate submodule: | ||
`var thirdparty = require('ethereumjs-wallet/thirdparty')` | ||
Instance methods: | ||
@@ -58,2 +53,36 @@ | ||
## Thirdparty API | ||
Importing various third party wallets is possible through the `thirdparty` submodule: | ||
`var thirdparty = require('ethereumjs-wallet/thirdparty')` | ||
Constructors: | ||
* `fromEtherCamp(passphrase)` - import a brain wallet used by Ether.Camp | ||
* `fromEtherWallet(input, password)` - import a wallet generated by EtherWallet | ||
* `fromKryptoKit(seed)` - import a wallet from a KryptoKit seed | ||
* `fromQuorumWallet(passphrase, userid)` - import a brain wallet used by Quorum Wallet | ||
## HD Wallet API | ||
To use BIP32 HD wallets, first include the `hdkey` submodule: | ||
`var hdkey = require('ethereumjs-wallet/hdkey')` | ||
Constructors: | ||
* `fromMasterSeed(seed)` - create an instance based on a seed | ||
* `fromExtendedKey(key)` - create an instance based on a BIP32 extended private or public key | ||
For the seed we suggest to use [bip39](https://npmjs.org/packages/bip39) to create one from a BIP39 mnemonic. | ||
Instance methods: | ||
* `privateExtendedKey()` - return a BIP32 extended private key | ||
* `publicExtendedKey()` - return a BIP32 extended private key | ||
* `derivePath(path)` - derive a node based on a path (e.g. m/44'/0'/0/1) | ||
* `deriveChild(index)` - derive a node based on a child index | ||
* `getWallet()` - return a `Wallet` instance as seen above | ||
### Remarks about `toV3` | ||
@@ -87,1 +116,7 @@ | ||
- `cipher`: `aes-128-ctr` | ||
## License | ||
MIT License | ||
Copyright (C) 2016 Alex Beregszaszi |
@@ -12,2 +12,7 @@ var assert = require('assert') | ||
}) | ||
it('should fail', function () { | ||
assert.throws(function () { | ||
Wallet.fromPrivateKey(new Buffer('001122', 'hex')) | ||
}) | ||
}) | ||
}) | ||
@@ -51,2 +56,47 @@ | ||
describe('public key only wallet', function () { | ||
var pubKey = new Buffer('5d4392f450262b276652c1fc037606abac500f3160830ce9df53aa70d95ce7cfb8b06010b2f3691c78c65c21eb4cf3dfdbfc0745d89b664ee10435bb3a0f906c', 'hex') | ||
it('.fromPublicKey() should work', function () { | ||
assert.equal(Wallet.fromPublicKey(pubKey).getPublicKey().toString('hex'), | ||
'5d4392f450262b276652c1fc037606abac500f3160830ce9df53aa70d95ce7cfb8b06010b2f3691c78c65c21eb4cf3dfdbfc0745d89b664ee10435bb3a0f906c') | ||
}) | ||
it('.fromPublicKey() should not accept compressed keys in strict mode', function () { | ||
assert.throws(function () { | ||
Wallet.fromPublicKey(new Buffer('030639797f6cc72aea0f3d309730844a9e67d9f1866e55845c5f7e0ab48402973d', 'hex')) | ||
}) | ||
}) | ||
it('.fromPublicKey() should accept compressed keys in non-strict mode', function () { | ||
var tmp = new Buffer('030639797f6cc72aea0f3d309730844a9e67d9f1866e55845c5f7e0ab48402973d', 'hex') | ||
assert.equal(Wallet.fromPublicKey(tmp, true).getPublicKey().toString('hex'), | ||
'0639797f6cc72aea0f3d309730844a9e67d9f1866e55845c5f7e0ab48402973defa5cb69df462bcc6d73c31e1c663c225650e80ef14a507b203f2a12aea55bc1') | ||
}) | ||
it('.getAddress() should work', function () { | ||
assert.equal(Wallet.fromPublicKey(pubKey).getAddress().toString('hex'), 'b14ab53e38da1c172f877dbc6d65e4a1b0474c3c') | ||
}) | ||
it('.getPrivateKey() should fail', function () { | ||
assert.throws(function () { | ||
Wallet.fromPublicKey(pubKey).getPrivateKey() | ||
}) | ||
}) | ||
it('.toV3() should fail', function () { | ||
assert.throws(function () { | ||
Wallet.fromPublicKey(pubKey).toV3() | ||
}) | ||
}) | ||
}) | ||
describe('.fromExtendedPrivateKey()', function () { | ||
it('should work', function () { | ||
var xprv = 'xprv9s21ZrQH143K4KqQx9Zrf1eN8EaPQVFxM2Ast8mdHn7GKiDWzNEyNdduJhWXToy8MpkGcKjxeFWd8oBSvsz4PCYamxR7TX49pSpp3bmHVAY' | ||
assert.equal(Wallet.fromExtendedPrivateKey(xprv).getAddressString(), '0xb800bf5435f67c7ee7d83c3a863269969a57c57c') | ||
}) | ||
}) | ||
describe('.fromExtendedPublicKey()', function () { | ||
it('should work', function () { | ||
var xpub = 'xpub661MyMwAqRbcGout4B6s29b6gGQsowyoiF6UgXBEr7eFCWYfXuZDvRxP9zEh1Kwq3TLqDQMbkbaRpSnoC28oWvjLeshoQz1StZ9YHM1EpcJ' | ||
assert.equal(Wallet.fromExtendedPublicKey(xpub).getAddressString(), '0xb800bf5435f67c7ee7d83c3a863269969a57c57c') | ||
}) | ||
}) | ||
describe('.generate()', function () { | ||
@@ -53,0 +103,0 @@ it('should generate an account', function () { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
42670
9
748
117
8
+ Addedbs58check@^1.0.8
+ Addedhdkey@^0.7.0
+ Addedsecp256k1@^3.0.1
+ Addedbase-x@1.1.0(transitive)
+ Addedbindings@1.5.0(transitive)
+ Addedbip66@1.1.5(transitive)
+ Addedbs58@2.0.13.1.0(transitive)
+ Addedbs58check@1.3.4(transitive)
+ Addedcoinstring@2.3.1(transitive)
+ Addeddrbg.js@1.0.1(transitive)
+ Addedfile-uri-to-path@1.0.0(transitive)
+ Addedhdkey@0.7.1(transitive)
+ Addedsecp256k1@3.8.0(transitive)
Updatedethereumjs-util@^4.3.0