Encryption Implementation
Encryption is implemented for Java Edition connections using AES-128 in CFB8 (Cipher Feedback 8-bit) mode.Dependencies
Defined inpumpkin-protocol/Cargo.toml:26-28
Cipher Types
Defined inpumpkin-protocol/src/lib.rs:185 and pumpkin-protocol/src/lib.rs:227
Stream Decryptor
TheStreamDecryptor wraps an AsyncRead stream to decrypt data on-the-fly.
Implementation
Defined inpumpkin-protocol/src/lib.rs:187-225
AsyncRead Implementation
Defined inpumpkin-protocol/src/lib.rs:201-225
The decryptor:
- Reads raw encrypted data from underlying stream
- Decrypts data in-place using AES-128 CFB8
- Returns decrypted data to caller
CFB8 Block Size
CFB8 mode operates on 1-byte blocks, making in-place decryption safe and efficient.Stream Encryptor
TheStreamEncryptor wraps an AsyncWrite stream to encrypt data on-the-fly.
Implementation
Defined inpumpkin-protocol/src/lib.rs:230-307
AsyncWrite Implementation
Defined inpumpkin-protocol/src/lib.rs:247-307
The encryptor:
- Encrypts each byte using AES-128 CFB8
- Writes encrypted bytes to underlying stream
- Handles partial writes by caching last encrypted byte
Write Buffering
The encryptor maintainslast_unwritten_encrypted_byte to handle cases where the underlying stream cannot accept a write immediately, ensuring data integrity.
Encryption in Java Edition
Decoder Encryption
Defined inpumpkin-protocol/src/java/packet_decoder.rs:96-102
Encoder Encryption
Defined inpumpkin-protocol/src/java/packet_encoder.rs:110-117
Key and IV
In Minecraft’s protocol, the encryption key and initialization vector (IV) are the same 16-byte value:Encryption Wrapper Types
DecryptionReader
Defined inpumpkin-protocol/src/java/packet_decoder.rs:38-71
EncryptionWriter
Defined inpumpkin-protocol/src/java/packet_encoder.rs:14-78
Encryption Lifecycle
Initial State
Connections start without encryption:Enabling Encryption
Encryption is enabled after login handshake:One-Way Transition
Encryption cannot be disabled once enabled. Attempting to enable it twice will panic:Encryption with Compression
Processing Order
Encoding (Server → Client):Implementation
Both encryption and compression can be enabled:Testing Encryption
Encryption is tested in the packet encoder/decoder test suites.Test: Decode with Encryption
Defined inpumpkin-protocol/src/java/packet_decoder.rs:310-331
Test: Encode with Encryption
Defined inpumpkin-protocol/src/java/packet_encoder.rs:497-535
Security Considerations
Key Exchange
The encryption key is established during the login handshake using RSA encryption. The server:- Generates a 16-byte shared secret
- Encrypts it with the client’s public key (RSA)
- Sends encrypted secret to client
- Client decrypts with private key
- Both parties derive the AES key from the shared secret
AES-128 CFB8 Properties
- Key Size: 128 bits (16 bytes)
- Block Size: 8 bits (1 byte) in CFB8 mode
- IV: Same as key in Minecraft protocol
- Padding: Not required (stream cipher mode)
- Security: Adequate for game traffic protection
Implementation Notes
- Keys are passed as
&[u8; 16]to ensure correct size - Cipher is initialized with
new_from_slices(key, iv)which validates key/IV lengths - Invalid keys cause a panic with
expect("invalid key")
Bedrock Edition Encryption
Current Status
Bedrock Edition encryption is not yet implemented:Planned Implementation
Bedrock Edition uses a different encryption scheme than Java Edition, which will require separate implementation.Next Steps
- Compression - Learn about packet compression
- Java Edition Protocol - See encryption in context
- Overview - Return to protocol overview
