diff --git a/src/client/encrypt.js b/src/client/encrypt.js new file mode 100644 index 0000000..872dc63 --- /dev/null +++ b/src/client/encrypt.js @@ -0,0 +1,65 @@ +var crypto = require('crypto'); +var yggserver = require('yggdrasil').server({}); +var debug = require("../debug"); + +module.exports = function(client) { + client.once('encryption_begin', onEncryptionKeyRequest); + + function onEncryptionKeyRequest(packet) { + crypto.randomBytes(16, gotSharedSecret); + + function gotSharedSecret(err, sharedSecret) { + if(err) { + debug(err); + client.emit('error', err); + client.end(); + return; + } + if(haveCredentials) { + joinServerRequest(onJoinServerResponse); + } else { + if(packet.serverId != '-') { + debug('This server appears to be an online server and you are providing no password, the authentication will probably fail'); + } + sendEncryptionKeyResponse(); + } + + function onJoinServerResponse(err) { + if(err) { + client.emit('error', err); + client.end(); + } else { + sendEncryptionKeyResponse(); + } + } + + function joinServerRequest(cb) { + yggserver.join(accessToken, client.session.selectedProfile.id, + packet.serverId, sharedSecret, packet.publicKey, cb); + } + + function sendEncryptionKeyResponse() { + var pubKey = mcPubKeyToURsa(packet.publicKey); + var encryptedSharedSecretBuffer = pubKey.encrypt(sharedSecret, undefined, undefined, ursa.RSA_PKCS1_PADDING); + var encryptedVerifyTokenBuffer = pubKey.encrypt(packet.verifyToken, undefined, undefined, ursa.RSA_PKCS1_PADDING); + client.write('encryption_begin', { + sharedSecret: encryptedSharedSecretBuffer, + verifyToken: encryptedVerifyTokenBuffer + }); + client.setEncryption(sharedSecret); + } + } + } +}; + +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'); +} diff --git a/src/createClient.js b/src/createClient.js index 83dc1b7..1bba4e3 100644 --- a/src/createClient.js +++ b/src/createClient.js @@ -3,12 +3,11 @@ var net = require('net'); var dns = require('dns'); var Client = require('./client'); var assert = require('assert'); -var crypto = require('crypto'); var yggdrasil = require('yggdrasil')({}); -var yggserver = require('yggdrasil').server({}); var states = require("./states"); var debug = require("./debug"); var UUID = require('uuid-1345'); +var encrypt = require('./client/encrypt'); module.exports=createClient; @@ -47,7 +46,7 @@ function createClient(options) { var client = new Client(false,version.majorVersion); client.on('connect', onConnect); if(keepAlive) client.on('keep_alive', onKeepAlive); - client.once('encryption_begin', onEncryptionKeyRequest); + encrypt(client); client.once('success', onLogin); client.once("compress", onCompressionRequest); client.on("set_compression", onCompressionRequest); @@ -114,52 +113,6 @@ function createClient(options) { }); } - function onEncryptionKeyRequest(packet) { - crypto.randomBytes(16, gotSharedSecret); - - function gotSharedSecret(err, sharedSecret) { - if(err) { - debug(err); - client.emit('error', err); - client.end(); - return; - } - if(haveCredentials) { - joinServerRequest(onJoinServerResponse); - } else { - if(packet.serverId != '-') { - debug('This server appears to be an online server and you are providing no password, the authentication will probably fail'); - } - sendEncryptionKeyResponse(); - } - - function onJoinServerResponse(err) { - if(err) { - client.emit('error', err); - client.end(); - } else { - sendEncryptionKeyResponse(); - } - } - - function joinServerRequest(cb) { - yggserver.join(accessToken, client.session.selectedProfile.id, - packet.serverId, sharedSecret, packet.publicKey, cb); - } - - function sendEncryptionKeyResponse() { - var pubKey = mcPubKeyToURsa(packet.publicKey); - var encryptedSharedSecretBuffer = pubKey.encrypt(sharedSecret, undefined, undefined, ursa.RSA_PKCS1_PADDING); - var encryptedVerifyTokenBuffer = pubKey.encrypt(packet.verifyToken, undefined, undefined, ursa.RSA_PKCS1_PADDING); - client.write('encryption_begin', { - sharedSecret: encryptedSharedSecretBuffer, - verifyToken: encryptedVerifyTokenBuffer - }); - client.setEncryption(sharedSecret); - } - } - } - function onLogin(packet) { client.state = states.PLAY; client.uuid = packet.uuid;