From 56f5a5841904a0f7e91bb608f97c8e1e1f23232e Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Sat, 21 Feb 2015 19:29:42 -0300 Subject: [PATCH] WIP ro-rw --- lib/client/api.js | 23 +++++++++++++++++------ lib/client/verifier.js | 2 ++ lib/expressapp.js | 3 +++ lib/model/copayer.js | 19 ++++++++++++++----- lib/server.js | 11 ++++++++--- lib/storage.js | 3 ++- test/integration/clientApi.js | 2 +- 7 files changed, 47 insertions(+), 16 deletions(-) diff --git a/lib/client/api.js b/lib/client/api.js index d6126c8..2bc5bfc 100644 --- a/lib/client/api.js +++ b/lib/client/api.js @@ -94,9 +94,13 @@ API.prototype._tryToComplete = function(data, cb) { if (wallet.status != 'complete') return cb('Wallet Incomplete'); - if (!Verifier.checkCopayers(wallet.copayers, data.walletPrivKey, data.xPrivKey, data.n)) + if (!Verifier.checkCopayers(wallet.copayers, data.walletPrivKey, + data.xPrivKey, data.n)) { + +console.log('[api.js.99]'); //TODO return cb(new ServerCompromisedError( 'Copayers in the wallet could not be verified to have known the wallet secret')); + } data.publicKeyRing = _.pluck(wallet.copayers, 'xPubKey') @@ -140,8 +144,13 @@ API.prototype._doRequest = function(method, url, args, data, cb) { var reqSignature; data = data || {}; - if (data.signingPrivKey) - reqSignature = _signRequest(method, url, args, data.signingPrivKey); + if (method == 'get') { + if (data.roPrivKey) + reqSignature = _signRequest(method, url, args, data.roPrivKey); + } else { + if (data.rwPrivKey) + reqSignature = _signRequest(method, url, args, data.rwPrivKey); + } var absUrl = this.baseUrl + url; var args = { @@ -185,8 +194,9 @@ API.prototype._doGetRequest = function(url, data, cb) { API.prototype._initData = function(network, walletPrivKey, m, n) { var xPrivKey = new Bitcore.HDPrivateKey(network); - var xPubKey = (new Bitcore.HDPublicKey(xPrivKey)).toString(); - var signingPrivKey = (new Bitcore.HDPrivateKey(xPrivKey)).derive('m/1/0').privateKey; + var xPubKey = xPrivKey.toString(); + var roPrivKey = xPrivKey.derive('m/1/0').privateKey; + var rwPrivKey = xPrivKey.derive('m/1/1').privateKey; var sharedEncryptingKey = Bitcore.crypto.Hash.sha256(walletPrivKey.toBuffer()).slice(0, 16).toString('base64'); var copayerId = WalletUtils.xPubToCopayerId(xPubKey); @@ -197,7 +207,8 @@ API.prototype._initData = function(network, walletPrivKey, m, n) { network: network, m: m, n: n, - signingPrivKey: signingPrivKey.toWIF(), + roPrivKey: roPrivKey.toWIF(), + rwPrivKey: rwPrivKey.toWIF(), walletPrivKey: walletPrivKey.toWIF(), sharedEncryptingKey: sharedEncryptingKey, }; diff --git a/lib/client/verifier.js b/lib/client/verifier.js index 2b3bb0b..3201447 100644 --- a/lib/client/verifier.js +++ b/lib/client/verifier.js @@ -45,6 +45,8 @@ Verifier.checkCopayers = function(copayers, walletPrivKey, myXPrivKey, n) { return false; var myXPubKey = new Bitcore.HDPublicKey(myXPrivKey).toString(); +console.log('[verifier.js.50:copayers:]',copayers); //TODO +console.log('[verifier.js.48:myXPubKey:]',myXPubKey); //TODO if (!_.contains(_.pluck(copayers, 'xPubKey'), myXPubKey)) { log.error('Server response does not contains our public keys') return false; diff --git a/lib/expressapp.js b/lib/expressapp.js index 71f920f..64e2d42 100644 --- a/lib/expressapp.js +++ b/lib/expressapp.js @@ -88,10 +88,13 @@ ExpressApp.start = function(opts) { code: 'NOTAUTHORIZED' }), res, req); + var readOnly = req.method == 'GET'; + var auth = { copayerId: credentials.copayerId, message: req.method.toLowerCase() + '|' + req.url + '|' + JSON.stringify(req.body), signature: credentials.signature, + readOnly: readOnly, }; WalletService.getInstanceWithAuth(auth, function(err, server) { if (err) return returnError(err, res, req); diff --git a/lib/model/copayer.js b/lib/model/copayer.js index d9cfc31..3c3f54f 100644 --- a/lib/model/copayer.js +++ b/lib/model/copayer.js @@ -11,7 +11,8 @@ var AddressManager = require('./addressmanager'); var Utils = require('../walletutils'); -var MESSAGE_SIGNING_PATH = "m/1/0"; +var RO_SIGNING_PATH = "m/1/0"; +var RW_SIGNING_PATH = "m/1/1"; function Copayer() { this.version = '1.0.0'; @@ -30,7 +31,8 @@ Copayer.create = function(opts) { x.id = Utils.xPubToCopayerId(x.xPubKey); x.name = opts.name; x.xPubKeySignature = opts.xPubKeySignature; // So third parties can check independently - x.signingPubKey = x.getSigningPubKey(); + x.roPubKey = x.getROPubKey(); + x.rwPubKey = x.getRWPubKey(); x.addressManager = AddressManager.create({ copayerIndex: opts.copayerIndex }); @@ -46,7 +48,8 @@ Copayer.fromObj = function(obj) { x.name = obj.name; x.xPubKey = obj.xPubKey; x.xPubKeySignature = obj.xPubKeySignature; - x.signingPubKey = obj.signingPubKey; + x.roPubKey = obj.roPubKey; + x.rwPubKey = obj.rwPubKey; x.addressManager = AddressManager.fromObj(obj.addressManager); return x; @@ -60,8 +63,14 @@ Copayer.prototype.getPublicKey = function(path) { .toString(); }; -Copayer.prototype.getSigningPubKey = function() { - return this.getPublicKey(MESSAGE_SIGNING_PATH); +Copayer.prototype.getROPubKey = function() { + return this.getPublicKey(RO_SIGNING_PATH); }; +Copayer.prototype.getRWPubKey = function() { + return this.getPublicKey(RW_SIGNING_PATH); +}; + + + module.exports = Copayer; diff --git a/lib/server.js b/lib/server.js index 0404d5e..8447daa 100644 --- a/lib/server.js +++ b/lib/server.js @@ -66,7 +66,8 @@ WalletService.getInstance = function() { * @param {Object} opts * @param {string} opts.copayerId - The copayer id making the request. * @param {string} opts.message - The contents of the request to be signed. - * @param {string} opts.signature - Signature of message to be verified using the copayer's signingPubKey. + * @param {string} opts.signature - Signature of message to be verified using the copayer's roPubKey / rwPubKey + * @param {string} opts.readOnly - Signature of message to be verified using the copayer's roPubKey / rwPubKey */ WalletService.getInstanceWithAuth = function(opts, cb) { @@ -78,8 +79,12 @@ WalletService.getInstanceWithAuth = function(opts, cb) { if (err) return cb(err); if (!copayer) return cb(new ClientError('NOTAUTHORIZED', 'Copayer not found')); - var isValid = server._verifySignature(opts.message, opts.signature, copayer.signingPubKey); - if (!isValid) return cb(new ClientError('NOTAUTHORIZED', 'Invalid signature')); + var pubKey = opts.readOnly ? copayer.roPubKey : copayer.rwPubKey; + var isValid = server._verifySignature(opts.message, opts.signature, + pubKey); + + if (!isValid) + return cb(new ClientError('NOTAUTHORIZED', 'Invalid signature')); server.copayerId = opts.copayerId; server.walletId = copayer.walletId; diff --git a/lib/storage.js b/lib/storage.js index 78ae1ce..7319ad9 100644 --- a/lib/storage.js +++ b/lib/storage.js @@ -84,7 +84,8 @@ Storage.prototype.storeWalletAndUpdateCopayersLookup = function(wallet, cb) { _.each(wallet.copayers, function(copayer) { var value = { walletId: wallet.id, - signingPubKey: copayer.signingPubKey, + roPubKey: copayer.roPubKey, + rwPubKey: copayer.rwPubKey, }; ops.push({ type: 'put', diff --git a/test/integration/clientApi.js b/test/integration/clientApi.js index ce9925a..ebbef81 100644 --- a/test/integration/clientApi.js +++ b/test/integration/clientApi.js @@ -164,7 +164,7 @@ describe('client API ', function() { }) }); }); - it('should be able to complete wallets in copayer that joined later', function(done) { + it.only('should be able to complete wallets in copayer that joined later', function(done) { helpers.createAndJoinWallet(clients, 2, 3, function(err) { should.not.exist(err); clients[0].getBalance(function(err, x) {