From 79d79012d4a62f38f8136e7c1b1979f1d7f30683 Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Fri, 12 Sep 2014 17:24:00 -0700 Subject: [PATCH] fix bug where you can't use isForMe without payloadKeypair It should be possible to check to see if a message isForMe with only the scanKeypair, and not the payloadKeypair. There was a bug where only the scanKeypair was being used to produce the receiveKeypair, but this was a mistake. Both the scanPubkey and payloadPubkey should be necessary to produce the receivePubkey, and both the scanPrivkey and payloadPrivkey should be necessary to produce the receivePrivkey. If an online computer has only the public keys of both (and the scanPrivkey), then that is good enough to check for isForMe. --- examples/stealthmessage.js | 13 +++++++++++++ lib/expmt/stealthaddress.js | 2 +- lib/expmt/stealthkey.js | 4 ++-- test/stealthkey.js | 4 ++-- test/stealthmessage.js | 11 ++++++++++- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/examples/stealthmessage.js b/examples/stealthmessage.js index 5ed227d..809af13 100644 --- a/examples/stealthmessage.js +++ b/examples/stealthmessage.js @@ -48,3 +48,16 @@ console.log('Is the message for me? ' + (StealthMessage.isForMe(encbuf, sk) ? "y var messagebuf2 = StealthMessage.decrypt(encbuf, sk); console.log('Decrypted message: ' + messagebuf2.toString()); + +//If you do not have the payload privkey, you can still use isForMe. +sk.payloadKeypair.privkey = undefined; + +console.log('Without payload privkey, is the message for me? ' + (StealthMessage.isForMe(encbuf, sk) ? "yes" : "no")); + +//...but not decrypt + +try { + StealthMessage.decrypt(encbuf, sk); +} catch (e) { + console.log("...but without the payload privkey, I can't decrypt."); +} diff --git a/lib/expmt/stealthaddress.js b/lib/expmt/stealthaddress.js index 0d82128..2c5cb8b 100644 --- a/lib/expmt/stealthaddress.js +++ b/lib/expmt/stealthaddress.js @@ -65,7 +65,7 @@ StealthAddress.prototype.getSharedKeypair = function(senderKeypair) { StealthAddress.prototype.getReceivePubkey = function(senderKeypair) { var sharedKeypair = this.getSharedKeypair(senderKeypair); - var pubkey = Pubkey(this.payloadPubkey.point.add(sharedKeypair.pubkey.point)); + var pubkey = Pubkey(this.scanPubkey.point.add(sharedKeypair.pubkey.point).add(this.payloadPubkey.point)); return pubkey; }; diff --git a/lib/expmt/stealthkey.js b/lib/expmt/stealthkey.js index 2570c77..385983b 100644 --- a/lib/expmt/stealthkey.js +++ b/lib/expmt/stealthkey.js @@ -46,14 +46,14 @@ Stealthkey.prototype.getSharedKeypair = function(senderPubkey) { Stealthkey.prototype.getReceivePubkey = function(senderPubkey) { var sharedKeypair = this.getSharedKeypair(senderPubkey); - var pubkey = Pubkey({point: this.payloadKeypair.pubkey.point.add(sharedKeypair.pubkey.point)}); + var pubkey = Pubkey({point: this.scanKeypair.pubkey.point.add(sharedKeypair.pubkey.point).add(this.payloadKeypair.pubkey.point)}); return pubkey; }; Stealthkey.prototype.getReceiveKeypair = function(senderPubkey) { var sharedKeypair = this.getSharedKeypair(senderPubkey); - var privkey = Privkey({bn: this.payloadKeypair.privkey.bn.add(sharedKeypair.privkey.bn).mod(Point.getN())}); + var privkey = Privkey({bn: this.scanKeypair.privkey.bn.add(sharedKeypair.privkey.bn).add(this.payloadKeypair.privkey.bn).mod(Point.getN())}); var key = Keypair({privkey: privkey}); key.privkey2pubkey(); diff --git a/test/stealthkey.js b/test/stealthkey.js index 472cd75..69b8b22 100644 --- a/test/stealthkey.js +++ b/test/stealthkey.js @@ -103,12 +103,12 @@ describe('Stealthkey', function() { describe('#isForMe', function() { it('should return true if it (the transaction or message) is for me', function() { - var pubkeyhash = new Buffer('3cb64fa6ee9b3e8754e3e2bd033bf61048604a99', 'hex'); + var pubkeyhash = new Buffer('0db7f06cffb913322e211e8b0688efe8ff52aa8d', 'hex'); stealthkey.isForMe(senderKeypair.pubkey, pubkeyhash).should.equal(true); }); it('should return false if it (the transaction or message) is not for me', function() { - var pubkeyhash = new Buffer('00b64fa6ee9b3e8754e3e2bd033bf61048604a99', 'hex'); + var pubkeyhash = new Buffer('ffb7f06cffb913322e211e8b0688efe8ff52aa8d', 'hex'); stealthkey.isForMe(senderKeypair.pubkey, pubkeyhash).should.equal(false); }); diff --git a/test/stealthmessage.js b/test/stealthmessage.js index 3a0015c..2fd3769 100644 --- a/test/stealthmessage.js +++ b/test/stealthmessage.js @@ -1,3 +1,4 @@ +var Keypair = require('../lib/keypair'); var StealthMessage = require('../lib/expmt/stealthmessage'); var Stealthkey = require('../lib/expmt/stealthkey'); var StealthAddress = require('../lib/expmt/stealthAddress'); @@ -11,7 +12,7 @@ describe('StealthMessage', function() { var payloadKeypair = KDF.buf2keypair(new Buffer('key1')); var scanKeypair = KDF.buf2keypair(new Buffer('key2')); var fromKeypair = KDF.buf2keypair(new Buffer('key3')); - var enchex = 'f557994f16d0d628fa4fdb4ab3d7e0bc5f2754f20381c7831a20c7c9ec88dcf092ea3683261798ccda991ed65a3a54a036d8125dec0381c7831a20c7c9ec88dcf092ea3683261798ccda991ed65a3a54a036d8125dec9f86d081884c7d659a2feaa0c55ad01560ba2904d3bc8395b6c4a6f87648edb33db6a22170e5e26f340c7ba943169210234cd6a753ad13919b0ab7d678b47b5e7d63e452382de2c2590fb57ef048f7b3'; + var enchex = '3867dce7be22e8551512b25f329b51fd5fe8ecfe0381c7831a20c7c9ec88dcf092ea3683261798ccda991ed65a3a54a036d8125dec0381c7831a20c7c9ec88dcf092ea3683261798ccda991ed65a3a54a036d8125dec9f86d081884c7d659a2feaa0c55ad015aca97de5af3a34a0f47eee0a1f7774dcb759187555003282bd23b047bceb5b2f2c1ee35b8f0be1fda7a41424f6cc8030559c8c32ea8cc812860f4c8123f1417a'; var encbuf = new Buffer(enchex, 'hex'); var ivbuf = Hash.sha256(new Buffer('test')).slice(0, 128 / 8); var sk = Stealthkey().set({payloadKeypair: payloadKeypair, scanKeypair: scanKeypair}); @@ -73,6 +74,14 @@ describe('StealthMessage', function() { StealthMessage.isForMe(encbuf, sk).should.equal(true); }); + it('should know that this message is for me even if my payloadPrivkey is not present', function() { + var sk2 = new Stealthkey(); + sk2.scanKeypair = sk.scanKeypair; + sk2.payloadKeypair = Keypair().set({pubkey: sk.payloadKeypair.pubkey}); + should.not.exist(sk2.payloadKeypair.privkey); + StealthMessage.isForMe(encbuf, sk2).should.equal(true); + }); + }); describe('#encrypt', function() {