diff --git a/lib/message.js b/lib/message.js index d370fc7..f9433c6 100644 --- a/lib/message.js +++ b/lib/message.js @@ -1,6 +1,7 @@ 'use strict'; var bitcore = require('bitcore'); +var _ = require('lodash'); var PrivateKey = bitcore.PrivateKey; var PublicKey = bitcore.PublicKey; var Address = bitcore.Address; @@ -9,20 +10,19 @@ var ECDSA = bitcore.crypto.ECDSA; var Signature = bitcore.crypto.Signature; var sha256sha256 = bitcore.crypto.Hash.sha256sha256; var JSUtil = bitcore.util.js; +var $ = bitcore.util.preconditions; /** - * Will construct a new message to sign and verify. - * + * constructs a new message to sign and verify. + * * @param {String} message * @returns {Message} */ var Message = function Message(message) { if (!(this instanceof Message)) { return new Message(message); - } - if (typeof message !== 'string') { - throw new TypeError('First argument should be a string'); } + $.checkArgument(_.isString(message), 'First argument should be a string'); this.message = message; return this; @@ -40,9 +40,8 @@ Message.prototype.magicHash = function magicHash() { }; Message.prototype._sign = function _sign(privateKey) { - if (!(privateKey instanceof PrivateKey)) { - throw new TypeError('First argument should be an instance of PrivateKey'); - } + $.checkArgument(privateKey instanceof PrivateKey, + 'First argument should be an instance of PrivateKey'); var hash = this.magicHash(); var ecdsa = new ECDSA(); ecdsa.hashbuf = hash; @@ -55,7 +54,7 @@ Message.prototype._sign = function _sign(privateKey) { /** * Will sign a message with a given bitcoin private key. - * + * * @param {PrivateKey} privateKey - An instance of PrivateKey * @returns {String} A base64 encoded compact signature */ @@ -65,12 +64,8 @@ Message.prototype.sign = function sign(privateKey) { }; Message.prototype._verify = function _verify(publicKey, signature) { - if (!(publicKey instanceof PublicKey)) { - throw new TypeError('First argument should be an instance of PublicKey'); - } - if (!(signature instanceof Signature)) { - throw new TypeError('Second argument should be an instance of Signature'); - } + $.checkArgument(publicKey instanceof PublicKey, 'First argument should be an instance of PublicKey'); + $.checkArgument(signature instanceof Signature, 'Second argument should be an instance of Signature'); var hash = this.magicHash(); var verified = ECDSA.verify(hash, signature, publicKey); if (!verified) { @@ -82,12 +77,18 @@ Message.prototype._verify = function _verify(publicKey, signature) { /** * Will return a boolean of the signature is valid for a given bitcoin address. * If it isn't the specific reason is accessible via the "error" member. - * - * @param {String} bitcoinAddress - A bitcoin address + * + * @param {Address|String} bitcoinAddress - A bitcoin address * @param {String} signatureString - A base64 encoded compact signature * @returns {Boolean} */ Message.prototype.verify = function verify(bitcoinAddress, signatureString) { + $.checkArgument(bitcoinAddress); + $.checkArgument(signatureString && _.isString(signatureString)); + + if (_.isString(bitcoinAddress)) { + bitcoinAddress = Address.fromString(bitcoinAddress); + } var signature = Signature.fromCompact(new Buffer(signatureString, 'base64')); // recover the public key @@ -96,11 +97,10 @@ Message.prototype.verify = function verify(bitcoinAddress, signatureString) { ecdsa.sig = signature; var publicKey = ecdsa.toPublicKey(); - var expectedAddress = Address.fromString(bitcoinAddress); - var signatureAddress = Address.fromPublicKey(publicKey, expectedAddress.network); + var signatureAddress = Address.fromPublicKey(publicKey, bitcoinAddress.network); // check that the recovered address and specified address match - if (expectedAddress.toString() !== signatureAddress.toString()) { + if (bitcoinAddress.toString() !== signatureAddress.toString()) { this.error = 'The signature did not match the message digest'; return false; } diff --git a/package.json b/package.json index 422912b..460b6aa 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "url": "https://github.com/bitpay/bitcore-message.git" }, "dependencies": { - "bitcore": "^0.9.4" + "bitcore": "^0.9.4", + "lodash": "^3.1.0" }, "devDependencies": { "bitcore-build": "bitpay/bitcore-build", diff --git a/test/message.js b/test/message.js index 6143b8e..7a51985 100644 --- a/test/message.js +++ b/test/message.js @@ -5,6 +5,7 @@ var expect = chai.expect; var should = chai.should(); var bitcore = require('bitcore'); +var Address = bitcore.Address; var Signature = bitcore.crypto.Signature; var Message = require('../'); @@ -24,9 +25,9 @@ describe('Message', function() { var publicKey = privateKey.toPublicKey(); it('will error with incorrect message type', function() { - expect(function(){ + expect(function() { return new Message(new Date()); - }).to.throw(TypeError); + }).to.throw('First argument should be a string'); }); it('will instantiate without "new"', function() { @@ -46,10 +47,10 @@ describe('Message', function() { }); it('sign will error with incorrect private key argument', function() { - expect(function(){ + expect(function() { var message3 = new Message(text); return message3.sign('not a private key'); - }).to.throw(TypeError); + }).to.throw('First argument should be an instance of PrivateKey'); }); it('can verify a message with signature', function() { @@ -65,17 +66,17 @@ describe('Message', function() { }); it('verify will error with incorrect public key argument', function() { - expect(function(){ + expect(function() { var message6 = new Message(text); return message6._verify('not a public key', signature); - }).to.throw(TypeError); + }).to.throw('First argument should be an instance of PublicKey'); }); it('verify will error with incorrect signature argument', function() { - expect(function(){ + expect(function() { var message7 = new Message(text); return message7._verify(publicKey, 'not a signature'); - }).to.throw(TypeError); + }).to.throw('Second argument should be an instance of Signature'); }); it('verify will correctly identify a bad signature', function() { @@ -146,5 +147,10 @@ describe('Message', function() { }); + it('accepts Address for verification', function() { + var verified = Message(text) + .verify(new Address(address), signatureString); + verified.should.equal(true); + }); });