I am designing an online multiplayer game and I am looking for a good tradeoff of secure communications with minimal CPU and bandwidth utilization. My ideal solution would only use UDP packets since TCP is a poor choice for the realtime requirement of the game. However, I have no problem falling back on TCP for the login server.
Here is my idea.
When users first login to the service:
- Users connect to an authentication server (which holds a Verisign cerficate) via SSL.
- The authentication server validates the user's login credentials.
- If the login is valid, then two 256-bit AES public/private key pairs are generated by the server. The user is sent one private key and one public key to remember, which can later be used for symmetric communication. The server remembers the opposing key pairs.
- Additionally, a random 32-bit integer is generated and sent to the user. I will call this the "obfuscation key" for now.
- The SSL connection is ended. From here on, all of the data is sent through UDP.
Whenever a user needs to perform a secure transaction with a server:
- For requests, the payload is encrypted using the public key that the client received.
- For responses, the payload is decrypted using the private key that the client received.
My first question -- is this safe and advisable?
The other problem I am trying to solve is sending timely packets for updates that don't have to be as secure but are extremely frequent, such as player movement and position.
Sending the data in the clear is dangerous due to trivial packet replay and man-in-the-middle attacks. However, I believe that performing the AES encryption for every such packet would be too CPU intensive. Instead, I am considering a simple XOR cipher obfuscation as follows:
- Create a key for the XOR cipher by XOR-ing a 32-bit timestamp with the "obfuscation key" received earlier.
- Apply the XOR cipher to the payload of the UDP packet.
- Send the UDP packet with the timestamp in the header plus the obfuscated payload. This way the server can de-obfuscate using the same timestamp.
One thing I hope to accomplish with this is to simply deter packet sniffers and "script kiddies" who might try to trivially reverse engineer the protocol. Another concern is preventing packet replay attacks, which is the reason for including the timestamp in the XOR cipher. Finally, I'm hoping that adding the "obfuscation key" into the mix will prevent trivial man-in-the-middle attacks.
My second question -- is there a simpler and/or more effective way to hit these goals?
I realize these are loaded questions, so thank you in advance for taking the time to read this.