From 265986e257fadd26b6ca3191b9880e5875da2cb7 Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Sun, 1 Mar 2015 10:27:26 -0300 Subject: [PATCH] pkr encryption --- lib/client/airgapped.js | 17 +++++++-- lib/client/api.js | 41 +++++++------------- lib/client/credentials.js | 1 + test/integration/client.js | 76 ++------------------------------------ 4 files changed, 33 insertions(+), 102 deletions(-) diff --git a/lib/client/airgapped.js b/lib/client/airgapped.js index 283ec6c..a096c2e 100644 --- a/lib/client/airgapped.js +++ b/lib/client/airgapped.js @@ -37,13 +37,24 @@ AirGapped.prototype.getSeed = function() { }; }; -AirGapped.prototype.signTxProposal = function(txp, pkr, m, n) { +AirGapped.prototype.signTxProposal = function(txp, encryptedPkr, m, n) { var self = this; - // TODO: complete credentials + var publicKeyRing; + try { + publicKeyRing = JSON.parse(WalletUtils.decryptMessage(encryptedPkr, self.credentials.personalEncryptingKey)); + } catch (ex) { + console.log(ex); + throw new Error('Could not decrypt public key ring'); + } + + if (!_.isArray(publicKeyRing) || publicKeyRing.length != n) { + throw new Error('Invalid public key ring'); + } + self.credentials.m = m; self.credentials.n = n; - self.credentials.addPublicKeyRing(pkr); + self.credentials.addPublicKeyRing(publicKeyRing); if (!Verifier.checkTxProposal(self.credentials, txp)) { throw new Error('Fake transaction proposal'); diff --git a/lib/client/api.js b/lib/client/api.js index f38c637..62ddcc8 100644 --- a/lib/client/api.js +++ b/lib/client/api.js @@ -461,30 +461,11 @@ API.prototype.getBalance = function(cb) { * */ -API.prototype.parseTxProposals = function(txData, cb) { - $.checkState(this.credentials && this.credentials.isComplete()); - - var self = this; - - var txps = txData.txps; - _processTxps(txps, self.credentials.sharedEncryptingKey); - - var fake = _.any(txps, function(txp) { - return (!Verifier.checkTxProposal(self.credentials, txp)); - }); - - if (fake) - return cb(new ServerCompromisedError('Server sent fake transaction proposal')); - - return cb(null, txps); -}; - - /** * * opts.doNotVerify - * opts.getRawTxps + * opts.forAirGapped * @return {undefined} */ @@ -497,11 +478,6 @@ API.prototype.getTxProposals = function(opts, cb) { self._doGetRequest(url, function(err, txps) { if (err) return cb(err); - var rawTxps; - if (opts.getRawTxps) { - rawTxps = JSON.parse(JSON.stringify(txps)); - } - _processTxps(txps, self.credentials.sharedEncryptingKey); var fake = _.any(txps, function(txp) { @@ -511,8 +487,19 @@ API.prototype.getTxProposals = function(opts, cb) { if (fake) return cb(new ServerCompromisedError('Server sent fake transaction proposal')); - // TODO: return a single arg - return cb(null, txps, rawTxps); + var result; + if (opts.forAirGapped) { + result = { + txps: JSON.parse(JSON.stringify(txps)), + publicKeyRing: WalletUtils.encryptMessage(JSON.stringify(self.credentials.publicKeyRing), self.credentials.personalEncryptingKey), + m: self.credentials.m, + n: self.credentials.n, + }; + } else { + result = txps; + } + + return cb(null, result); }); }; diff --git a/lib/client/credentials.js b/lib/client/credentials.js index 5af6a76..c4bd7fe 100644 --- a/lib/client/credentials.js +++ b/lib/client/credentials.js @@ -59,6 +59,7 @@ Credentials.prototype._expand = function() { this.xPubKey = (new Bitcore.HDPublicKey(xPrivKey)).toString(); this.requestPrivKey = xPrivKey.derive('m/1/1').privateKey.toString(); } + this.personalEncryptingKey = WalletUtils.privateKeyToAESKey(this.requestPrivKey); this.copayerId = WalletUtils.xPubToCopayerId(this.xPubKey); }; diff --git a/test/integration/client.js b/test/integration/client.js index 21ba42b..1b0c8a1 100644 --- a/test/integration/client.js +++ b/test/integration/client.js @@ -865,69 +865,6 @@ describe('client API ', function() { }); describe('Air gapped related flows', function() { - it('should be able get Tx proposals from a file', function(done) { - helpers.createAndJoinWallet(clients, 1, 2, function(w) { - clients[0].createAddress(function(err, x0) { - should.not.exist(err); - blockExplorerMock.setUtxo(x0, 1, 1); - var opts = { - amount: 10000000, - toAddress: 'n2TBMPzPECGUfcT2EByiTJ12TPZkhN2mN5', - message: 'hello 1-1', - }; - clients[1].sendTxProposal(opts, function(err, x) { - should.not.exist(err); - clients[1].getTxProposals({ - getRawTxps: true - }, function(err, txs, rawTxps) { - should.not.exist(err); - - clients[0].parseTxProposals({ - txps: rawTxps - }, function(err, txs2) { - should.not.exist(err); - txs[0].should.deep.equal(txs2[0]); - done(); - }); - - }); - }); - }); - }); - }); - it('should detect fakes from Tx proposals file', function(done) { - helpers.createAndJoinWallet(clients, 1, 2, function(w) { - clients[0].createAddress(function(err, x0) { - should.not.exist(err); - blockExplorerMock.setUtxo(x0, 1, 1); - var opts = { - amount: 10000000, - toAddress: 'n2TBMPzPECGUfcT2EByiTJ12TPZkhN2mN5', - message: 'hello 1-1', - }; - clients[1].sendTxProposal(opts, function(err, x) { - should.not.exist(err); - clients[1].getTxProposals({ - getRawTxps: true - }, function(err, txs, rawTxps) { - should.not.exist(err); - - //Tamper - rawTxps[0].amount++; - - clients[0].parseTxProposals({ - txps: rawTxps - }, function(err, txs2) { - err.code.should.equal('SERVERCOMPROMISED'); - done(); - }); - - }); - }); - }); - }); - }); - it('should create wallet in proxy from airgapped', function(done) { var airgapped = new AirGapped({ network: 'testnet' @@ -989,16 +926,11 @@ describe('client API ', function() { }, function(txp, next) { proxy.getTxProposals({ - getRawTxps: true + forAirGapped: true }, next); }, - function(txps, rawTxps, next) { - // TODO: these params should be grouped, signed, encrypted, etc - var pkr = proxy.credentials.publicKeyRing; - var m = proxy.credentials.m; - var n = proxy.credentials.n; - - var signatures = airgapped.signTxProposal(rawTxps[0], pkr, m, n); + function(bundle, next) { + var signatures = airgapped.signTxProposal(bundle.txps[0], bundle.publicKeyRing, bundle.m, bundle.n); next(null, signatures); }, function(signatures, next) { @@ -1028,7 +960,7 @@ describe('client API ', function() { } ); }); - it.skip('should be able to detect tampered pkr when signing on airgapped client', function(done) {}); + it.skip('should be able to detect tampered PKR when signing on airgapped client', function(done) {}); it.skip('should be able to detect tampered proposal when signing on airgapped client', function(done) {}); it.skip('should be able to detect tampered change address when signing on airgapped client', function(done) {}); });