Browse Source

pkr encryption

activeAddress
Ivan Socolsky 10 years ago
parent
commit
265986e257
  1. 17
      lib/client/airgapped.js
  2. 41
      lib/client/api.js
  3. 1
      lib/client/credentials.js
  4. 76
      test/integration/client.js

17
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; 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.m = m;
self.credentials.n = n; self.credentials.n = n;
self.credentials.addPublicKeyRing(pkr); self.credentials.addPublicKeyRing(publicKeyRing);
if (!Verifier.checkTxProposal(self.credentials, txp)) { if (!Verifier.checkTxProposal(self.credentials, txp)) {
throw new Error('Fake transaction proposal'); throw new Error('Fake transaction proposal');

41
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.doNotVerify
* opts.getRawTxps * opts.forAirGapped
* @return {undefined} * @return {undefined}
*/ */
@ -497,11 +478,6 @@ API.prototype.getTxProposals = function(opts, cb) {
self._doGetRequest(url, function(err, txps) { self._doGetRequest(url, function(err, txps) {
if (err) return cb(err); if (err) return cb(err);
var rawTxps;
if (opts.getRawTxps) {
rawTxps = JSON.parse(JSON.stringify(txps));
}
_processTxps(txps, self.credentials.sharedEncryptingKey); _processTxps(txps, self.credentials.sharedEncryptingKey);
var fake = _.any(txps, function(txp) { var fake = _.any(txps, function(txp) {
@ -511,8 +487,19 @@ API.prototype.getTxProposals = function(opts, cb) {
if (fake) if (fake)
return cb(new ServerCompromisedError('Server sent fake transaction proposal')); return cb(new ServerCompromisedError('Server sent fake transaction proposal'));
// TODO: return a single arg var result;
return cb(null, txps, rawTxps); 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);
}); });
}; };

1
lib/client/credentials.js

@ -59,6 +59,7 @@ Credentials.prototype._expand = function() {
this.xPubKey = (new Bitcore.HDPublicKey(xPrivKey)).toString(); this.xPubKey = (new Bitcore.HDPublicKey(xPrivKey)).toString();
this.requestPrivKey = xPrivKey.derive('m/1/1').privateKey.toString(); this.requestPrivKey = xPrivKey.derive('m/1/1').privateKey.toString();
} }
this.personalEncryptingKey = WalletUtils.privateKeyToAESKey(this.requestPrivKey);
this.copayerId = WalletUtils.xPubToCopayerId(this.xPubKey); this.copayerId = WalletUtils.xPubToCopayerId(this.xPubKey);
}; };

76
test/integration/client.js

@ -865,69 +865,6 @@ describe('client API ', function() {
}); });
describe('Air gapped related flows', 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) { it('should create wallet in proxy from airgapped', function(done) {
var airgapped = new AirGapped({ var airgapped = new AirGapped({
network: 'testnet' network: 'testnet'
@ -989,16 +926,11 @@ describe('client API ', function() {
}, },
function(txp, next) { function(txp, next) {
proxy.getTxProposals({ proxy.getTxProposals({
getRawTxps: true forAirGapped: true
}, next); }, next);
}, },
function(txps, rawTxps, next) { function(bundle, next) {
// TODO: these params should be grouped, signed, encrypted, etc var signatures = airgapped.signTxProposal(bundle.txps[0], bundle.publicKeyRing, bundle.m, bundle.n);
var pkr = proxy.credentials.publicKeyRing;
var m = proxy.credentials.m;
var n = proxy.credentials.n;
var signatures = airgapped.signTxProposal(rawTxps[0], pkr, m, n);
next(null, signatures); next(null, signatures);
}, },
function(signatures, next) { 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 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) {}); it.skip('should be able to detect tampered change address when signing on airgapped client', function(done) {});
}); });

Loading…
Cancel
Save