diff --git a/lib/address.js b/lib/address.js index ff1ffa9..c124cbc 100644 --- a/lib/address.js +++ b/lib/address.js @@ -4,6 +4,8 @@ var Hash = require('./hash'); var Pubkey = require('./pubkey'); function Address(hashbuf, network, type) { + if (!(this instanceof Address)) + return new Address(hashbuf, network, type); this.hashbuf = hashbuf; this.network = network; this.type = type; diff --git a/lib/ecdsa.js b/lib/ecdsa.js index 53959a3..ea62070 100644 --- a/lib/ecdsa.js +++ b/lib/ecdsa.js @@ -21,7 +21,6 @@ ECDSA.prototype.calci = function() { try { var Qprime = this.sig2pubkey(); } catch (e) { - console.log(e); continue; } @@ -140,7 +139,10 @@ ECDSA.prototype.sign = function() { var k = this.k; var d = privkey.bn; - if (!hashbuf || !privkey || !k || !d) + if (!k) + throw new Error('You must specify k - perhaps you should run signRandomK instead'); + + if (!hashbuf || !privkey || !d) throw new Error('invalid parameters'); var N = Point.getN(); diff --git a/lib/message.js b/lib/message.js new file mode 100644 index 0000000..bb36f11 --- /dev/null +++ b/lib/message.js @@ -0,0 +1,90 @@ +var ECDSA = require('./ecdsa'); +var Key = require('./key'); +var Privkey = require('./privkey'); +var Pubkey = require('./pubkey'); +var BufferWriter = require('./bufferwriter'); +var Hash = require('./hash'); +var Address = require('./address'); + +var Message = function Message(messagebuf, key, sig, address, verified) { + if (!(this instanceof Message)) + return new Message(messagebuf, key, sig); + this.messagebuf = messagebuf; + this.key = key; + this.sig = sig; + this.address = address; + this.verified = verified; +}; + +Message.magicBytes = new Buffer('Bitcoin Signed Message:\n'); + +Message.magicHash = function(messagebuf) { + if (!Buffer.isBuffer(messagebuf)) + throw new Error('messagebuf must be a buffer'); + var bw = new BufferWriter(); + bw.writeVarInt(Message.magicBytes.length); + bw.write(Message.magicBytes); + bw.writeVarInt(messagebuf.length); + bw.write(messagebuf); + var buf = bw.concat(); + + var hashbuf = Hash.sha256sha256(buf); + + return hashbuf; +}; + +Message.prototype.sign = function() { + var hashbuf = Message.magicHash(this.messagebuf); + var ecdsa = ECDSA(hashbuf, this.key); + ecdsa.signRandomK(); + ecdsa.calci(); + this.sig = ecdsa.sig; + return this; +}; + +/* +Message.sign = function(messagebuf, key) { + var m = Message(messagebuf, key); + var sig = m.sign(); + var sigbuf = sig.toCompressed(); + var base64 = sigbuf.toString('base64'); + return base64; +}; +*/ + +Message.prototype.verify = function() { + var hashbuf = Message.magicHash(this.messagebuf); + + var ecdsa = new ECDSA(); + ecdsa.hashbuf = hashbuf; + ecdsa.sig = this.sig; + ecdsa.key = new Key(); + ecdsa.key.pubkey = ecdsa.sig2pubkey(); + + if (!ecdsa.verify()) { + console.log(ecdsa.sigError()); + this.verified = false; + return this; + } + + var address = Address().fromPubkey(ecdsa.key.pubkey); + //TODO: what if livenet/testnet mismatch? + if (address.hashbuf.toString('hex') === this.address.hashbuf.toString('hex')) + this.verified = true; + else + this.verified = false; + + return this; +}; + +/* +Message.verify = function(messagebuf, sigstr, address) { + var sigbuf = new Buffer(sigstr, 'base64'); + var message = new Message(); + message.messagebuf = messagebuf; + message.sig = Signature().fromCompressed(sigbuf); + message.address = address; +}; +*/ + +module.exports = Message; diff --git a/test/test.message.js b/test/test.message.js new file mode 100644 index 0000000..34f9063 --- /dev/null +++ b/test/test.message.js @@ -0,0 +1,49 @@ +var Address = require('../lib/address'); +var Message = require('../lib/message'); +var Key = require('../lib/key'); +var should = require('chai').should(); + +describe('Message', function() { + + it('should make a new message', function() { + var message = new Message(); + should.exist(message); + }); + + it('should make a new message when called without "new"', function() { + var message = Message(); + should.exist(message); + }); + + describe('#sign', function() { + var messagebuf = new Buffer('this is my message'); + var key = Key().fromRandom(); + + it('should sign a message', function() { + var message = new Message(); + message.messagebuf = messagebuf; + message.key = key; + message.sign(); + var sig = message.sig; + should.exist(sig); + }); + + }); + + describe('#verify', function() { + var messagebuf = new Buffer('this is my message'); + var key = Key().fromRandom(); + + it('should verify a message that was just signed', function() { + var message = new Message(); + message.messagebuf = messagebuf; + message.key = key; + message.address = Address().fromPubkey(key.pubkey); + message.sign(); + message.verify(); + message.verified.should.equal(true); + }); + + }); + +});