8 topical docs (overview, data types, lifecycle, handshake, status/ping, login+encryption, configuration, version-differences) + proxy-forwarding set + 16 per-version release-line docs, sourced from minecraft.wiki, ViaVersion (source + commits), minecraft-data, node-minecraft-protocol, Velocity, BungeeCord. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
27 KiB
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:
<Packet Length: VarInt> <Packet ID: VarInt> <Data: bytes>
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:
Signaturecontainer present (profile public key for chat-signing); removed in 1.19.3.- 1.19: only
signaturefield (no UUID). - 1.19.2: adds optional
playerUUIDafter the signature.
- 1.19: only
- 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-protocolserver/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 = falseonly 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 Tokenfield 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
-1disables 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 (
idfield, dashes stripped) in online mode. In offline mode it isUUID.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
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)
// 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):
serverIdstring bytes, encoded as ISO-8859-1 (Latin-1) — in vanilla this is always an empty string, so no bytes are contributed.sharedSecret— the raw 16-byte AES key.- Server's RSA public key — DER-encoded SubjectPublicKeyInfo bytes.
Algorithm:
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):
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:
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):
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):
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):
// 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); VelocityInitialLoginSessionHandler.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": "<launcher access token>",
"selectedProfile": "<UUID of player, dashes removed>",
"serverId": "<serverIdHash>"
}
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=<username>
&serverId=<serverIdHash>
[&ip=<client_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:
- Login Start (1.19–1.19.2): Client sends its profile public key (DER + Mojang signature).
- 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):
// 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:
- Write path:
Compress → Encrypt → TCP - 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/<version>/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 |