From ecbf109a716639a36415ab23b8edc2df36ad4070 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 23 Mar 2016 00:39:20 +0000 Subject: [PATCH] Support instantation with public keys --- README.md | 3 ++- index.js | 33 ++++++++++++++++++++++++++++----- test/index.js | 21 +++++++++++++++++++++ 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 64974cc..c107e39 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,8 @@ Features not supported: 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 +* `fromPublicKey(input)` - create an instance based on a public key (certain methods will not be available) * `fromV1(input, password)` - import a wallet (Version 1 of the Ethereum wallet format) * `fromV3(input, password, [nonStrict])` - import a wallet (Version 3 of the Ethereum wallet format). Set `nonStrict` true to accept files with mixed-caps. * `fromEthSale(input, password)` - import an Ethereum Pre Sale wallet diff --git a/index.js b/index.js index 3f94b01..43e7564 100644 --- a/index.js +++ b/index.js @@ -13,13 +13,30 @@ function decipherBuffer (decipher, data) { return Buffer.concat([ decipher.update(data), decipher.final() ]) } -var Wallet = function (priv) { - if (!ethUtil.isValidPrivate(priv)) { +var Wallet = function (priv, pub) { + if (priv && !ethUtil.isValidPrivate(priv)) { throw new Error('Private key does not satisfy the curve requirements (ie. it is invalid)') } - this.privKey = priv + 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) { if (icapDirect) { while (true) { @@ -42,7 +59,7 @@ Wallet.prototype.getPrivateKeyString = function () { } Wallet.prototype.getPublicKey = function () { - return ethUtil.privateToPublic(this.privKey) + return this.pubKey } Wallet.prototype.getPublicKeyString = function () { @@ -50,7 +67,7 @@ Wallet.prototype.getPublicKeyString = function () { } Wallet.prototype.getAddress = function () { - return ethUtil.privateToAddress(this.privKey) + return ethUtil.publicToAddress(this.pubKey) } Wallet.prototype.getAddressString = function () { @@ -63,6 +80,8 @@ Wallet.prototype.getChecksumAddressString = function () { // https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition Wallet.prototype.toV3 = function (password, opts) { + assert(this._privKey, 'This is a public key only wallet') + opts = opts || {} var salt = opts.salt || crypto.randomBytes(32) var iv = opts.iv || crypto.randomBytes(16) @@ -140,6 +159,10 @@ Wallet.prototype.toV3String = function (password, opts) { return JSON.stringify(this.toV3(password, opts)) } +Wallet.fromPublicKey = function (pub) { + return new Wallet(null, pub) +} + Wallet.fromPrivateKey = function (priv) { return new Wallet(priv) } diff --git a/test/index.js b/test/index.js index 312bd57..a2fe899 100644 --- a/test/index.js +++ b/test/index.js @@ -52,6 +52,27 @@ describe('.getChecksumAddressString()', function () { }) }) +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('.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('.generate()', function () { it('should generate an account', function () { assert.equal(Wallet.generate().getPrivateKey().length, 32)