Browse Source
This code should be regarded as being a proof-of-concept, and needs more review before being used in production code. At least one thing is guaranteed to change, and that is the format of a stealth address.patch-2
Ryan X. Charles
11 years ago
4 changed files with 219 additions and 3 deletions
@ -0,0 +1,85 @@ |
|||||
|
var Stealthkey = require('./stealthkey'); |
||||
|
var StealthAddress = require('./stealthaddress'); |
||||
|
var ECIES = require('./ecies'); |
||||
|
var Message = require('../message'); |
||||
|
var Keypair = require('../keypair'); |
||||
|
var Address = require('../address'); |
||||
|
var Pubkey = require('../pubkey'); |
||||
|
|
||||
|
var StealthMessage = function StealthMessage(obj) { |
||||
|
if (!(this instanceof StealthMessage)) |
||||
|
return new StealthMessage(obj); |
||||
|
if (obj) |
||||
|
this.set(obj); |
||||
|
}; |
||||
|
|
||||
|
StealthMessage.prototype.set = function(obj) { |
||||
|
this.messagebuf = obj.messagebuf || this.messagebuf; |
||||
|
this.encbuf = obj.encbuf || this.encbuf; |
||||
|
this.toStealthAddress = obj.toStealthAddress || this.toStealthAddress; |
||||
|
this.toStealthkey = obj.toStealthkey || this.toStealthkey; |
||||
|
this.fromKeypair = obj.fromKeypair || this.fromKeypair; |
||||
|
this.receiveAddress = obj.receiveAddress || this.receiveAddress; |
||||
|
return this; |
||||
|
}; |
||||
|
|
||||
|
StealthMessage.encrypt = function(messagebuf, toStealthAddress, fromKeypair, ivbuf) { |
||||
|
var sm = StealthMessage().set({ |
||||
|
messagebuf: messagebuf, |
||||
|
toStealthAddress: toStealthAddress, |
||||
|
fromKeypair: fromKeypair |
||||
|
}); |
||||
|
sm.encrypt(ivbuf); |
||||
|
var buf = Buffer.concat([ |
||||
|
sm.receiveAddress.hashbuf, |
||||
|
sm.fromKeypair.pubkey.toDER(true), |
||||
|
sm.encbuf |
||||
|
]); |
||||
|
return buf; |
||||
|
}; |
||||
|
|
||||
|
StealthMessage.decrypt = function(buf, toStealthkey) { |
||||
|
var sm = StealthMessage().set({ |
||||
|
toStealthkey: toStealthkey, |
||||
|
receiveAddress: Address().set({hashbuf: buf.slice(0, 20)}), |
||||
|
fromKeypair: Keypair().set({pubkey: Pubkey().fromDER(buf.slice(20, 20 + 33))}), |
||||
|
encbuf: buf.slice(20 + 33) |
||||
|
}); |
||||
|
return sm.decrypt().messagebuf; |
||||
|
}; |
||||
|
|
||||
|
StealthMessage.isForMe = function(buf, toStealthkey) { |
||||
|
var sm = StealthMessage().set({ |
||||
|
toStealthkey: toStealthkey, |
||||
|
receiveAddress: Address().set({hashbuf: buf.slice(0, 20)}), |
||||
|
fromKeypair: Keypair().set({pubkey: Pubkey().fromDER(buf.slice(20, 20 + 33))}), |
||||
|
encbuf: buf.slice(20 + 33) |
||||
|
}); |
||||
|
return sm.isForMe(); |
||||
|
}; |
||||
|
|
||||
|
StealthMessage.prototype.encrypt = function(ivbuf) { |
||||
|
if (!this.fromKeypair) |
||||
|
this.fromKeypair = Keypair().fromRandom(); |
||||
|
var receivePubkey = this.toStealthAddress.getReceivePubkey(this.fromKeypair); |
||||
|
this.receiveAddress = Address().fromPubkey(receivePubkey); |
||||
|
this.encbuf = ECIES.encrypt(this.messagebuf, Keypair().set({pubkey: receivePubkey}), this.fromKeypair, ivbuf); |
||||
|
return this; |
||||
|
}; |
||||
|
|
||||
|
StealthMessage.prototype.decrypt = function() { |
||||
|
var receiveKeypair = this.toStealthkey.getReceiveKeypair(this.fromKeypair.pubkey); |
||||
|
this.messagebuf = ECIES.decrypt(this.encbuf, receiveKeypair); |
||||
|
return this; |
||||
|
}; |
||||
|
|
||||
|
StealthMessage.prototype.isForMe = function() { |
||||
|
var receivePubkey = this.toStealthkey.getReceivePubkey(this.fromKeypair.pubkey); |
||||
|
var receiveAddress = Address().fromPubkey(receivePubkey); |
||||
|
if (receiveAddress.toString('hex') === this.receiveAddress.toString('hex')) |
||||
|
return true; |
||||
|
else |
||||
|
return false; |
||||
|
}; |
||||
|
|
||||
|
module.exports = StealthMessage; |
@ -0,0 +1,130 @@ |
|||||
|
var StealthMessage = require('../lib/expmt/stealthmessage'); |
||||
|
var Stealthkey = require('../lib/expmt/stealthkey'); |
||||
|
var StealthAddress = require('../lib/expmt/stealthAddress'); |
||||
|
var KDF = require('../lib/kdf'); |
||||
|
var Hash = require('../lib/hash'); |
||||
|
var should = require('chai').should(); |
||||
|
var Address = require('../lib/address'); |
||||
|
|
||||
|
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 encbuf = new Buffer(enchex, 'hex'); |
||||
|
var ivbuf = Hash.sha256(new Buffer('test')).slice(0, 128 / 8); |
||||
|
var sk = Stealthkey().set({payloadKeypair: payloadKeypair, scanKeypair: scanKeypair}); |
||||
|
var sa = StealthAddress().fromStealthkey(sk); |
||||
|
var messagebuf = new Buffer('this is my message'); |
||||
|
|
||||
|
it('should make a new stealthmessage', function() { |
||||
|
var sm = new StealthMessage(); |
||||
|
should.exist(sm); |
||||
|
sm = StealthMessage() |
||||
|
should.exist(sm); |
||||
|
}); |
||||
|
|
||||
|
it('should allow "set" style syntax', function() { |
||||
|
var encbuf = StealthMessage().set({ |
||||
|
messagebuf: messagebuf, |
||||
|
toStealthAddress: sa |
||||
|
}).encrypt().encbuf; |
||||
|
should.exist(encbuf); |
||||
|
encbuf.length.should.equal(113); |
||||
|
}); |
||||
|
|
||||
|
describe('#set', function() { |
||||
|
|
||||
|
it('should set the messagebuf', function() { |
||||
|
var sm = StealthMessage().set({messagebuf: messagebuf}); |
||||
|
should.exist(sm.messagebuf); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
describe('@encrypt', function() { |
||||
|
|
||||
|
it('should encrypt a message', function() { |
||||
|
var encbuf = StealthMessage.encrypt(messagebuf, sa); |
||||
|
encbuf.length.should.equal(166); |
||||
|
}); |
||||
|
|
||||
|
it('should encrypt a message with this fromKeypair and ivbuf the same each time', function() { |
||||
|
var encbuf = StealthMessage.encrypt(messagebuf, sa, fromKeypair, ivbuf); |
||||
|
encbuf.length.should.equal(166); |
||||
|
encbuf.toString('hex').should.equal(enchex); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
describe('@decrypt', function() { |
||||
|
|
||||
|
it('should decrypt this known message correctly', function() { |
||||
|
var messagebuf2 = StealthMessage.decrypt(encbuf, sk); |
||||
|
messagebuf2.toString('hex').should.equal(messagebuf.toString('hex')); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
describe('@isForMe', function() { |
||||
|
|
||||
|
it('should know that this message is for me', function() { |
||||
|
StealthMessage.isForMe(encbuf, sk).should.equal(true); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
describe('#encrypt', function() { |
||||
|
|
||||
|
it('should encrypt this message', function() { |
||||
|
var sm = StealthMessage().set({ |
||||
|
messagebuf: messagebuf, |
||||
|
toStealthAddress: sa, |
||||
|
fromKeypair: fromKeypair |
||||
|
}); |
||||
|
sm.encrypt().encbuf.length.should.equal(113); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
describe('#decrypt', function() { |
||||
|
|
||||
|
it('should decrypt that which was encrypted', function() { |
||||
|
var sm = StealthMessage().set({ |
||||
|
messagebuf: messagebuf, |
||||
|
toStealthAddress: sa |
||||
|
}).encrypt(); |
||||
|
var messagebuf2 = StealthMessage().set({ |
||||
|
encbuf: sm.encbuf, |
||||
|
fromKeypair: sm.fromKeypair, |
||||
|
toStealthkey: sk |
||||
|
}).decrypt().messagebuf; |
||||
|
messagebuf2.toString('hex').should.equal(messagebuf.toString('hex')); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
describe('#isForMe', function() { |
||||
|
|
||||
|
it('should know that this message is for me', function() { |
||||
|
StealthMessage().set({ |
||||
|
encbuf: encbuf, |
||||
|
toStealthkey: sk, |
||||
|
fromKeypair: fromKeypair, |
||||
|
receiveAddress: Address().set({hashbuf: encbuf.slice(0, 20)}) |
||||
|
}).isForMe().should.equal(true); |
||||
|
}); |
||||
|
|
||||
|
it('should know that this message is not for me', function() { |
||||
|
StealthMessage().set({ |
||||
|
encbuf: encbuf, |
||||
|
toStealthkey: sk, |
||||
|
fromKeypair: fromKeypair, |
||||
|
receiveAddress: Address().set({hashbuf: encbuf.slice(0, 20)}) |
||||
|
}).isForMe().should.equal(true); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
}); |
Loading…
Reference in new issue