From 3bc30a97b5e5b43b8165b2031cf962212a3aa7dc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 1 Jan 2013 01:49:38 -0500 Subject: [PATCH] AES encryption/decryption working. now getting kicked for not verifying username --- lib/parser.js | 11 ++++++++++- packets.json | 36 ++++++++++++++++++++++++++++++++++++ test.js | 16 ++++++++++++++-- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/lib/parser.js b/lib/parser.js index dc0d98a..12473a3 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -11,6 +11,11 @@ module.exports = Parser; function Parser(options) { EventEmitter.call(this); + + this.client = null; + this.encryptionEnabled = false; + this.cipher = null; + this.decipher = null; } util.inherits(Parser, EventEmitter); @@ -21,6 +26,7 @@ Parser.prototype.connect = function(port, host) { }); var incomingBuffer = new Buffer(0); self.client.on('data', function(data) { + if (self.encryptionEnabled) data = new Buffer(self.decipher.update(data), 'binary'); incomingBuffer = Buffer.concat([incomingBuffer, data]); var parsed; while (true) { @@ -42,7 +48,9 @@ Parser.prototype.connect = function(port, host) { Parser.prototype.writePacket = function(packetId, params) { var buffer = createPacketBuffer(packetId, params); - this.client.write(buffer); + var out = this.encryptionEnabled ? new Buffer(this.cipher.update(buffer), 'binary') : buffer; + if (this.encryptionEnabled) console.log("writing", packetId, "packet with encryption"); + this.client.write(out); }; var writers = { @@ -180,6 +188,7 @@ function parsePacket(buffer) { for (i = 0; i < packetInfo.length; ++i) { fieldInfo = packetInfo[i]; read = readers[fieldInfo.type]; + assert.ok(read, "missing reader for data type: " + fieldInfo.type); readResults = read(buffer, size); if (readResults) { results[fieldInfo.name] = readResults.value; diff --git a/packets.json b/packets.json index 62a5dba..b9e54f9 100644 --- a/packets.json +++ b/packets.json @@ -1,4 +1,34 @@ { + "1": [ + { + "name": "entityId", + "type": "int" + }, + { + "name": "levelType", + "type": "string" + }, + { + "name": "gameMode", + "type": "byte" + }, + { + "name": "dimension", + "type": "byte" + }, + { + "name": "difficulty", + "type": "byte" + }, + { + "name": "_notUsed1", + "type": "byte" + }, + { + "name": "maxPlayers", + "type": "byte" + } + ], "2": [ { "name": "protocolVersion", @@ -46,5 +76,11 @@ "name": "verifyToken", "type": "byteArray" } + ], + "255": [ + { + "name": "reason", + "type": "string" + } ] } diff --git a/test.js b/test.js index 1b8f95e..701e5e2 100644 --- a/test.js +++ b/test.js @@ -32,8 +32,18 @@ parser.connect(25565, 'localhost'); var packetHandlers = { 0xFC: onEncryptionKeyResponse, 0xFD: onEncryptionKeyRequest, + 0x01: onLoginRequest, + 0xFF: onKick, }; +function onKick(packet) { + console.log("kick", packet); +} + +function onLoginRequest(packet) { + console.log("login request", packet); +} + function onEncryptionKeyRequest(packet) { console.log("enc key request"); crypto.randomBytes(16, function (err, sharedSecret) { @@ -43,6 +53,8 @@ function onEncryptionKeyRequest(packet) { var encryptedSharedSecretBuffer = new Buffer(encryptedSharedSecret, 'base64'); var encryptedVerifyToken = pubKey.encrypt(packet.verifyToken, 'binary', 'base64', ursa.RSA_PKCS1_PADDING); var encryptedVerifyTokenBuffer = new Buffer(encryptedVerifyToken, 'base64'); + parser.cipher = crypto.createCipheriv('aes-128-cfb8', sharedSecret, sharedSecret); + parser.decipher = crypto.createDecipheriv('aes-128-cfb8', sharedSecret, sharedSecret); console.log("write enc key response"); parser.writePacket(Parser.ENCRYPTION_KEY_RESPONSE, { sharedSecret: encryptedSharedSecretBuffer, @@ -55,8 +67,8 @@ function onEncryptionKeyResponse(packet) { console.log("confirmation enc key response"); assert.strictEqual(packet.sharedSecret.length, 0); assert.strictEqual(packet.verifyToken.length, 0); - // TODO: enable AES encryption, then we can do the below line - //parser.writePacket(Parser.CLIENT_STATUSES, { payload: 0 }); + parser.encryptionEnabled = true; + parser.writePacket(Parser.CLIENT_STATUSES, { payload: 0 }); } function mcPubKeyToURsa(mcPubKeyBuffer) {