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.
88 lines
2.3 KiB
JavaScript
88 lines
2.3 KiB
JavaScript
var Stealthkey = require('./stealthkey');
|
|
var Base58check = require('../base58check');
|
|
var Pubkey = require('../pubkey');
|
|
var KDF = require('../kdf');
|
|
|
|
var StealthAddress = function StealthAddress(addrstr) {
|
|
if (!(this instanceof StealthAddress))
|
|
return new StealthAddress(addrstr);
|
|
|
|
if (typeof addrstr === 'string') {
|
|
this.fromString(addrstr)
|
|
}
|
|
else if (Buffer.isBuffer(addrstr)) {
|
|
var buf = addrstr;
|
|
this.fromBuffer(buf);
|
|
}
|
|
else if (addrstr) {
|
|
var obj = addrstr;
|
|
this.set(obj);
|
|
}
|
|
};
|
|
|
|
StealthAddress.prototype.set = function(obj) {
|
|
this.payloadPubkey = obj.payloadPubkey || this.payloadPubkey;
|
|
this.scanPubkey = obj.scanPubkey || this.scanPubkey;
|
|
return this;
|
|
};
|
|
|
|
StealthAddress.prototype.fromStealthkey = function(stealthkey) {
|
|
this.set({
|
|
payloadPubkey: stealthkey.payloadKeypair.pubkey,
|
|
scanPubkey: stealthkey.scanKeypair.pubkey
|
|
});
|
|
return this;
|
|
};
|
|
|
|
StealthAddress.prototype.fromBuffer = function(buf) {
|
|
if (!Buffer.isBuffer(buf) || buf.length !== 66)
|
|
throw new Error('stealthkey: A stealth address must have length 66');
|
|
|
|
var pPubBuf = buf.slice(0, 33);
|
|
var sPubBuf = buf.slice(33, 66);
|
|
|
|
this.payloadPubkey = Pubkey().fromDER(pPubBuf);
|
|
this.scanPubkey = Pubkey().fromDER(sPubBuf);
|
|
|
|
return this;
|
|
};
|
|
|
|
StealthAddress.prototype.fromString = function(str) {
|
|
var buf = Base58check.decode(str);
|
|
this.fromBuffer(buf);
|
|
|
|
return this;
|
|
};
|
|
|
|
StealthAddress.prototype.getSharedKeypair = function(senderKeypair) {
|
|
var sharedSecretPoint = this.scanPubkey.point.mul(senderKeypair.privkey.bn);
|
|
var sharedSecretPubkey = Pubkey(sharedSecretPoint);
|
|
var buf = sharedSecretPubkey.toDER(true);
|
|
var sharedKeypair = KDF.sha256hmac2keypair(buf);
|
|
|
|
return sharedKeypair;
|
|
};
|
|
|
|
StealthAddress.prototype.getReceivePubkey = function(senderKeypair) {
|
|
var sharedKeypair = this.getSharedKeypair(senderKeypair);
|
|
var pubkey = Pubkey(this.scanPubkey.point.add(sharedKeypair.pubkey.point).add(this.payloadPubkey.point));
|
|
|
|
return pubkey;
|
|
};
|
|
|
|
StealthAddress.prototype.toBuffer = function() {
|
|
var pBuf = this.payloadPubkey.toDER(true);
|
|
var sBuf = this.scanPubkey.toDER(true);
|
|
|
|
return Buffer.concat([pBuf, sBuf]);
|
|
};
|
|
|
|
StealthAddress.prototype.toString = function() {
|
|
var buf = this.toBuffer();
|
|
var b58 = Base58check.encode(buf);
|
|
|
|
return b58;
|
|
};
|
|
|
|
module.exports = StealthAddress;
|