Checking In

Published March 21, 2007
Advertisement
I've had all of fifteen minutes on the project since last time. I made it send the login challenge cookie. W00t!

If you want to know more about authentication for networked games, and what a "challenge cookie" is, read one. I'm also signed up to write a chapter in Game Programming Gems 7 on game authentication, which will likely borrow from my web page above. (As you may know, I also wrote a chapter on NAT traversal, with code, in GPG 5)

In brief, the client sends an empty login packet to the server, which the server takes as a request for a challenge. The server generates a strong random number and sends back to the client. The client computes a cryptographic hash (I'm using SHA-256) of the following items:
- user password
- challenge cookie
The client then returns a packet containing the user name and the hash to the server.
The server looks up the password in the database, and computes the same hash, using the previously emitted cookie. If the hash matches, the server sends success; if not, the server disconnects, which the client takes as a hint that the name or password was wrong.

This way, the password is never transmitted, even encrypted, over the network. Instead, the user must have set up the password beforehand (when registering, say). The draw-back is that the password must be available in cleartext for the server to retrieve, so I'll have to trust whatever IT infrastructure the servers will run on when I'm done.

I'm actually doing a ticket infrastructure, too, a la Kerberos, but I just realized that that's only useful when authentication happens on a machine different from the receiving machine. Right now, I'm having users log in anew each time they change zones (machines), so that's totally useless -- I'd better get rid of it, as it's needless complication.
Previous Entry Untitled
0 likes 6 comments

Comments

Evil Steve
For anyone who cares, MSN uses challenge cookies in almost the same way. When you connect, and every so often (5 or 10 minutes I think), the server sends the client a challenge string, which the client then has to MD5 hash with the client password. The client password isn't your password though, it's a string that's built into the client, and each protocol version uses a different password (Some of which have been leaked on the Internet).

I look forwards to the GPG7 article, I have GPG 1 through 6 so far, all of which have proved usedful in some way.
March 22, 2007 04:33 AM
hplus0603
Yes the challenge hash is a well-known practice. As far as I know, it started being put to good use twenty years ago when Kerberos first came out :-)
Nothing like borrowing from the best to make sure you get a solid system!
March 22, 2007 11:38 AM
Anon Mike
Why not store a hash of the user name/id and password instead of just the password? Everything is the same except that the client has one extra step and you don't have to worry about untrusted IT people being snoopy.
March 22, 2007 02:29 PM
hplus0603
Storing a hash of username/password isn't good enough, because then that hash becomes the new "password," and someone snooping the system can still impersonate the user -- without knowing the password.

If you worry about IT people, then storing a hash of the password, and sending the password over the login connection is the alternative solution. This has strength against snoopy IT people, but has weaknesses in that the password is transmitted from the client on each log-in, and thus needs to be encrypted, which means a public-key crypto is needed. The decrypted password will still be available in core on the server machine (for verification), so a determined IT person will still be able to recover the cleartext password.

Instead of storing the password in cleartext in the database, I might end up using a built-in key in the server to scramble the password, which doesn't significantly add to security, but it prevents accidental disclosure (through looking in logs, etc).
March 23, 2007 03:21 PM
Anon Mike
It's true that storing a hash doesn't stop unscrupulous IT people from getting enough info to impersonate one of your users, in your service, but it does keep them from impersonating that user on some other online service when they use the same password for everything, as most people do.
March 23, 2007 04:01 PM
hplus0603
I thought I just proved that it doesn't even stop that -- the cleartext password needs to be visible in RAM of the server process to be hashed for comparison, so an unscrupulous operator could still extract the password (albeit with slightly more effort required to read /proc/mem or similar).

The closest you can get to avoid that problem is to store the internal state of the hashing function at an intermediate state, where you have hashed the name and password, and sufficient padding. Then, when verifying password, have the user compute hash(name+password+padding+cookie) and then, on the client side, restore state of the hash function, and add the cookie, to get a comparable number.

Unfortunately, getting the intermediate state of the hash function will usually significantly weaken the strength of the hash (as the internal state is usually at least twice the size of the produced digest). At least the operator, at that point, needs to know a bit of applied cryptography to extract good guesses for the password.

However, for this system, for now, I am the operator, and I trust myself. I will store the password in a lightly shrouded form, though, to work around the "log file" or "table browsing" problem.
March 23, 2007 06:11 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement