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;
// 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');

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.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);
});
};

1
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);
};

76
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) {});
});

Loading…
Cancel
Save