From b8f6ab4ed387157701730dbb9d88c9e3fec378a7 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Tue, 11 May 2021 21:09:35 -0400 Subject: [PATCH 1/3] Remove crypto deps Use node crypto lib --- package.json | 4 +-- src/auth/encryption.js | 72 ++++++++++++----------------------------- src/auth/login.js | 20 +++++------- src/auth/loginVerify.js | 24 ++++---------- 4 files changed, 37 insertions(+), 83 deletions(-) diff --git a/package.json b/package.json index 589ad5e..1022e71 100644 --- a/package.json +++ b/package.json @@ -23,11 +23,9 @@ "dependencies": { "@azure/msal-node": "^1.0.0-beta.6", "@xboxreplay/xboxlive-auth": "^3.3.3", - "asn1": "^0.2.4", "debug": "^4.3.1", - "ec-pem": "^0.18.0", "jsonwebtoken": "^8.5.1", - "jsp-raknet": "^2.0.0", + "jsp-raknet": "^2.1.0", "minecraft-folder-path": "^1.1.0", "node-fetch": "^2.6.1", "prismarine-nbt": "^1.5.0", diff --git a/src/auth/encryption.js b/src/auth/encryption.js index 95d87b1..2656a99 100644 --- a/src/auth/encryption.js +++ b/src/auth/encryption.js @@ -1,27 +1,26 @@ -const { Ber } = require('asn1') const { ClientStatus } = require('../connection') const JWT = require('jsonwebtoken') const crypto = require('crypto') -const ecPem = require('ec-pem') const debug = require('debug')('minecraft-protocol') const SALT = '🧂' const curve = 'secp384r1' +const pem = { format: 'pem', type: 'sec1' } +const der = { format: 'der', type: 'spki' } function Encrypt (client, server, options) { - client.ecdhKeyPair = crypto.createECDH(curve) - client.ecdhKeyPair.generateKeys() - client.clientX509 = writeX509PublicKey(client.ecdhKeyPair.getPublicKey()) + client.ecdhKeyPair = crypto.generateKeyPairSync('ec', { namedCurve: curve }) + client.publicKeyDER = client.ecdhKeyPair.publicKey.export(der) + client.privateKeyPEM = client.ecdhKeyPair.privateKey.export(pem) + console.log(client.publicKeyPEM) + client.clientX509 = client.publicKeyDER.toString('base64') function startClientboundEncryption (publicKey) { debug('[encrypt] Client pub key base64: ', publicKey) - const pubKeyBuf = readX509PublicKey(publicKey.key) - const alice = client.ecdhKeyPair - const alicePEM = ecPem(alice, curve) // https://github.com/nodejs/node/issues/15116#issuecomment-384790125 - const alicePEMPrivate = alicePEM.encodePrivateKey() + const pubKeyDer = crypto.createPublicKey({ key: Buffer.from(publicKey.key, 'base64'), ...der }) // Shared secret from the client's public key + our private key - client.sharedSecret = alice.computeSecret(pubKeyBuf) + client.sharedSecret = crypto.diffieHellman({ privateKey: client.ecdhKeyPair.privateKey, publicKey: pubKeyDer }) // Secret hash we use for packet encryption: // From the public key of the remote and the private key @@ -36,15 +35,12 @@ function Encrypt (client, server, options) { client.secretKeyBytes = secretHash.digest() // console.log('[encrypt] Shared hash', client.secretKeyBytes) - const x509 = writeX509PublicKey(alice.getPublicKey()) const token = JWT.sign({ salt: toBase64(SALT), - signedToken: alice.getPublicKey('base64') - }, alicePEMPrivate, { algorithm: 'ES384', header: { x5u: x509 } }) + signedToken: client.clientX509 + }, client.ecdhKeyPair.privateKey, { algorithm: 'ES384', header: { x5u: client.clientX509 } }) - client.write('server_to_client_handshake', { - token: token - }) + client.write('server_to_client_handshake', { token }) // The encryption scheme is AES/CFB8/NoPadding with the // secret key being the result of the sha256 above and @@ -57,28 +53,27 @@ function Encrypt (client, server, options) { debug('[encrypt] Starting serverbound encryption', token) const jwt = token?.token if (!jwt) { - // TODO: allow connecting to servers without encryption throw Error('Server did not return a valid JWT, cannot start encryption!') } + // TODO: Should we do some JWT signature validation here? Seems pointless - const alice = client.ecdhKeyPair + const [header, payload] = jwt.split('.').map(k => Buffer.from(k, 'base64')) const head = JSON.parse(String(header)) const body = JSON.parse(String(payload)) - const serverPublicKey = readX509PublicKey(head.x5u) - client.sharedSecret = alice.computeSecret(serverPublicKey) - // console.log('[encrypt] Shared secret', client.sharedSecret) + + const pubKeyDer = crypto.createPublicKey({ key: Buffer.from(head.x5u, 'base64'), ...der }) + // Shared secret from the client's public key + our private key + client.sharedSecret = crypto.diffieHellman({ privateKey: client.ecdhKeyPair.privateKey, publicKey: pubKeyDer }) const salt = Buffer.from(body.salt, 'base64') - const secretHash = crypto.createHash('sha256') secretHash.update(salt) secretHash.update(client.sharedSecret) client.secretKeyBytes = secretHash.digest() - // console.log('[encrypt] Shared hash', client.secretKeyBytes) - const initial = client.secretKeyBytes.slice(0, 16) - client.startEncryption(initial) + const iv = client.secretKeyBytes.slice(0, 16) + client.startEncryption(iv) // It works! First encrypted packet :) client.write('client_to_server_handshake', {}) @@ -94,29 +89,4 @@ function toBase64 (string) { return Buffer.from(string).toString('base64') } -function readX509PublicKey (key) { - const reader = new Ber.Reader(Buffer.from(key, 'base64')) - reader.readSequence() - reader.readSequence() - reader.readOID() // Hey, I'm an elliptic curve - reader.readOID() // This contains the curve type, could be useful - return Buffer.from(reader.readString(Ber.BitString, true)).slice(1) -} - -function writeX509PublicKey (key) { - const writer = new Ber.Writer() - writer.startSequence() - writer.startSequence() - writer.writeOID('1.2.840.10045.2.1') - writer.writeOID('1.3.132.0.34') - writer.endSequence() - writer.writeBuffer(Buffer.concat([Buffer.from([0x00]), key]), Ber.BitString) - writer.endSequence() - return writer.buffer.toString('base64') -} - -module.exports = { - readX509PublicKey, - writeX509PublicKey, - Encrypt -} +module.exports = { Encrypt } diff --git a/src/auth/login.js b/src/auth/login.js index afa74fb..c55665c 100644 --- a/src/auth/login.js +++ b/src/auth/login.js @@ -1,18 +1,15 @@ const fs = require('fs') const JWT = require('jsonwebtoken') const DataProvider = require('../../data/provider') -const ecPem = require('ec-pem') -const curve = 'secp384r1' const { nextUUID } = require('../datatypes/util') +const { PUBLIC_KEY } = require('./constants') +const algorithm = 'ES384' module.exports = (client, server, options) => { const skinGeom = fs.readFileSync(DataProvider(options.protocolVersion).getPath('skin_geom.txt'), 'utf-8') client.createClientChain = (mojangKey, offline) => { - mojangKey = mojangKey || require('./constants').PUBLIC_KEY - const alice = client.ecdhKeyPair - const alicePEM = ecPem(alice, curve) // https://github.com/nodejs/node/issues/15116#issuecomment-384790125 - const alicePEMPrivate = alicePEM.encodePrivateKey() + const privateKey = client.ecdhKeyPair.privateKey let token if (offline) { @@ -25,16 +22,16 @@ module.exports = (client, server, options) => { certificateAuthority: true, identityPublicKey: client.clientX509 } - token = JWT.sign(payload, alicePEMPrivate, { algorithm: 'ES384', notBefore: 0, issuer: 'self', expiresIn: 60 * 60, header: { x5u: client.clientX509 } }) + token = JWT.sign(payload, privateKey, { algorithm, notBefore: 0, issuer: 'self', expiresIn: 60 * 60, header: { x5u: client.clientX509 } }) } else { token = JWT.sign({ - identityPublicKey: mojangKey, + identityPublicKey: mojangKey || PUBLIC_KEY, certificateAuthority: true - }, alicePEMPrivate, { algorithm: 'ES384', header: { x5u: client.clientX509 } }) + }, privateKey, { algorithm, header: { x5u: client.clientX509 } }) } client.clientIdentityChain = token - client.createClientUserChain(alicePEMPrivate) + client.createClientUserChain(privateKey) } client.createClientUserChain = (privateKey) => { @@ -82,7 +79,6 @@ module.exports = (client, server, options) => { const customPayload = options.skinData || {} payload = { ...payload, ...customPayload } - client.clientUserChain = JWT.sign(payload, privateKey, - { algorithm: 'ES384', header: { x5u: client.clientX509 } }) + client.clientUserChain = JWT.sign(payload, privateKey, { algorithm, header: { x5u: client.clientX509 } }) } } diff --git a/src/auth/loginVerify.js b/src/auth/loginVerify.js index 233e729..722dd17 100644 --- a/src/auth/loginVerify.js +++ b/src/auth/loginVerify.js @@ -1,11 +1,14 @@ const JWT = require('jsonwebtoken') const constants = require('./constants') const debug = require('debug')('minecraft-protocol') +const crypto = require('crypto') module.exports = (client, server, options) => { // Refer to the docs: // https://web.archive.org/web/20180917171505if_/https://confluence.yawk.at/display/PEPROTOCOL/Game+Packets#GamePackets-Login + const getDER = b64 => crypto.createPublicKey({ key: Buffer.from(b64, 'base64'), format: 'der', type: 'spki' }) + function verifyAuth (chain) { let data = {} @@ -16,9 +19,9 @@ module.exports = (client, server, options) => { // signed by Mojang by checking the x509 public key in the JWT headers let didVerify = false - let pubKey = mcPubKeyToPem(getX5U(chain[0])) // the first one is client signed, allow it + let pubKey = getDER(getX5U(chain[0])) // the first one is client signed, allow it let finalKey = null - // console.log(pubKey) + for (const token of chain) { const decoded = JWT.verify(token, pubKey, { algorithms: ['ES384'] }) // console.log('Decoded', decoded) @@ -30,7 +33,7 @@ module.exports = (client, server, options) => { debug('Verified client with mojang key', x5u) } - pubKey = decoded.identityPublicKey ? mcPubKeyToPem(decoded.identityPublicKey) : x5u + pubKey = decoded.identityPublicKey ? getDER(decoded.identityPublicKey) : x5u finalKey = decoded.identityPublicKey || finalKey // non pem data = { ...data, ...decoded } } @@ -44,7 +47,7 @@ module.exports = (client, server, options) => { } function verifySkin (publicKey, token) { - const pubKey = mcPubKeyToPem(publicKey) + const pubKey = getDER(publicKey) const decoded = JWT.verify(token, pubKey, { algorithms: ['ES384'] }) return decoded } @@ -71,16 +74,3 @@ function getX5U (token) { const hjson = JSON.parse(hdec) return hjson.x5u } - -function mcPubKeyToPem (mcPubKeyBuffer) { - if (mcPubKeyBuffer[0] === '-') return mcPubKeyBuffer - let pem = '-----BEGIN PUBLIC KEY-----\n' - let base64PubKey = mcPubKeyBuffer.toString('base64') - const maxLineLength = 65 - while (base64PubKey.length > 0) { - pem += base64PubKey.substring(0, maxLineLength) + '\n' - base64PubKey = base64PubKey.substring(maxLineLength) - } - pem += '-----END PUBLIC KEY-----\n' - return pem -} From 7d532e8c7ec30b07b454d4fdd8b6796702447af1 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Tue, 11 May 2021 21:40:53 -0400 Subject: [PATCH 2/3] protocol updates --- data/1.16.220/protocol.json | 74 ++++++++++++++++++++------------ data/latest/proto.yml | 84 ++++++++++++++++++++++++------------- data/latest/types.yaml | 13 +++--- 3 files changed, 106 insertions(+), 65 deletions(-) diff --git a/data/1.16.220/protocol.json b/data/1.16.220/protocol.json index ea3b674..115676d 100644 --- a/data/1.16.220/protocol.json +++ b/data/1.16.220/protocol.json @@ -212,7 +212,7 @@ } ] ], - "BlockPalette": [ + "BlockProperties": [ "array", { "countType": "varint", @@ -4287,8 +4287,8 @@ "type": "zigzag32" }, { - "name": "block_palette", - "type": "BlockPalette" + "name": "block_properties", + "type": "BlockProperties" }, { "name": "itemstates", @@ -5967,6 +5967,31 @@ { "compareTo": "type", "fields": { + "show_bar": [ + "container", + [ + { + "name": "title", + "type": "string" + }, + { + "name": "progress", + "type": "lf32" + }, + { + "name": "screen_darkening", + "type": "li16" + }, + { + "name": "color", + "type": "varint" + }, + { + "name": "overlay", + "type": "varint" + } + ] + ], "register_player": [ "container", [ @@ -5985,16 +6010,21 @@ } ] ], - "show": [ + "set_bar_progress": [ + "container", + [ + { + "name": "progress", + "type": "lf32" + } + ] + ], + "set_bar_title": [ "container", [ { "name": "title", "type": "string" - }, - { - "name": "bar_progress", - "type": "lf32" } ] ], @@ -6002,8 +6032,16 @@ "container", [ { - "name": "darkness_factor", + "name": "screen_darkening", "type": "li16" + }, + { + "name": "color", + "type": "varint" + }, + { + "name": "overlay", + "type": "varint" } ] ], @@ -6019,24 +6057,6 @@ "type": "varint" } ] - ], - "set_bar_progress": [ - "container", - [ - { - "name": "bar_progress", - "type": "lf32" - } - ] - ], - "set_bar_title": [ - "container", - [ - { - "name": "title", - "type": "string" - } - ] ] }, "default": "void" diff --git a/data/latest/proto.yml b/data/latest/proto.yml index aebfc05..57bbd76 100644 --- a/data/latest/proto.yml +++ b/data/latest/proto.yml @@ -21,30 +21,30 @@ nbt: native # load the packet map file !import: packet_map.yml -#todo: docs !StartDocs: Packets # # Login Sequence # The login process is as follows: # -# C→S: [Login](#packet_login) -# S→C: [Server To Client Handshake](#packet_server_to_client_handshake) -# C→S: [Client To Server Handshake](#packet_client_to_server_handshake) -# S→C: [Play Status (Login success)](#packet_play_status) -# To spawn, the following packets should be sent, in order, after the ones above: +# * C→S: [Login](#packet_login) +# * S→C: [Server To Client Handshake](#packet_server_to_client_handshake) +# * C→S: [Client To Server Handshake](#packet_client_to_server_handshake) +# * S→C: [Play Status (Login success)](#packet_play_status) +# * To spawn, the following packets should be sent, in order, after the ones above: +# * S→C: [Resource Packs Info](#packet_resource_packs_info) +# * C→S: [Resource Pack Client Response](#packet_resource_pack_client_response) +# * S→C: [Resource Pack Stack](#packet_resource_pack_stack) +# * C→S: [Resource Pack Client Response](#packet_resource_pack_client_response) +# * S→C: [Start Game](#packet_start_game) +# * S→C: [Creative Content](#packet_creative_content) +# * S→C: [Biome Definition List](#packet_biome_definition_list) +# * S→C: [Chunks](#packet_level_chunk) +# * S→C: [Play Status (Player spawn)](#packet_play_status) # -# S→C: [Resource Packs Info](#packet_resource_packs_info) -# C→S: [Resource Pack Client Response](#packet_resource_pack_client_response) -# S→C: [Resource Pack Stack](#packet_resource_pack_stack) -# C→S: [Resource Pack Client Response](#packet_resource_pack_client_response) -# S→C: [Start Game](#packet_start_game) -# S→C: [Creative Content](#packet_creative_content) -# S→C: [Biome Definition List](#packet_biome_definition_list) -# S→C: [Chunks](#packet_level_chunk) -# S→C: [Play Status (Player spawn)](#packet_play_status) # If there are no resource packs being sent, a Resource Pack Stack can be sent directly # after Resource Packs Info to avoid the client responses. - +# +# === packet_login: !id: 0x01 @@ -366,15 +366,17 @@ packet_start_game: # results both client- and server-side. enchantment_seed: zigzag32 - ## This is not sent anymore in protocol versions > 419 (Bedrock Edition v1.16.100) - ## A list of all blocks registered on the server. - block_palette: BlockPalette + # BlockProperties is a list of all the custom blocks registered on the server. + block_properties: BlockProperties # A list of all items with their legacy IDs which are available in the game. # Failing to send any of the items that are in the game will crash mobile clients. itemstates: Itemstates # A unique ID specifying the multi-player session of the player. # A random UUID should be filled out for this field. multiplayer_correlation_id: string + # ServerAuthoritativeInventory specifies if the server authoritative inventory system is enabled. This + # is a new system introduced in 1.16. Backwards compatibility with the inventory transactions has to + # some extent been preserved, but will eventually be removed. server_authoritative_inventory: bool @@ -1387,20 +1389,41 @@ packet_boss_event: # S2C: Not implemented :( Intended to alter bar appearance, but these currently produce no effect on client-side whatsoever. 7: texture _: type? - if register_player or unregister_player: - player_id: zigzag64 - if show: + if show_bar: + # BossBarTitle is the title shown above the boss bar. It currently does not function, and instead uses + # the name tag of the boss entity at all times. It is only set if the EventType is BossEventShow or + # BossEventTitle. + title: string + # HealthPercentage is the percentage of health that is shown in the boss bar. It currently does not + # function, and instead uses the health percentage of the boss entity at all times. It is only set if the + # EventType is BossEventShow or BossEventHealthPercentage. + progress: lf32 + # ScreenDarkening currently seems not to do anything. + screen_darkening: li16 + # Colour is the colour of the boss bar that is shown when a player is subscribed. It currently does not + # function. It is only set if the EventType is BossEventShow, BossEventAppearanceProperties or + # BossEventTexture. + # Format is ARGB + color: varint + # Overlay is the overlay of the boss bar that is shown on top of the boss bar when a player is + # subscribed. It currently does not function. It is only set if the EventType is BossEventShow, + # BossEventAppearanceProperties or BossEventTexture. + overlay: varint + if register_player or unregister_player: + # PlayerUniqueID is the unique ID of the player that is registered to or unregistered from the boss + # fight. It is set if EventType is either BossEventRegisterPlayer or BossEventUnregisterPlayer. + player_id: zigzag64 + if set_bar_progress: + progress: lf32 + if set_bar_title: title: string - bar_progress: lf32 if update_properties: - darkness_factor: li16 + screen_darkening: li16 + color: varint + overlay: varint if texture: color: varint overlay: varint - if set_bar_progress: - bar_progress: lf32 - if set_bar_title: - title: string packet_show_credits: !id: 0x4b @@ -1418,8 +1441,9 @@ packet_available_commands: # The length of the enums for all the command paramaters in this packet values_len: varint # Not read from stream: instead calculated from the `values_len` field - # If the values_len < 0xff => byte - # If the values_len < 0xffff => short + # + # If the values_len < 0xff => byte, + # If the values_len < 0xffff => short, # If the values_len < 0xffffff => int _enum_type: '["enum_size_based_on_values_len"]' # Here all the enum values for all of the possible commands are stored to one array palette diff --git a/data/latest/types.yaml b/data/latest/types.yaml index 888be3c..8174c0f 100644 --- a/data/latest/types.yaml +++ b/data/latest/types.yaml @@ -1,4 +1,4 @@ -# !StartDocs: Types +!StartDocs: Types BehaviourPackInfos: []li16 uuid: string @@ -66,7 +66,7 @@ Blob: # Payload in it. payload: ByteArray -BlockPalette: []varint +BlockProperties: []varint name: string state: nbt @@ -75,7 +75,7 @@ Itemstates: []varint runtime_id: li16 component_based: bool -# Start of item crap ... + ItemExtraDataWithBlockingTick: has_nbt: lu16 => @@ -102,7 +102,7 @@ ItemExtraDataWithoutBlockingTick: can_place_on: ShortArray[]li32 can_destroy: ShortArray[]li32 -# Same as below but without a "networkStackID" boolean ... +# Same as below but without a "networkStackID" boolean ItemLegacy: network_id: zigzag32 _: network_id? @@ -140,8 +140,6 @@ Item: if 355: '["encapsulated", { "lengthType": "varint", "type": "ItemExtraDataWithBlockingTick" }]' default: '["encapsulated", { "lengthType": "varint", "type": "ItemExtraDataWithoutBlockingTick" }]' -# end of item crap - vec3i: x: zigzag32 y: zigzag32 @@ -632,8 +630,7 @@ Recipes: []varint recipe_id: string width: zigzag32 height: zigzag32 - # todo: can this become - # RecipeIngredient[$height][$width] or RecipeIngredient[]$height[]$width ? + # 2D input array, size of width*height input: []$width _: RecipeIngredient[]$height output: ItemLegacy[]varint From 879a4c21ba07f2e181f48d768428e35c150ffb2c Mon Sep 17 00:00:00 2001 From: extremeheat Date: Wed, 12 May 2021 04:20:35 -0400 Subject: [PATCH 3/3] Rename src/auth -> src/handshake --- src/client.js | 8 ++++---- src/{auth => handshake}/constants.js | 0 src/{auth/encryption.js => handshake/keyExchange.js} | 12 +++++++----- src/{auth => handshake}/login.js | 0 src/{auth => handshake}/loginVerify.js | 0 src/serverPlayer.js | 8 ++++---- 6 files changed, 15 insertions(+), 13 deletions(-) rename src/{auth => handshake}/constants.js (100%) rename src/{auth/encryption.js => handshake/keyExchange.js} (92%) rename src/{auth => handshake}/login.js (100%) rename src/{auth => handshake}/loginVerify.js (100%) diff --git a/src/client.js b/src/client.js index 68f247c..68c8886 100644 --- a/src/client.js +++ b/src/client.js @@ -7,9 +7,9 @@ const debug = require('debug')('minecraft-protocol') const Options = require('./options') const auth = require('./client/auth') -const { Encrypt } = require('./auth/encryption') -const Login = require('./auth/login') -const LoginVerify = require('./auth/loginVerify') +const { KeyExchange } = require('./handshake/keyExchange') +const Login = require('./handshake/login') +const LoginVerify = require('./handshake/loginVerify') const debugging = false @@ -25,7 +25,7 @@ class Client extends Connection { this.serializer = createSerializer(this.options.version) this.deserializer = createDeserializer(this.options.version) - Encrypt(this, null, this.options) + KeyExchange(this, null, this.options) Login(this, null, this.options) LoginVerify(this, null, this.options) diff --git a/src/auth/constants.js b/src/handshake/constants.js similarity index 100% rename from src/auth/constants.js rename to src/handshake/constants.js diff --git a/src/auth/encryption.js b/src/handshake/keyExchange.js similarity index 92% rename from src/auth/encryption.js rename to src/handshake/keyExchange.js index 2656a99..e4dfe54 100644 --- a/src/auth/encryption.js +++ b/src/handshake/keyExchange.js @@ -8,7 +8,8 @@ const curve = 'secp384r1' const pem = { format: 'pem', type: 'sec1' } const der = { format: 'der', type: 'spki' } -function Encrypt (client, server, options) { +function KeyExchange (client, server, options) { + // Generate a key pair at program start up client.ecdhKeyPair = crypto.generateKeyPairSync('ec', { namedCurve: curve }) client.publicKeyDER = client.ecdhKeyPair.publicKey.export(der) client.privateKeyPEM = client.ecdhKeyPair.privateKey.export(pem) @@ -31,10 +32,9 @@ function Encrypt (client, server, options) { const secretHash = crypto.createHash('sha256') secretHash.update(SALT) secretHash.update(client.sharedSecret) - // console.log('[encrypt] Shared secret', client.sharedSecret) client.secretKeyBytes = secretHash.digest() - // console.log('[encrypt] Shared hash', client.secretKeyBytes) + const token = JWT.sign({ salt: toBase64(SALT), signedToken: client.clientX509 @@ -56,13 +56,14 @@ function Encrypt (client, server, options) { throw Error('Server did not return a valid JWT, cannot start encryption!') } - // TODO: Should we do some JWT signature validation here? Seems pointless + // No verification here, not needed const [header, payload] = jwt.split('.').map(k => Buffer.from(k, 'base64')) const head = JSON.parse(String(header)) const body = JSON.parse(String(payload)) const pubKeyDer = crypto.createPublicKey({ key: Buffer.from(head.x5u, 'base64'), ...der }) + // Shared secret from the client's public key + our private key client.sharedSecret = crypto.diffieHellman({ privateKey: client.ecdhKeyPair.privateKey, publicKey: pubKeyDer }) @@ -76,6 +77,7 @@ function Encrypt (client, server, options) { client.startEncryption(iv) // It works! First encrypted packet :) + client.write('client_to_server_handshake', {}) this.emit('join') client.status = ClientStatus.Initializing @@ -89,4 +91,4 @@ function toBase64 (string) { return Buffer.from(string).toString('base64') } -module.exports = { Encrypt } +module.exports = { KeyExchange } diff --git a/src/auth/login.js b/src/handshake/login.js similarity index 100% rename from src/auth/login.js rename to src/handshake/login.js diff --git a/src/auth/loginVerify.js b/src/handshake/loginVerify.js similarity index 100% rename from src/auth/loginVerify.js rename to src/handshake/loginVerify.js diff --git a/src/serverPlayer.js b/src/serverPlayer.js index 9005cef..7335d6d 100644 --- a/src/serverPlayer.js +++ b/src/serverPlayer.js @@ -3,9 +3,9 @@ const fs = require('fs') const Options = require('./options') const debug = require('debug')('minecraft-protocol') -const { Encrypt } = require('./auth/encryption') -const Login = require('./auth/login') -const LoginVerify = require('./auth/loginVerify') +const { KeyExchange } = require('./handshake/keyExchange') +const Login = require('./handshake/login') +const LoginVerify = require('./handshake/loginVerify') class Player extends Connection { constructor (server, connection) { @@ -16,7 +16,7 @@ class Player extends Connection { this.connection = connection this.options = server.options - Encrypt(this, server, server.options) + KeyExchange(this, server, server.options) Login(this, server, server.options) LoginVerify(this, server, server.options)