diff --git a/lib/common/service/sessionService.js b/lib/common/service/sessionService.js index d21acf7b1..0b54e1539 100644 --- a/lib/common/service/sessionService.js +++ b/lib/common/service/sessionService.js @@ -1,4 +1,5 @@ var EventEmitter = require('events').EventEmitter; +var crypto = require('crypto') var util = require('util'); var logger = require('pomelo-logger').getLogger('pomelo', __filename); var utils = require('../../util/utils'); @@ -514,6 +515,10 @@ Session.prototype.get = function(key) { * @param {Object} msg final message sent to client */ Session.prototype.send = function(msg) { + if(!!this.__socket__.__serverSecret){ + var cipher = crypto.createCipher('rc4', this.__socket__.__serverSecret); + msg = cipher.update(msg); + } this.__socket__.send(msg); }; @@ -523,6 +528,14 @@ Session.prototype.send = function(msg) { * @param {Array} msgs list of message */ Session.prototype.sendBatch = function(msgs) { + if(!!this.__socket__.__serverSecret){ + for(var i = 0; i < msgs.length; i ++){ + var msg = msgs[i]; + var cipher = crypto.createCipher('rc4', this.__socket__.__serverSecret); + msg = cipher.update(msg); + msgs[i] = msg; + } + } this.__socket__.sendBatch(msgs); }; diff --git a/lib/components/connector.js b/lib/components/connector.js index f2906f54b..3bf694511 100644 --- a/lib/components/connector.js +++ b/lib/components/connector.js @@ -1,3 +1,4 @@ +var crypto = require('crypto') var logger = require('pomelo-logger').getLogger('pomelo', __filename); var taskManager = require('../common/manager/taskManager'); var pomelo = require('../pomelo'); @@ -216,6 +217,10 @@ var bindEvents = function(self, socket) { // new message socket.on('message', function(msg) { + if(!!socket.__serverSecret){ + var decipher = crypto.createDecipher('rc4', socket.__serverSecret); + msg.body = decipher.update(msg.body); + } var dmsg = msg; if(self.decode) { dmsg = self.decode.call(self, msg, session); diff --git a/lib/connectors/commands/handshake.js b/lib/connectors/commands/handshake.js index 63b0b6088..a8a95c8ed 100644 --- a/lib/connectors/commands/handshake.js +++ b/lib/connectors/commands/handshake.js @@ -1,5 +1,6 @@ var pomelo = require('../../pomelo'); var Package = require('pomelo-protocol').Package; +var crypto = require('crypto') var CODE_OK = 200; var CODE_USE_ERROR = 500; @@ -27,6 +28,7 @@ var Command = function(opts) { this.useDict = opts.useDict; this.useProtobuf = opts.useProtobuf; this.useCrypto = opts.useCrypto; + this.useCrypto2 = opts.useCrypto2; }; module.exports = Command; @@ -85,6 +87,25 @@ Command.prototype.handle = function(socket, msg) { pomelo.app.components.__connector__.setPubKey(socket.id, msg.sys.rsa); } + if(this.useCrypto2){ + if(!msg.sys.clientKey || 'string' !== typeof msg.sys.clientKey || msg.sys.clientKey.trim().length === 0){ + return processError(socket, CODE_USE_ERROR); + } + var clientKey = msg.sys.clientKey; + var challenge = crypto.randomBytes(8).toString('base64'); + var serverDiff = crypto.getDiffieHellman('modp1'); + serverDiff.generateKeys(); + var serverKey = serverDiff.getPublicKey('base64'); + var serverSecret = serverDiff.computeSecret(clientKey, 'base64', 'base64'); + opts.crypto2 = true; + opts.serverKey = serverKey; + opts.challenge = challenge; + socket.__serverSecret = serverSecret; + var cipher = crypto.createCipher('rc4', serverSecret); + var rc4 = cipher.update(challenge, 'utf8', 'base64'); + rc4 += cipher.final('base64'); + socket.__challenge = rc4; + } if(typeof this.userHandshake === 'function') { this.userHandshake(msg, function(err, resp) { if(err) { diff --git a/lib/connectors/common/handler.js b/lib/connectors/common/handler.js index e29aa9de0..cb760c3ee 100644 --- a/lib/connectors/common/handler.js +++ b/lib/connectors/common/handler.js @@ -25,6 +25,17 @@ var handleHandshakeAck = function(socket, pkg) { return; } socket.state = ST_WORKING; + if(socket.__serverSecret){ + try{ + var body = JSON.parse(protocol.strdecode(pkg.body)); + if(!body || body.challenge !== socket.__challenge){ + return socket.emit('error', new Error('challenge failed')) + } + }catch(e){ + return socket.emit('error', new Error('challenge failed')) + } + delete socket.__challenge; + } socket.emit('heartbeat'); };