From a10e2b4a433315a5787deb10f8dea6a6b4148db0 Mon Sep 17 00:00:00 2001 From: Rainer Koirikivi Date: Sun, 2 Nov 2014 16:39:40 +0200 Subject: [PATCH] Add support for verifymessage /api/messages/verify accepts three parameters either via JSON POST data or GET query parameters, pipes them to the bitcoin RPCs verifymessage command, and returns the result for the user. --- app/controllers/messages.js | 27 +++++++++++ config/routes.js | 5 ++ lib/Rpc.js | 12 +++++ test/integration/messages.js | 90 ++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 app/controllers/messages.js create mode 100644 test/integration/messages.js diff --git a/app/controllers/messages.js b/app/controllers/messages.js new file mode 100644 index 0000000..5c2fbfc --- /dev/null +++ b/app/controllers/messages.js @@ -0,0 +1,27 @@ +'use strict'; + +var common = require('./common'); +var Rpc = require('../../lib/Rpc'); + + +exports.verify = function(req, res) { + var address = req.param('address'), + signature = req.param('signature'), + message = req.param('message'); + + if(typeof(address) == 'undefined' + || typeof(signature) == 'undefined' + || typeof(message) == 'undefined') { + return common.handleErrors({ + message: 'Missing parameters (expected "address", "signature" and "message")', + code: 1 + }, res); + } + + Rpc.verifyMessage(address, signature, message, function(err, result) { + if (err) { + return common.handleErrors(err, res); + } + res.json({'result' : result}); + }); +}; diff --git a/config/routes.js b/config/routes.js index 36efa23..c99ed8e 100644 --- a/config/routes.js +++ b/config/routes.js @@ -60,6 +60,11 @@ module.exports = function(app) { app.get(apiPrefix + '/email/validate', emailPlugin.validate); } + // Address routes + var messages = require('../app/controllers/messages'); + app.get(apiPrefix + '/messages/verify', messages.verify); + app.post(apiPrefix + '/messages/verify', messages.verify); + //Home route var index = require('../app/controllers/index'); app.get(apiPrefix + '/version', index.version); diff --git a/lib/Rpc.js b/lib/Rpc.js index a71c396..50f41cc 100644 --- a/lib/Rpc.js +++ b/lib/Rpc.js @@ -106,6 +106,18 @@ Rpc.sendRawTransaction = function(rawtx, cb) { }); }; +Rpc.verifyMessage = function(address, signature, message, cb) { + var self = this; + bitcoreRpc.verifyMessage(address, signature, message, function(err, message) { + if (err && (err.code === -3 || err.code === -5)) + return cb(err); // -3 = invalid address, -5 = malformed base64 / etc. + if (err) + return cb(self.errMsg(err)); + + return cb(err, message.result); + }); +}; + module.exports = require('soop')(Rpc); diff --git a/test/integration/messages.js b/test/integration/messages.js new file mode 100644 index 0000000..d51ccba --- /dev/null +++ b/test/integration/messages.js @@ -0,0 +1,90 @@ +#!/usr/bin/env node +'use strict'; + +process.env.NODE_ENV = process.env.NODE_ENV || 'development'; + +var assert = require('assert'), + config = require('../../config/config'), + messages = require('../../app/controllers/messages'), + correctMessage = 'test2', + correctAddress, + correctSignature; + +if(config.network === 'livenet') { + correctAddress = '16Q7eRty2LrpAWvP3VTtaXXCMZj2v4xm57', + correctSignature = 'HERpcxkyOezkBPPwvUUAaxYXR/9X/8eyVjp8WKGYl7Aw8' + + 'pMsiMXDWXf8G1t/SOUEWy94I+KA/SrBKYs2LfIHA0Q='; +} else { + correctAddress = 'mhtJo5nZLcreM5Arrf8EDABpCevp2MfmCW', + correctSignature = 'G/y2UhjZ4qBPLQGmOhl/4p/EIwTHIO1iq95kPxDk9RjYr' + + '1JKL6dsCSuhXat7VLTGwAM3PdgRh/jwGxi6x6dNeSE='; +} + +function createMockReq(body) { + // create a simplified mock of express' request object, suitable for the + // needs of test cases in this file + return { + body: body, + param: function(name) { + return this.body[name]; + } + }; +} + +describe('messages.verify', function() { + + it('should return true with correct message', function(done) { + var mockReq = createMockReq({ + address: correctAddress, + signature: correctSignature, + message: correctMessage + }); + var mockRes = { + json: function(data) { + assert.deepEqual(data, { + result: true, + }); + done(); + } + }; + messages.verify(mockReq, mockRes); + }); + + it('should return false with incorrect message', function(done) { + var mockReq = createMockReq({ + address: correctAddress, + signature: correctSignature, + message: 'NOPE' + }); + var mockRes = { + json: function(data) { + assert.deepEqual(data, { + result: false, + }); + done(); + } + }; + + messages.verify(mockReq, mockRes); + }); + + it('should return error with incorrect parameters', function(done) { + var mockReq = createMockReq({ + address: correctAddress, + message: correctMessage + }); + var mockRes = { + status: function(code) { + assert.equal(code, 400); + return this; + }, + send: function(data) { + assert.ok(data.match(/^Missing parameters/), + "Match not found, got '" + data + "' instead") + done(); + } + }; + messages.verify(mockReq, mockRes); + }); + +});