Browse Source

fix proposal signature validation in publishTx

activeAddress
Ivan Socolsky 9 years ago
parent
commit
5f35aafc29
  1. 14
      lib/server.js
  2. 34
      test/integration/server.js

14
lib/server.js

@ -1618,8 +1618,6 @@ WalletService.prototype._verifyRequestPubKey = function(requestPubKey, signature
* @param {Object} opts * @param {Object} opts
* @param {string} opts.txProposalId - The tx id. * @param {string} opts.txProposalId - The tx id.
* @param {string} opts.proposalSignature - S(raw tx). Used by other copayers to verify the proposal. * @param {string} opts.proposalSignature - S(raw tx). Used by other copayers to verify the proposal.
* @param {string} opts.proposalSignaturePubKey - (Optional) An alternative public key used to verify the proposal signature.
* @param {string} opts.proposalSignaturePubKeySig - (Optional) A signature used to validate the opts.proposalSignaturePubKey.
*/ */
WalletService.prototype.publishTx = function(opts, cb) { WalletService.prototype.publishTx = function(opts, cb) {
var self = this; var self = this;
@ -1648,13 +1646,11 @@ WalletService.prototype.publishTx = function(opts, cb) {
return cb(new ClientError('Invalid proposal signature')); return cb(new ClientError('Invalid proposal signature'));
} }
// Verify signingKey // Save signature info for other copayers to check
if (opts.proposalSignaturePubKey) { txp.proposalSignature = opts.proposalSignature;
if (opts.proposalSignaturePubKey != signingKey || if (signingKey.selfSigned) {
!self._verifyRequestPubKey(opts.proposalSignaturePubKey, opts.proposalSignaturePubKeySig, copayer.xPubKey) txp.proposalSignaturePubKey = signingKey.key;
) { txp.proposalSignaturePubKeySig = signingKey.signature;
return cb(new ClientError('Invalid proposal signing key'));
}
} }
// Verify UTXOs are still available // Verify UTXOs are still available

34
test/integration/server.js

@ -2739,6 +2739,7 @@ describe('Wallet service', function() {
server.getPendingTxs({}, function(err, txs) { server.getPendingTxs({}, function(err, txs) {
should.not.exist(err); should.not.exist(err);
txs.length.should.equal(1); txs.length.should.equal(1);
should.exist(txs[0].proposalSignature);
done(); done();
}); });
}); });
@ -2795,21 +2796,14 @@ describe('Wallet service', function() {
should.not.exist(err); should.not.exist(err);
should.exist(txp); should.exist(txp);
var raw = txp.getRawTx();
var proposalSignature = helpers.signMessage(raw, TestData.copayers[0].privKey_1H_0);
var pubKey = new Bitcore.PrivateKey(TestData.copayers[0].privKey_1H_0).toPublicKey().toString();
var pubKeySig = helpers.signMessage(pubKey, TestData.copayers[1].privKey_1H_0);
var publishOpts = { var publishOpts = {
txProposalId: txp.id, txProposalId: txp.id,
proposalSignature: proposalSignature, proposalSignature: helpers.signMessage(txp.getRawTx(), TestData.copayers[1].privKey_1H_0),
proposalSignaturePubKey: pubKey,
proposalSignaturePubKeySig: pubKeySig,
} }
server.publishTx(publishOpts, function(err) { server.publishTx(publishOpts, function(err) {
should.exist(err); should.exist(err);
err.message.should.contain('Invalid proposal signing key'); err.message.should.contain('Invalid proposal signature');
done(); done();
}); });
}); });
@ -2818,18 +2812,17 @@ describe('Wallet service', function() {
it('should accept a tx proposal signed with a custom key', function(done) { it('should accept a tx proposal signed with a custom key', function(done) {
var reqPrivKey = new Bitcore.PrivateKey(); var reqPrivKey = new Bitcore.PrivateKey();
var reqPubKey = reqPrivKey.toPublicKey(); var reqPubKey = reqPrivKey.toPublicKey().toString();
var xPrivKey = TestData.copayers[0].xPrivKey_44H_0H_0H; var xPrivKey = TestData.copayers[0].xPrivKey_44H_0H_0H;
var sig = helpers.signRequestPubKey(reqPubKey, xPrivKey);
var opts = { var accessOpts = {
copayerId: TestData.copayers[0].id44, copayerId: TestData.copayers[0].id44,
requestPubKey: reqPubKey, requestPubKey: reqPubKey,
signature: sig, signature: helpers.signRequestPubKey(reqPubKey, xPrivKey),
}; };
server.addAccess(opts, function(err) { server.addAccess(accessOpts, function(err) {
should.not.exist(err); should.not.exist(err);
helpers.stubUtxos(server, wallet, [1, 2], function() { helpers.stubUtxos(server, wallet, [1, 2], function() {
@ -2846,19 +2839,24 @@ describe('Wallet service', function() {
var publishOpts = { var publishOpts = {
txProposalId: txp.id, txProposalId: txp.id,
proposalSignature: helpers.signMessage(txp.getRawTx(), reqPrivKey), proposalSignature: helpers.signMessage(txp.getRawTx(), reqPrivKey),
proposalSignaturePubKey: reqPubKey,
proposalSignaturePubKeySig: sig,
} }
server.publishTx(publishOpts, function(err) { server.publishTx(publishOpts, function(err) {
should.exist(err); should.not.exist(err);
err.message.should.contain('Invalid proposal signing key'); server.getTx({
txProposalId: txp.id
}, function(err, x) {
should.not.exist(err);
x.proposalSignature.should.equal(publishOpts.proposalSignature);
x.proposalSignaturePubKey.should.equal(accessOpts.requestPubKey);
x.proposalSignaturePubKeySig.should.equal(accessOpts.signature);
done(); done();
}); });
}); });
}); });
}); });
}); });
});
it('should fail to send a temporary tx proposal if utxos are unavailable', function(done) { it('should fail to send a temporary tx proposal if utxos are unavailable', function(done) {
var txp1, txp2; var txp1, txp2;

Loading…
Cancel
Save