# 05 — Login State, Encryption & Compression > **Scope:** Java Edition 1.7.10 → latest (1.21.x). Covers the Login protocol state, > the encryption handshake, Mojang session auth, packet compression, and the 1.19/1.20.2 > versioned deviations. All crypto details are sourced from the reference implementations > listed in each section. --- ## 1. Login State Overview The Login state begins immediately after the client sends a Handshake packet with `next state = 2`. It ends when the server sends **Login Success** (and, since 1.20.2, the client acknowledges it). All packets in this state use the standard framing: ``` ``` After **Set Compression** is negotiated (if at all), each packet gains an extra **Data Length** VarInt (see §4). After **Encryption Response** is processed, the entire TCP stream — including the Length prefix — is encrypted with AES/CFB8 (see §3). --- ## 2. Packet Reference ### 2.1 Login Start (0x00 Serverbound) The first Login-state packet sent by the client. | Field | Type | Version range | Notes | |---|---|---|---| | Username | String(16) | all | Player username, max 16 chars | | Signature | Optional container | 1.19–1.19.2 | Profile public key; see §5 | | └ Timestamp | i64 | 1.19–1.19.2 | Key expiry timestamp (ms since epoch) | | └ Public Key | Prefixed byte array | 1.19–1.19.2 | DER SubjectPublicKeyInfo of player's key | | └ Signature | Prefixed byte array | 1.19–1.19.2 | Mojang-signed; see §5 | | Has UUID | Optional bool (not present in 1.20.2+) | 1.19.1–1.20.1 | Presence flag | | Player UUID | UUID | 1.19.1+ | Optional (flag-gated) in 1.19.1–1.20.1; always present 1.20.2+ | **Source:** `minecraft-data/data/pc/1.7/protocol.json`, `minecraft-data/data/pc/1.19/protocol.json`, `minecraft-data/data/pc/1.19.2/protocol.json`, `minecraft-data/data/pc/1.20.2/protocol.json`; `BungeeCord/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginRequest.java:28–39` Version notes: - **≤1.19.2:** `Signature` container present (profile public key for chat-signing); removed in 1.19.3. - **1.19:** only `signature` field (no UUID). - **1.19.2:** adds optional `playerUUID` after the signature. - **1.19.1–1.20.1:** UUID is optional (preceded by a boolean flag). - **1.20.2+:** UUID is unconditionally included (no flag byte). (`BungeeCord LoginRequest.java:35–38`: `if (protocolVersion >= MINECRAFT_1_20_2)` reads UUID directly.) --- ### 2.2 Encryption Request (0x01 Clientbound) Sent by the server in online mode to initiate the key exchange. | Field | Type | Version range | Notes | |---|---|---|---| | Server ID | String(20) | all | Historically a 10-char hex; **empty string `""` in vanilla 1.7+** | | Public Key | Prefixed byte array | 1.8+ | DER-encoded X.509 SubjectPublicKeyInfo of server's RSA-1024 public key | | Public Key | 2-byte-length byte array | 1.7 (pre-Netty) | Same key, length prefixed with `i16` | | Verify Token | Prefixed byte array | all | 4 random bytes generated per-connection | | Should Authenticate | Boolean | 1.20.5+ | Whether Mojang session auth should be performed | **Source:** `Velocity/proxy/.../EncryptionRequestPacket.java:62–74` (1.7 vs 1.8+ branching on `readByteArray` vs `readByteArray17`; `shouldAuthenticate` field read at line 67–69); `BungeeCord/protocol/.../EncryptionRequest.java:26–30`; `minecraft-data/data/pc/1.7/protocol.json` (countType `i16`); `minecraft-data/data/pc/1.8/protocol.json` (countType `varint`). Notes: - The Server ID string was meaningful in old Alpha/Beta versions but **has been an empty string `""` in all vanilla servers since 1.7** (wiki.minecraft.net/w/Java_Edition_protocol/Encryption). Some implementations (node-minecraft-protocol `server/login.js:89`) generate a short random hex string instead. - `shouldAuthenticate` (1.20.5+) lets the server tell the client not to call the Mojang session endpoint; used for offline-mode negotiation without breaking the encryption handshake. (`Velocity/proxy/.../EncryptionRequestPacket.java:67–69`) --- ### 2.3 Encryption Response (0x01 Serverbound) Client reply containing the RSA-encrypted shared secret and token. **Standard form (all versions except 1.19–1.19.2 with profile keys):** | Field | Type | Notes | |---|---|---| | Shared Secret | Prefixed byte array | 128 bytes (RSA-PKCS1 v1.5 ciphertext of 16-byte secret) | | Verify Token | Prefixed byte array | 128 bytes (RSA-PKCS1 v1.5 ciphertext of the 4-byte token) | **1.19–1.19.2 form with profile keys (chat signing enabled):** | Field | Type | Notes | |---|---|---| | Shared Secret | Prefixed byte array | 128 bytes as above | | Has Verify Token | Boolean | `true` = standard token; `false` = signed salt | | — if true: Verify Token | Prefixed byte array | 128 bytes as above | | — if false: Salt | i64 | Random 64-bit salt | | — if false: Message Signature | Prefixed byte array | SHA256withRSA sig over `verifyToken ‖ salt` | **Source:** `Velocity/proxy/.../EncryptionResponsePacket.java:66–101` (version branching); `BungeeCord/protocol/.../EncryptionResponse.java:24–55`; `node-minecraft-protocol/src/client/encrypt.js:52–73` (1.19 `hasVerifyToken`/`salt`/`messageSignature` branch); `node-minecraft-protocol/src/server/login.js:109–141` (server-side verification). Notes: - `Has Verify Token = false` only occurs in 1.19–1.19.2 when the client has a profile key (chat-signing enabled). The server verifies the salt+signature against the player's profile public key from Login Start instead of decrypting the token. (`server/login.js:120–126`: `crypto.verify('sha256WithRSAEncryption', …)`) - In 1.19.3+, profile keys were removed from Login Start; `Has Verify Token` field is gone and the packet reverts to the simple two-field form. (`Velocity/proxy/.../EncryptionResponsePacket.java:70–74`: version range `>= 1.19 && < 1.19.3`) --- ### 2.4 Set Compression (0x03 Clientbound) Optional packet. If sent, all subsequent packets in Login (and Play) use the compressed framing described in §4. | Field | Type | Notes | |---|---|---| | Threshold | VarInt | Minimum uncompressed size to trigger compression. Negative = disable. | **Source:** `BungeeCord/protocol/.../SetCompression.java:19–22`; `node-minecraft-protocol/src/server/login.js:179–181` (`client.write('compress', { threshold: 256 })`). Notes: - Added in **1.8** (protocol version 47, snapshot 14w28a). (`node-minecraft-protocol/src/server/login.js:179`: `if (client.protocolVersion >= 27)`) - Vanilla default threshold is **256 bytes** uncompressed payload. - A threshold of `-1` disables compression; packets keep the uncompressed framing. - **Must be sent before Login Success** if used. The server enables its own compressor and decompressor as soon as it sends this packet; the client enables them on receipt. --- ### 2.5 Login Success (0x02 Clientbound) Signals the end of authentication. Carries the player's resolved UUID and username. | Field | Type | Version range | Notes | |---|---|---|---| | UUID | String (hyphenated) | ≤1.15 | `"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"` | | UUID | UUID (128-bit wire) | 1.16+ | Raw 16-byte big-endian UUID | | Username | String(16) | all | Canonical (case-corrected) name from Mojang | | Properties | Array of Property | 1.19+ | Texture/cape data; each has `name`, `value`, optional `signature` | | Strict Error Handling | Boolean | 1.20.5–1.21.1 | Vanilla sends `true` | **Source:** `BungeeCord/protocol/.../LoginSuccess.java:28–43` (UUID wire-type branch at 1.16; properties at 1.19; `strictErrorHandling` at 1.20.5–1.21.1); `node-minecraft-protocol/src/server/login.js:184–188`. Notes: - UUID comes from the Mojang session server response (`id` field, dashes stripped) in online mode. In offline mode it is `UUID.nameUUIDFromBytes("OfflinePlayer:" + username)`. - **Login Success is sent encrypted** (all prior negotiation including Encryption Response triggers immediate cipher switch; see §3.5). --- ### 2.6 Login Acknowledged (0x03 Serverbound) No fields. The client sends this to confirm it has processed Login Success and is ready to enter the **Configuration** state. Added in **1.20.2**. **Source:** `minecraft-data/data/pc/1.20.2/protocol.json` (toServer `0x03: login_acknowledged`); `node-minecraft-protocol/src/server/login.js:189–191` (`if (client.supportFeature('hasConfigurationState')) client.once('login_acknowledged', …)`); `minecraft-data/data/pc/common/features.json` (`hasConfigurationState` versions: `["1.20.2", "latest"]`). --- ## 3. Encryption Handshake ### 3.1 Sequence Diagram ```mermaid sequenceDiagram participant C as Client participant S as Server participant M as sessionserver.mojang.com C->>S: Handshake (next_state=2) C->>S: Login Start (username [+ profile key 1.19–1.19.2]) Note over S: online-mode? generate RSA-1024 keypair (once at startup) S->>C: Encryption Request (serverId="", DER pubkey, 4-byte verifyToken) Note over C: generate 16-byte random sharedSecret Note over C: RSA-PKCS1-v1.5 encrypt sharedSecret → enc_secret (128 B) Note over C: RSA-PKCS1-v1.5 encrypt verifyToken → enc_token (128 B) Note over C: compute serverIdHash = MinecraftSHA1(serverId‖sharedSecret‖pubKey) C->>M: POST /session/minecraft/join {accessToken, selectedProfile, serverId=serverIdHash} M-->>C: 204 No Content C->>S: Encryption Response (enc_secret, enc_token) Note over C: enable AES/CFB8 (key=sharedSecret, IV=sharedSecret) — all outgoing encrypted now Note over S: RSA-decrypt enc_secret → sharedSecret Note over S: RSA-decrypt enc_token → verify == original verifyToken? Note over S: compute serverIdHash = MinecraftSHA1(serverId‖sharedSecret‖pubKey) S->>M: GET /session/minecraft/hasJoined?username=&serverId=serverIdHash M-->>S: 200 {id, name, properties} or 204 (not found) Note over S: enable AES/CFB8 (key=sharedSecret, IV=sharedSecret) — all outgoing encrypted now S->>C: [Set Compression] (optional, 1.8+) S->>C: Login Success (uuid, username, properties) — encrypted C->>S: Login Acknowledged (1.20.2+) — encrypted ``` --- ### 3.2 RSA Key Exchange **Key size:** 1024-bit RSA, generated once at server startup. - BungeeCord: `EncryptionUtil.java:51` — `generator.initialize(1024)` - Velocity: `VelocityServer.java:255` — `EncryptionUtils.createRsaKeyPair(1024)` **Public key encoding:** The bytes sent in Encryption Request are the **DER-encoded X.509 SubjectPublicKeyInfo** (i.e. `java.security.PublicKey.getEncoded()` using the `X509EncodedKeySpec`). This wraps the raw RSA key in an ASN.1 structure identifying the algorithm (`rsaEncryption OID 1.2.840.113549.1.1.1`). The client reconstructs the public key from this DER blob: (`node-minecraft-protocol/src/client/encrypt.js:48–50`) ```js // encrypt.js:48–50 const pubKey = mcPubKeyToPem(packet.publicKey) // DER → PEM wrapper const encryptedSharedSecretBuffer = crypto.publicEncrypt({ key: pubKey, padding: crypto.constants.RSA_PKCS1_PADDING }, sharedSecret) const encryptedVerifyTokenBuffer = crypto.publicEncrypt({ key: pubKey, padding: crypto.constants.RSA_PKCS1_PADDING }, packet.verifyToken) ``` **Padding:** PKCS#1 v1.5 (`RSA_PKCS1_PADDING` / `RSA/ECB/PKCS1Padding`). - BungeeCord: `EncryptionUtil.java:144–148` — `Cipher.getInstance("RSA/ECB/PKCS1Padding")` - Velocity: `EncryptionUtils.java:190–193` — `Cipher.getInstance("RSA")` (JCA default = PKCS#1 v1.5) **Ciphertext size:** With a 1024-bit key and PKCS#1 v1.5 padding, any input ≤ 117 bytes produces a **128-byte ciphertext**. Both the encrypted shared secret and encrypted verify token are therefore 128 bytes on the wire. --- ### 3.3 Server-ID Hash Algorithm The **serverIdHash** (called `serverId` in the Mojang API) is a non-standard SHA-1 digest formatted as a signed two's-complement hex integer, possibly with a leading `-`. **Inputs (in order):** 1. `serverId` string bytes, encoded as ISO-8859-1 (Latin-1) — in vanilla this is always an empty string, so no bytes are contributed. 2. `sharedSecret` — the raw 16-byte AES key. 3. Server's RSA public key — DER-encoded SubjectPublicKeyInfo bytes. **Algorithm:** ```python import hashlib, textwrap def minecraft_sha1_hex(server_id: str, shared_secret: bytes, server_pub_der: bytes) -> str: h = hashlib.sha1() h.update(server_id.encode('iso-8859-1')) h.update(shared_secret) h.update(server_pub_der) digest = h.digest() # 20 raw bytes # Interpret as a signed big-endian integer (two's complement): n = int.from_bytes(digest, byteorder='big', signed=True) return format(n, 'x') # hex, with '-' prefix if negative ``` Java equivalent (BungeeCord `InitialHandler.java:517–525`): ```java MessageDigest sha = MessageDigest.getInstance("SHA-1"); sha.update(request.getServerId().getBytes("ISO_8859_1")); sha.update(sharedKey.getEncoded()); sha.update(EncryptionUtil.keys.getPublic().getEncoded()); String hash = new BigInteger(sha.digest()).toString(16); // BigInteger(byte[]) treats the input as two's-complement big-endian → negative if MSB set ``` Velocity (`EncryptionUtils.java:203–212`) omits the `serverId` update because the field is always `""` in Velocity: ```java digest.update(sharedSecret); // EncryptionUtils.java:207 digest.update(key.getEncoded()); // EncryptionUtils.java:208 return twosComplementHexdigest(digest.digest()); // twosComplementHexdigest: new BigInteger(digest).toString(16) (line 179) ``` **Wiki examples** (minecraft.wiki/w/Java_Edition_protocol/Encryption): | Input string | serverIdHash | |---|---| | `Notch` | `4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48` | | `jeb_` | `-7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1` | | `simon` | `88e16a1019277b15d58faf0541e11910eb756f6` | Note: these examples use the string as the entire input (simulating a server where `serverId = "Notch"` etc.), not a realistic scenario. **Why two's complement?** The SHA-1 output is 20 bytes. Mojang's original Minecraft code treated this raw byte array as a signed big-endian integer via Java's `BigInteger(byte[])`. If the high bit of the first byte is set (digest[0] ≥ 0x80), the integer is negative, and the hex string gets a leading `-`. This is non-standard but has been the canonical format since Minecraft Beta 1.2. --- ### 3.4 AES/CFB8 Stream Cipher After both sides process Encryption Response, every subsequent byte on the TCP connection is encrypted. There are **no unencrypted bytes** after this point — not even the packet length VarInt. **Cipher parameters:** | Parameter | Value | |---|---| | Algorithm | AES | | Mode | CFB8 (Cipher Feedback, 8-bit segment size) | | Key | 16-byte shared secret | | IV | 16-byte shared secret (same as key) | | Padding | None | BungeeCord (`JavaCipher.java`): ```java this.cipher = Cipher.getInstance("AES/CFB8/NoPadding"); cipher.init(mode, key, new IvParameterSpec(key.getEncoded())); // key.getEncoded() == the 16-byte shared secret, used as IV ``` Velocity (`JavaVelocityCipher.java:50–61`): ```java this.cipher = Cipher.getInstance("AES/CFB8/NoPadding"); this.cipher.init( encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, key, new IvParameterSpec(key.getEncoded()) // IV = key = shared secret ); ``` node-minecraft-protocol (`transforms/encryption.js:6–17`): ```js // encryption.js:6–9 function createCipher(secret) { if (crypto.getCiphers().includes('aes-128-cfb8')) { return crypto.createCipheriv('aes-128-cfb8', secret, secret) // key=secret, IV=secret } return new Cipher(secret) // fallback uses aes-js CFB with segment size 1 byte } ``` **Important:** Reusing the key as the IV is a known weakness (noted in Velocity source, `JavaVelocityCipher.java:52–58`: *"reusing the key as the IV defeats the entire point"*). The cipher is initialized this way by Mojang design; it cannot be changed without a protocol breaking change. **Continuous operation:** The AES/CFB8 state is maintained across packets. The cipher is never reset or re-initialized between packets; the feedback register carries over. --- ### 3.5 Timing: When Encryption Activates - **Client:** enables AES/CFB8 immediately after *sending* Encryption Response (`node-minecraft-protocol/src/client/encrypt.js:73`: `client.setEncryption(sharedSecret)`) - **Server:** enables AES/CFB8 after *receiving* Encryption Response and verifying it (`node-minecraft-protocol/src/server/login.js:150`: `client.setEncryption(sharedSecret)`; Velocity `InitialLoginSessionHandler.java:234`: `mcConnection.enableEncryption(decryptedSharedSecret)`) The server enables encryption before calling the Mojang session server, so if `hasJoined` fails, the server sends a disconnect packet that is already encrypted. --- ## 4. Session Authentication (Online Mode) ### 4.1 Client → Mojang: `join` Before sending Encryption Response, the client posts to the Mojang session server: ``` POST https://sessionserver.mojang.com/session/minecraft/join Content-Type: application/json { "accessToken": "", "selectedProfile": "", "serverId": "" } ``` Expected response: **204 No Content** on success. (`node-minecraft-protocol/src/client/encrypt.js:41–43`: `yggdrasilServer.join(accessToken, selectedProfile.id, packet.serverId, sharedSecret, packet.publicKey, cb)` — the `join` call in the yggdrasil library computes the hash internally from `serverId + sharedSecret + publicKey`.) ### 4.2 Server → Mojang: `hasJoined` After enabling encryption and verifying the token, the server queries: ``` GET https://sessionserver.mojang.com/session/minecraft/hasJoined ?username= &serverId= [&ip=] # optional; prevents proxy-hopping ``` - **200 OK** → body is a GameProfile JSON `{id, name, properties[]}`. Login proceeds. - **204 No Content** → client did not call `join`; kick with `"offline_mode_player"` or similar. (`Velocity/proxy/.../InitialLoginSessionHandler.java:68–71`: URL template; BungeeCord `InitialHandler.java:527–528`: URL construction with `URLEncoder.encode`.) ### 4.3 Mojang → Microsoft Account Migration The original `sessionserver.mojang.com` endpoints still work after the Mojang → Microsoft account migration. All Minecraft clients (Bedrock and Java launcher) now use Microsoft OAuth tokens internally, but the session server interface is unchanged at the API level. ### 4.4 Offline Mode In offline mode, the server skips: - Sending Encryption Request (no encryption handshake at all) - Calling `hasJoined` UUID is derived deterministically: `UUID.nameUUIDFromBytes("OfflinePlayer:" + username)` (MD5-based UUID v3 equivalent). (`BungeeCord/proxy/.../connection/InitialHandler.java:560`) --- ## 5. 1.19 Profile Public Keys (Chat Signing) Minecraft 1.19 introduced per-player RSA key pairs signed by Mojang, allowing chat message signing. The **Login Start** packet gained a `Signature` field to deliver the player's public key to the server. This only affects the **login phase** through two mechanisms: 1. **Login Start (1.19–1.19.2):** Client sends its profile public key (DER + Mojang signature). 2. **Encryption Response (1.19–1.19.2):** Client may replace the encrypted verify token with a salt + signature over `verifyToken ‖ salt`, proving possession of the private key corresponding to the profile key. ### Profile Key Container (in Login Start, 1.19–1.19.2) | Sub-field | Type | Notes | |---|---|---| | Timestamp | i64 | Key expiry in milliseconds since epoch | | Public Key | Prefixed byte array | DER SubjectPublicKeyInfo | | Signature | Prefixed byte array | Mojang signature over the key material | **Signature verification (server side):** - **1.19:** verify against Mojang's public key over `UTF8(expiryTimestamp + PEM(playerPubKey))`. (`node-minecraft-protocol/src/server/login.js:72`: `Buffer.from(timestamp + mcPubKeyToPem(publicKey), 'utf8')`) - **1.19.2 (profileKeySignatureV2):** verify against Mojang's public key over `UUID(playerUUID) ‖ i64(timestamp) ‖ DER(playerPubKey)`. (`node-minecraft-protocol/src/server/login.js:71`: `concat('UUID', playerUUID, 'i64', timestamp, 'buffer', publicKey.export({type:'spki', format:'der'}))`) - Both use **RSA-SHA1** (`crypto.verify('RSA-SHA1', …)`). (`minecraft-data/data/pc/common/features.json`: `signatureEncryption` active on `["1.19", "1.19.2"]`; `profileKeySignatureV2` active on `["1.19.2", "latest"]`.) ### Removal in 1.19.3 Profile keys were removed from Login Start in 1.19.3. The `Signature` field is absent, the `Has Verify Token` field in Encryption Response is also gone, and the standard two-field Encryption Response format is used again. (`Velocity/proxy/.../EncryptionResponsePacket.java:70–74`: `if (version.noLessThan(MINECRAFT_1_19) && version.lessThan(MINECRAFT_1_19_3)) { salt check }`) --- ## 6. Compression ### 6.1 Negotiation The server may send **Set Compression** (0x03 clientbound) at any point during the Login state, before Login Success. The threshold value (VarInt) controls when zlib is applied: - **threshold < 0** — compression is disabled (revert to uncompressed framing). - **threshold = 0** — compress all packets. - **threshold > 0** (common: 256) — compress only packets whose uncompressed data length exceeds the threshold. Compression was added in **1.8** (snapshot 14w28a, protocol version 47). (`node-minecraft-protocol/src/server/login.js:179`: `if (client.protocolVersion >= 27)`) ### 6.2 Packet Format Before Set Compression ``` ┌─────────────────────────────────────────────────────────┐ │ Packet Length (VarInt) — byte count of ID + Data │ │ Packet ID (VarInt) │ │ Data (bytes) │ └─────────────────────────────────────────────────────────┘ ``` ### 6.3 Packet Format After Set Compression Two VarInts precede the payload: ``` ┌─────────────────────────────────────────────────────────┐ │ Packet Length (VarInt) — byte count of (Data Length │ │ VarInt + possibly compressed │ │ ID+Data) │ │ Data Length (VarInt) — 0 = not compressed; │ │ >0 = uncompressed byte count │ │ Packet ID + Data (bytes) — zlib-compressed if DL>0, │ │ raw otherwise │ └─────────────────────────────────────────────────────────┘ ``` **Uncompressed case** (data length < threshold): - Data Length VarInt = **0** - ID + Data follow uncompressed **Compressed case** (data length ≥ threshold): - Data Length VarInt = uncompressed byte count of ID+Data - ID + Data bytes are zlib (`DEFLATE`) compressed BungeeCord implementation (`netty/LengthPrependerAndCompressor.java:47–93`): ```java // uncompressed path (line 54–63): if (oldBodyLen < threshold) { DefinedPacket.writeVarInt(oldBodyLen + 1, lenBuf); // Packet Length lenBuf.writeByte(0); // Data Length = 0 → uncompressed // ... append raw body ... } // compressed path (line 78–93): else { DefinedPacket.writeVarInt(oldBodyLen, buf); // Data Length = original size zlib.process(msg, buf); // compress // Packet Length written as VarInt in front } ``` ### 6.4 Interaction with Encryption Compression and encryption are independent layers. When both are active: 1. **Write path:** `Compress → Encrypt → TCP` 2. **Read path:** `TCP → Decrypt → Decompress` The encrypted bytestream carries compressed packet data; the AES/CFB8 cipher sees compressed bytes and does not know about packet boundaries. --- ## 7. Version Summary | Feature | Introduced | Removed / Changed | |---|---|---| | Login Start: basic (name only) | 1.7 | — | | Encryption request/response | 1.2.5 (Beta) | — | | Byte arrays length-prefixed with VarInt | 1.8 | — | | Set Compression packet | 1.8 (14w28a) | — | | Login Start: profile public key | 1.19 | Removed 1.19.3 | | Encryption Response: Has Verify Token + salt | 1.19 | Removed 1.19.3 | | Login Start: optional UUID | 1.19.1 | Mandatory 1.20.2+ | | Profile key signature V2 | 1.19.2 | — | | Login Acknowledged packet | 1.20.2 | — | | Configuration state after login | 1.20.2 | — | | Encryption Request: Should Authenticate | 1.20.5 | — | | Login Success: Strict Error Handling | 1.20.5 | Removed 1.21.2 | | Login Success: UUID as raw 128-bit wire type | 1.16 | — | | Login Success: Properties array | 1.19 | — | --- ## 8. Sources | Reference | Path | |---|---| | node-minecraft-protocol encrypt.js | `node-minecraft-protocol/src/client/encrypt.js` | | node-minecraft-protocol encryption.js | `node-minecraft-protocol/src/transforms/encryption.js` | | node-minecraft-protocol server/login.js | `node-minecraft-protocol/src/server/login.js` | | Velocity EncryptionRequestPacket | `Velocity/proxy/.../packet/EncryptionRequestPacket.java` | | Velocity EncryptionResponsePacket | `Velocity/proxy/.../packet/EncryptionResponsePacket.java` | | Velocity EncryptionUtils | `Velocity/proxy/.../crypto/EncryptionUtils.java` | | Velocity JavaVelocityCipher | `Velocity/native/.../encryption/JavaVelocityCipher.java` | | Velocity InitialLoginSessionHandler | `Velocity/proxy/.../client/InitialLoginSessionHandler.java` | | BungeeCord EncryptionUtil | `BungeeCord/proxy/.../EncryptionUtil.java` | | BungeeCord InitialHandler | `BungeeCord/proxy/.../connection/InitialHandler.java` | | BungeeCord JavaCipher | `BungeeCord/native/.../cipher/JavaCipher.java` | | BungeeCord LengthPrependerAndCompressor | `BungeeCord/proxy/.../netty/LengthPrependerAndCompressor.java` | | BungeeCord LoginRequest | `BungeeCord/protocol/.../packet/LoginRequest.java` | | BungeeCord LoginSuccess | `BungeeCord/protocol/.../packet/LoginSuccess.java` | | BungeeCord EncryptionRequest | `BungeeCord/protocol/.../packet/EncryptionRequest.java` | | BungeeCord EncryptionResponse | `BungeeCord/protocol/.../packet/EncryptionResponse.java` | | BungeeCord SetCompression | `BungeeCord/protocol/.../packet/SetCompression.java` | | minecraft-data protocol.json (all versions) | `minecraft-data/data/pc//protocol.json` | | minecraft-data features.json | `minecraft-data/data/pc/common/features.json` | | minecraft.wiki Protocol Encryption | `https://minecraft.wiki/w/Java_Edition_protocol/Encryption` |