Beginner Packet Encryption

Started by
17 comments, last by hplus0603 10 years, 11 months ago

I hope I am not bringing up a question that is already answered, if it has, a point in the right direction would be appreciated, but in all my searching I can't seem to find my exact answer to my question.

I have fully functioning MMO with client/server communication. Players download the client obviously, and the server is located remotely (currently controlled only by me) an an Amazon AWS server.

So my basic is question is this. Players create their account for my game from within the client (email, username, password, etc), store this on the server (currently encrypted on the client using a simple XOR encryption, then sent to the server ). And now of course I am looking to now finally make this packet encryption more legitimate and professional.

While researching this, I find people asking similar questions, but I see them jumping right into terms like already having "SSL encryption", sending "salts" and "hashing" the data, but I need to know where to begin from step 1. I am not finding a step-by-step general procedure for beginning to encrypt packets, and figuring out which method I should be doing. It seems like this is more complicated than just writing some simple algorithms and hashing data.

I am attempting to make my game secure enough so that if I do start charging money for the game, or just make the game go "live", I can tell my players "Your login information is secure". I am not interested in dealing with any real money account information at this point. Just one step at a time.

I am basically looking for a guideline of where to start with this. The simplest answer is basically what I am looking for. My game is currently communicating with Winsock, and for now is going to be windows platform specific. Coded in C++.

Should I just look into using something like OpenSSL and go from there?

--------------------------Vantage: Greenlit on Steam / Independent Games Festival Submission http://www.crystaldragon.com

Advertisement

Basically, yes, you have the right idea. Use Transport Layer Security (TLS) because it doesn't really interfere with the rest of the network program.

The salt and XOR during transmission isn't really useful. You need to just encrypt your communication. This will ensure that when a player connects to your server nobody can intercept or modify the content.

If you already have your app with WinSock, you can use the WSASetSocketSecurity() function. It will either require that a secure connection is established or fail to connect.

You might also consider using SChannel, which is Microsoft's implementation of the wrapper. Here's an example where it is used in practice. It is a little more complex but it also gives more control than the simple success/fail model.

Those sound like the solutions I may be looking for, I will begin researching those immediately, thanks for the reply!

--------------------------Vantage: Greenlit on Steam / Independent Games Festival Submission http://www.crystaldragon.com

Before you spend too much time on this: What particular kind of attack are you trying to guard against?

Chances are that changing from your plain TCP connection to TLS at this point in your game development is largely a waste of time, because the real problem you're having is likely getting enough people to think the game is fun that they come back and play again :-)
enum Bool { True, False, FileNotFound };

So, XOR is meaningless. Really, seriously, honestly, you might as well ROT-13 it, meaningless.

Here are some basics on cryptography for data-at-rest.


One, don't write your own. Just don't go there. Get a tested library, use that.

Two, in an ideal world, you want to be able to swap out your crypto algorithm if a problem arises in it. So your code shouldn't be deeply tied to the cryptographic routine you are using. This is generally termed "crypto-agility".

Three, salts and hashes. So, a cryptographic hash is a one way conversion. You take a value (say, a password), and you generate a hash of it. In order to get the original from the hash, you would have to just generate values until you got one that matched the same hash (more on this later). You then store the hash in your database (so you never keep the actual plaintext of the password in your database). A salt is a value that you derive deterministically from the account (whether it is intrinsic to the account or simply a random value stored with the account) that you add to the password before hashing it. What this does is mean that if Bob has password "123456" and Alice also has password "123456", they still have different hashes in your database. Otherwise, if I hash "123456", I can immediately get every account that used that password. On the other hand, if I get your database, and I want to get Bob's password only, it doesn't make a difference.

Which brings us to four, hashes continued. Counter-intuitively, you want to use *slow* algorithms for hashing when you are picking your algorithm. The reason for this is that you can afford the extra time to hash a password on login, but you make it much harder for someone to brute force things. Remember how we said you'd have to algorithmically generate strings until we got our hash again? That's why you want a slow algorithm (ex. bcrypt).

Now most of what I just said only applies to the password.


Storing other information is also important, and can have real legal repercussions depending on where the servers are located (for example, if you were suddenly running on a server in the EU, you fall into EU privacy laws), and if you start dealing with Credit Cards you have all sorts of contractual headaches about data storage. The easiest way to secure data is not to have it, so always consider whether or not you need a piece of information at all.

If you are storing it, consider what parts of your server actually need it, and when, and keep the data encrypted at rest. You may want to have the service that actually needs that information on a separate server (one that doesn't handle the untrusted input that is user interactions on a regular basis), such that even if someone were able to get control of the game server, they wouldn't be able to pivot to get the user information.

And finally, I am not a cryptographer. It is entirely possible that I made an error, especially since I'm just jotting this post off, and I'm certainly not a lawyer.

Thanks for all the information, that is all extremely useful. I am currently running all my information through TCP. I do not know what the difference between using TCP and TLS until I start looking into this more, however I am only planning on trying to sending only account information this way (email, login, password) so I am only going to send a few packets securely for now.

I am not going to attempt to do any type of monetary transactions of any kind (credit cards, virtual goods/cash etc ). If I get to that point I will rely on a third party, but I am not near that stage just yet. However I may want people to receive a "CD-key" to register their game (free or paid) off a website login at some point which they would enter as well, but will be the extent of how far I go with this until I rely on more professionally secure methods for money transactions.

As I mentioned before I would just like to assure people who play game that their information is "secure" when they send it and it is stored on the server. I realize it can never be 100% foolproof. But again, its better then what I am doing now.

I am not trying to guard against any particular type of attack, just trying to do a general secure encryption for this information.

--------------------------Vantage: Greenlit on Steam / Independent Games Festival Submission http://www.crystaldragon.com

I found this great post on Stack Overflow which seems to describe what I should be doing based off of your suggestions as well:

http://stackoverflow.com/questions/5415752/how-to-save-string-username-password-in-encrypted-form-in-database-and-decryp

It explains that you should salt and hash the password using the SHA-256 algorithm from OpenSSL.

But a few questions still linger.

How should I still send the password (and other info like login/email) to the server by itself so I can still salt/hash it? Should just still be sending it through WSASetSocketSecurity() be safe enough since I will be salt/hashing it on server and not storing the password in any way on the server? (Should I be masking the data somehow to deter packet sniffers? etc..)

Does WSASetSocketSecurity() have any performance issues? Should I just leave it on for the player the whole game? Or just use it when sending sensitive information packets?

I hope I am thinking about this the right way. Of all my years programming I just seem to have a bit of trouble wrapping my head around this.

--------------------------Vantage: Greenlit on Steam / Independent Games Festival Submission http://www.crystaldragon.com

Don't transmit password data directly if you can avoid it. Use a method like SRP to handshake instead.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Okay so this is what I am thinking so far...

I will open up my TCP socket and add WSASetSocketSecurity to it.

I will implement a self-made SRP Protocol to the character string.

I will use the SHA-256 hash algorithm from OpenSSL for the SRP hash

The SRP pseudocode from wikipedia makes it seem simple enough to implement by hand.

I really don't know the stability, uses, or performance issues of doing this. The documentation for those issues seem non-existant. I am assuming this will provide "enough" protection for account information, without completely converting my code from TCP to TLS.

Any thoughts?

--------------------------Vantage: Greenlit on Steam / Independent Games Festival Submission http://www.crystaldragon.com

Before you spend too much time on this: What particular kind of attack are you trying to guard against?
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement