diff --git a/lib/model/wallet.js b/lib/model/wallet.js index 80d982c..792cb07 100644 --- a/lib/model/wallet.js +++ b/lib/model/wallet.js @@ -5,6 +5,7 @@ var _ = require('lodash'); var Copayer = require('./copayer'); var Bitcore = require('bitcore'); var PublicKey = Bitcore.PublicKey; +var WALLET_VERSION = '1.0.0'; function Wallet(opts) { opts = opts || {}; @@ -18,6 +19,7 @@ function Wallet(opts) { this.publicKeyRing = []; this.addressIndex = 0; this.copayers = []; + this.version = WALLET_VERSION; if (opts.pubKey) this.pubKey = new PublicKey(opts.pubKey); @@ -26,6 +28,10 @@ function Wallet(opts) { Wallet.fromObj = function (obj) { var x = new Wallet(); + // TODO add sanity checks OR migration steps? + if (!obj.pubKey || !obj.m || !obj.n) + return cb('Wallet corrupted'); + x.createdOn = obj.createdOn; x.id = obj.id; x.name = obj.name; @@ -39,6 +45,7 @@ Wallet.fromObj = function (obj) { }); x.pubKey = new PublicKey(obj.pubKey); + return x; }; diff --git a/lib/server.js b/lib/server.js index b00c566..dfb3710 100644 --- a/lib/server.js +++ b/lib/server.js @@ -11,6 +11,7 @@ var Explorers = require('bitcore-explorers'); var Lock = require('./lock'); var Storage = require('./storage'); +var SignUtils = require('./signutils'); var Wallet = require('./model/wallet'); var Copayer = require('./model/copayer'); @@ -77,7 +78,6 @@ CopayServer.prototype.createWallet = function (opts, cb) { self.storage.fetchWallet(opts.id, function (err, wallet) { if (err) return cb(err); if (!wallet) return cb('Wallet not found'); - return cb(null, wallet); }); }; @@ -95,6 +95,16 @@ CopayServer.prototype._runLocked = function (walletId, cb, task) { }); }; +/** + * Verifies a signature + * @param text + * @param signature + * @param pubKey + */ +CopayServer.prototype._verifySignature = function (text, signature, pubKey) { + return SignUtils.verify( text, signature, pubKey); +}; + /** * Joins a wallet in creation. * @param {Object} opts @@ -110,11 +120,13 @@ CopayServer.prototype._runLocked = function (walletId, cb, task) { self._runLocked(opts.walletId, cb, function (cb) { self.getWallet({ id: opts.walletId }, function (err, wallet) { if (err) return cb(err); + + if (!self._verifySignature(opts.xPubKey, opts.xPubKeySignature, wallet.pubKey)) { + return cb('Bad request'); + } + if (_.find(wallet.copayers, { xPubKey: opts.xPubKey })) return cb('Copayer already in wallet'); if (wallet.copayers.length == wallet.n) return cb('Wallet full'); - // TODO: validate copayer's extended public key using the public key from this wallet - // Note: use Bitcore.crypto.ecdsa .verify() - var copayer = new Copayer({ id: opts.id, name: opts.name, diff --git a/test/integration.js b/test/integration.js index 664de0c..9f45c15 100644 --- a/test/integration.js +++ b/test/integration.js @@ -203,6 +203,7 @@ describe('Copay server', function() { server = new CopayServer({ storage: storage, }); + server._verifySignature = sinon.stub().returns(true); }); it('should join existing wallet', function (done) {