1.9 KiB
Protocol Internals
This client supports the modern OpenTTD Game Port protocol (TCP 3979), specifically as implemented in JGRPP.
X25519 PAKE Authentication
OpenTTD 14+ and JGRPP use a Password-Authenticated Key Exchange to prevent plaintext password leakage.
Key Derivation (KDF)
We use Blake2b (64-byte digest) to derive two 32-byte session keys.
- Input:
SharedSecret (32)+ServerPublicKey (32)+ClientPublicKey (32)+Password (string) - Output:
0..31: Client-to-Server Key32..63: Server-to-Client Key
Handshake Nonces
The server provides a 24-byte nonce in the ServerAuthenticationRequest. This nonce is used for the AEAD challenge during the auth response and for the initial stream encryption setup.
Stream Encryption (AEAD)
Once ServerEnableEncryption is received, all subsequent packets use XChaCha20-Poly1305 (Authenticated Encryption with Associated Data).
Encrypted Packet Format
On the wire, encrypted packets have the following structure:
- Length (2 bytes): Big-endian uint16 of the entire remaining packet.
- MAC (16 bytes): The Poly1305 authentication tag.
- Ciphertext (variable): The encrypted payload.
Decryption Logic
The OpenTTDProtocol layer uses an IncrementalAuthenticatedEncryption state from the Monocypher library. It maintains the nonce state internally. If a MAC check fails (indicating corruption or a wrong key), the client immediately closes the connection (SocketClosed).
Keep-Alive (Simulation Synchronization)
OpenTTD is a lockstep simulation. The server sends ServerFrame packets periodically.
- Client Requirement: You must respond with a
ClientAckcontaining the frame number and a one-timetokenprovided in the frame packet. - Timeout: If the server does not receive an ACK for several in-game days, it will disconnect the client with error code 17 (
TimeoutComputer).