successfully getting the encryption key response

This commit is contained in:
Andrew Kelley 2012-12-31 23:53:36 -05:00
parent 043cbd5882
commit 321a97acb4
3 changed files with 155 additions and 13 deletions

View File

@ -49,6 +49,7 @@ var writers = {
'int': IntWriter,
'byte': ByteWriter,
'string': StringWriter,
'byteArray': ByteArrayWriter,
};
var readers = {
@ -107,8 +108,19 @@ function StringWriter(value) {
StringWriter.prototype.write = function(buffer, offset) {
buffer.writeInt16BE(this.value.length, offset);
this.encoded.copy(buffer, offset + 2);
};
function ByteArrayWriter(value) {
assert.ok(Buffer.isBuffer(value), "non buffer passed to ByteArrayWriter");
this.value = value;
this.size = 2 + value.length;
}
ByteArrayWriter.prototype.write = function(buffer, offset) {
buffer.writeInt16BE(this.value.length, offset);
this.value.copy(buffer, offset + 2);
};
function ByteWriter(value) {
this.value = value;
this.size = 1;
@ -118,6 +130,15 @@ ByteWriter.prototype.write = function(buffer, offset) {
buffer.writeInt8(this.value, offset);
}
function UByteWriter(value) {
this.value = value;
this.size = 1;
}
UByteWriter.prototype.write = function(buffer, offset) {
buffer.writeUInt8(this.value, offset);
};
function IntWriter(value) {
this.value = value;
this.size = 4;
@ -129,11 +150,13 @@ IntWriter.prototype.write = function(buffer, offset) {
function createPacketBuffer(packetId, params) {
var size = 1;
var fields = [ new ByteWriter(packetId) ];
var fields = [ new UByteWriter(packetId) ];
var packet = packets[packetId];
packet.forEach(function(fieldInfo) {
var value = params[fieldInfo.name];
var field = new writers[fieldInfo.type](value);
var Writer = writers[fieldInfo.type];
assert.ok(Writer, "missing writer for data type: " + fieldInfo.type);
var field = new Writer(value);
size += field.size;
fields.push(field);
});
@ -171,3 +194,79 @@ function parsePacket(buffer) {
results: results,
};
}
// packet ids
Parser.KEEP_ALIVE = 0x00;
Parser.LOGIN_REQUEST = 0x01;
Parser.HANDSHAKE = 0x02;
Parser.CHAT_MESSAGE = 0x03;
Parser.TIME_UPDATE = 0x04;
Parser.ENTITY_EQUIPMENT = 0x05;
Parser.SPAWN_POSITION = 0x06;
Parser.USE_ENTITY = 0x07;
Parser.UPDATE_HEALTH = 0x08;
Parser.RESPAWN = 0x09;
Parser.PLAYER = 0x0A;
Parser.PLAYER_POSITION = 0x0B;
Parser.PLAYER_LOOK = 0x0C;
Parser.PLAYER_POSITION_AND_LOOK = 0x0D;
Parser.PLAYER_DIGGING = 0x0E;
Parser.PLAYER_BLOCK_PLACEMENT = 0x0F;
Parser.HELD_ITEM_CHANGE = 0x10;
Parser.USE_BED = 0x11;
Parser.ANIMATION = 0x12;
Parser.ENTITY_ACTION = 0x13;
Parser.SPAWN_NAMED_ENTITY = 0x14;
Parser.COLLECT_ITEM = 0x16;
Parser.SPAWN_OBJECT_VEHICLE = 0x17;
Parser.SPAWN_MOB = 0x18;
Parser.SPAWN_PAINTING = 0x19;
Parser.SPAWN_EXPERIENCE_ORB = 0x1A;
Parser.ENTITY_VELOCITY = 0x1C;
Parser.DESTROY_ENTITY = 0x1D;
Parser.ENTITY = 0x1E;
Parser.ENTITY_RELATIVE_MOVE = 0x1F;
Parser.ENTITY_LOOK = 0x20;
Parser.ENTITY_LOOK_AND_RELATIVE_MOVE = 0x21;
Parser.ENTITY_TELEPORT = 0x22;
Parser.ENTITY_HEAD_LOOK = 0x23;
Parser.ENTITY_STATUS = 0x26;
Parser.ATTACH_ENTITY = 0x27;
Parser.ENTITY_METADATA = 0x28;
Parser.ENTITY_EFFECT = 0x29;
Parser.REMOVE_ENTITY_EFFECT = 0x2A;
Parser.SET_EXPERIENCE = 0x2B;
Parser.CHUNK_DATA = 0x33;
Parser.MULTI_BLOCK_CHANGE = 0x34;
Parser.BLOCK_CHANGE = 0x35;
Parser.BLOCK_ACTION = 0x36;
Parser.BLOCK_BREAK_ANIMATION = 0x37;
Parser.MAP_CHUNK_BULK = 0x38;
Parser.EXPLOSION = 0x3C;
Parser.SOUND_OR_PARTICLE_EFFECT = 0x3D;
Parser.NAMED_SOUND_EFFECT = 0x3E;
Parser.CHANGE_GAME_STATE = 0x46;
Parser.SPAWN_GLOBAL_ENTITY = 0x47;
Parser.OPEN_WINDOW = 0x64;
Parser.CLOSE_WINDOW = 0x65;
Parser.CLICK_WINDOW = 0x66;
Parser.SET_SLOT = 0x67;
Parser.SET_WINDOW_ITEMS = 0x68;
Parser.UPDATE_WINDOW_PROPERTY = 0x69;
Parser.CONFIRM_TRANSACTION = 0x6A;
Parser.CREATIVE_INVENTORY_ACTION = 0x6B;
Parser.ENCHANT_ITEM = 0x6C;
Parser.UPDATE_SIGN = 0x82;
Parser.ITEM_DATA = 0x83;
Parser.UPDATE_TILE_ENTITY = 0x84;
Parser.INCREMENT_STATISTIC = 0xC8;
Parser.PLAYER_LIST_ITEM = 0xC9;
Parser.PLAYER_ABILITIES = 0xCA;
Parser.TAB_COMPLETE = 0xCB;
Parser.CLIENT_SETTINGS = 0xCC;
Parser.CLIENT_STATUSES = 0xCD;
Parser.PLUGIN_MESSAGE = 0xFA;
Parser.ENCRYPTION_KEY_RESPONSE = 0xFC;
Parser.ENCRYPTION_KEY_REQUEST = 0xFD;
Parser.SERVER_LIST_PING = 0xFE;
Parser.DISCONNECT_KICK = 0xFF;

View File

@ -17,6 +17,22 @@
"type": "int"
}
],
"205": [
{
"name": "payload",
"type": "byte"
}
],
"252": [
{
"name": "sharedSecret",
"type": "byteArray"
},
{
"name": "verifyToken",
"type": "byteArray"
}
],
"253": [
{
"name": "serverId",

49
test.js
View File

@ -1,9 +1,12 @@
var Parser = require('./lib/parser');
var Parser = require('./lib/parser')
, ursa = require('ursa')
, crypto = require('crypto')
, assert = require('assert')
var parser = new Parser();
parser.on('connect', function() {
console.info("connect");
parser.writePacket(0x02, {
parser.writePacket(Parser.HANDSHAKE, {
protocolVersion: 51,
userName: 'superjoe30',
serverHost: 'localhost',
@ -27,19 +30,43 @@ parser.on('end', function() {
parser.connect(25565, 'localhost');
var packetHandlers = {
0xFC: onEncryptionKeyResponse,
0xFD: onEncryptionKeyRequest,
};
function onEncryptionKeyRequest(packet) {
var sharedSecret = randomBuffer(16);
console.log("enc key request");
crypto.randomBytes(16, function (err, sharedSecret) {
assert.ifError(err);
var pubKey = mcPubKeyToURsa(packet.publicKey);
var encryptedSharedSecret = pubKey.encrypt(sharedSecret, 'binary', 'base64', ursa.RSA_PKCS1_PADDING);
var encryptedSharedSecretBuffer = new Buffer(encryptedSharedSecret, 'base64');
var encryptedVerifyToken = pubKey.encrypt(packet.verifyToken, 'binary', 'base64', ursa.RSA_PKCS1_PADDING);
var encryptedVerifyTokenBuffer = new Buffer(encryptedVerifyToken, 'base64');
console.log("write enc key response");
parser.writePacket(Parser.ENCRYPTION_KEY_RESPONSE, {
sharedSecret: encryptedSharedSecretBuffer,
verifyToken: encryptedVerifyTokenBuffer,
});
});
}
function randomBuffer(size) {
var buffer = new Buffer(size);
var i, number;
for (i = 0; i < size; ++i) {
number = Math.floor(Math.random() * 256);
buffer.writeUInt8(number, i);
}
return buffer;
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 });
}
function mcPubKeyToURsa(mcPubKeyBuffer) {
var pem = "-----BEGIN PUBLIC KEY-----\n";
var base64PubKey = mcPubKeyBuffer.toString('base64');
var maxLineLength = 65;
while (base64PubKey.length > 0) {
pem += base64PubKey.substring(0, maxLineLength) + "\n";
base64PubKey = base64PubKey.substring(maxLineLength);
}
pem += "-----END PUBLIC KEY-----\n";
return ursa.createPublicKey(pem, 'utf8');
}