Some client encryption design thoughts

Published by

on

My goal was to get libsodium integrated, but I quickly realized I need more systems. For one, I need an LRU cache for storing client keys. Our clients will need to prove they are legitimate before we enqueue their packets, the only way we can do this is if we have some way to determine their packets are legit. We do this by using AEAD encryption with Additional Authenticated Data (AAD). The ADD section is not encrypted, meaning we can read it prior to decrypting, this is where we will pass the UserId.

With the UserID as part of the AAD, we can strip it out, look up in our cache/crypto module what that user’s key is, then attempt to decrypt the data. If it fails, guess what? Invalid user, or a jerk or whatever, so we don’t enqueue. Keep in mind AAD is included in the signature, so any tampering will cause the signature validation to fail. If we do decrypt it, boom we can enqueue and pass to our server loop.

How do we get said keys you may be wondering? In the future I’ll have a login system that generates or /derives/ a key once a user logs in. This will be temporary for that users session and be passed to the game world server via a socket or stuffed in a database or whatever. The game server will read in this key and internally map it to a cache system with that Users Id. Bingo bango we can now accept their UDP packets and verify it’s them.

Here’s a dope diagram from draw.io:

Pretty straight forward, our user would login to the AuthServer and on success would generate a temporary key for them and pass it back to the client. The AuthServer then notifies the Game Server that this User Id + key combo will be available soon. The client then starts blastin’ packets to the game server with it’s data encrypted with the key from the AuthServer. Since we can pull out the UserId from the AAD of the encrypted packet, we can look up their key, pull it from cache (or worst case, a DB) and then start decrypting packets.

So why a cache? Well we can’t just be looking up in a database or RPC out to another server for EVERY UDP packet that comes in, hence the cache. I went with LRU as I figured once clients died off they’d just get removed from the cache automatically. I could change this if a different caching strategy is required.

Anyways, I’m making progress, just added in the stub of the crypto module and some utilities I’ll need. As always, the code is available. I’ll do another post on the actual usage of the crypto module in another post.

I’m some what annoyed however, since libsodium doesn’t have a CMake build I had to third_party vendor it. I was really hoping to avoid such things, I really hate the c++ ecosystem, really which a good package manager existed!

Anyways…

Previous Post
Next Post