3

I am currently implementing SRP on a game I am developing. However, I will be distributing this game server and client, so I would like registration to be allowable on-the-fly, without requiring the host to use some sort of forum or email communication to pre-register the account before the first login. I'll go over the basic flow of SRP, and then my registration changes.

SRP Documentation: Found Here

  1. The User enters their username and password into the client.
  2. The client sends the username and a randomly generated value to the server.
  3. The server gets the salt and password verifier (which is the result of a function on the password, both stored externally) of the user and sends the salt and another randomly generated value to the client.
  4. Each side now independently calculates a strong shared session key, and proves that key to each other.
  5. If both proofs match, the user has successfully authenticated.

To add the registration functionality, here are my proposed changes.

  1. The User enters their username and password into the client.
  2. The client sends the username to the server.
  3. The server checks to see if there currently exists a user with the username sent from the client.
  4. If no user exists, the server sends the RSA Public key to the client, requesting the client to generate a salt, and verifier.
  5. The client sends the salt, public ephemeral value, and verifier to the server, and encodes it with the public key.
  6. The server decodes the salt and verifier with the private key.
  7. Each side now independently calculates a strong shared session key, and proves that key to each other.
  8. If both proofs match, the user has successfully authenticated.
  9. If the user has authenticated sucessfully, the salt and verifier are saved to the database, or file for the user.

Would this be an acceptable, secure form of on-the-fly registration? Or are there some things that I haven't considered?

Edit: It seems that I haven't provided all of the information necessary. The way I'm modeling my game after is similar to Minecraft servers, where users can either download the client and connect to any number of user-hosted servers available, or they themselves can host the server. The difference however is that the Minecraft user accounts are created once, when they register for the account, and when they launch the client, the client authenticates with the official Minecraft servers. I want to leave the userbase management up to the people hosting the servers; that way the only user accounts they know about, are those that have registered with their server.

3
+50

Yes your approach would work.

Some comments though.

Where you say:

  1. The client sends the username and a randomly generated value to the server.

It is not clear what is the purpose of the random value and I don't think that it is necessary.

Later you say:

  1. If no user exists, the server sends the RSA Public key to the client, requesting the client to generate a salt, and verifier.

SRP is designed such that the salt is given to anyone who knows the username who wants to perform a password proof. That can be a hostile attacker trying to guess the password who has learnt the username. So really encrypting the salt upon registration adds no security. You do need to encrypt the verifier to prevent an offline dictionary attack. The salt you can send along with the username at step 2.

For added security it is worth encrypting the username on the wire; an attacker needs to know that to try to guess obvious or very weak passwords. So you are better off using TLS to encrypt the whole registration communication from end-to-end to protect the user identity. Your approach needs an RSA public key to encrypt (at least) the verifier. That involves generating a public private key pair for the server. So it is equivalent effort to generate self signed certificate for each server upon installation. Then you can run TLS for the whole of the registration process with the generated self signed cert.

If you do go with only encrypting the verifier then you must force the user to select a strong password to protect against someone who saw the plain text username guessing a weak password. Even if you encrypt the username people typically use the same username on many services so it is easily guessable; so enforcing a strong password is still a good idea.

(Edit see this answer/question which also suggests an encrypted connection is the way to go https://security.stackexchange.com/a/17245/45960 )

(Edit note as protecting the username is a good idea you should consider using TLS for logging into the game. issue them a 128bit random number as a session token and have them disconnect and reconnect without encryption passing the session token as their credential to map the new unencrypted connection to the user account you issued the token to over TLS. Then they never have to pass thier username in cleartext).

  • The randomly generated value in step 2 is a reference to the A public ephemeral value, which is the hash of a randomly generated number. For TLS, could I generate the RSA Key pair when the server first starts up, and somehow set that up to be used as the connection socket? – Zymus Jan 9 '15 at 0:00
  • No don't send 'A' with the registration. Immediately after the user is registered you want to test that login works so then you send a 'A' as part of the normal login flow appended to the end of the registration flow. – simbo1905 Jan 9 '15 at 8:54
  • Yes first usage of the server you can generate the TSL self signed cert which you don't distribute which is read from a folder writable to the server. You simply have your server launcher wrapper test for the cert files existence, which won't be there on first launch, then your server launcher generates it. – simbo1905 Jan 9 '15 at 9:01
  • Yes, it was a mistake on my part. I edited the post for the correct flow. And thank you for the information, you and cpast have helped me determine how better to secure on-the-fly registration, and SteveSether has helped be stabilize the server against DDoS attacks. – Zymus Jan 9 '15 at 17:10
  • Should TSL be TLS? – cpast Jan 9 '15 at 20:36
2

One thing to consider is bots. You've made the registration very easy and convenient. That also makes it very easy and convenient for griefers, cheaters, or other types of miscreants to create bots that swarm a server.

Depending on what your game is, that might be irrelevant. But automated registration with no CAPTCHA is something you should consider.

  • That is something that I had considered, but instead deferred it to the server host to determine. They could add that specified plugin to the server if they choose. In terms of the mass spamming of new connections, I planned on having a limit for the number of connections per IP address to 1 (ie. a normal player would only need to play on one client normally). Anything more could be considered a DDoS attack and would be logged (if the last login attempt was less than n seconds ago) and ignored (connection closed by the server). But I sense some problems with this approach as well. – Zymus Jan 5 '15 at 19:08
  • The problem with limiting any service like that by IP is that many, many locations have just one outgoing IP. Coffee shops, airports, and multiple people living in the same house all have one IP. So if you started trying to limit to one active connection, you're going to have problems. – Steve Sether Jan 5 '15 at 19:19
  • 1
    One idea to avoid DDos attacks is to put in a "proof of work" into the registration. Force the client end to solve a problem that's easy to create, but hard to solve. The simplest is factoring a number that's the multiplicative product of two large primes. Creating two prime numbers is easy. Multiplying them to create a 3rd number is easy. Factoring the 3rd number to get back the original two is hard. – Steve Sether Jan 6 '15 at 1:57
  • @SteveSether Proof-of-work sounds nice in theory, but it's often not possible to find a cost factor that's acceptable for legitimate users but still big enough to deter spam accounts. – CodesInChaos Jan 9 '15 at 16:08
  • @CodesInChaos I'd agree. But I was talking referring to using a proof of work to prevent DDos attacks. – Steve Sether Jan 9 '15 at 16:17
1

The second-biggest issue I see with the registration is that there is no server authentication. When I'm registering initially, there is no way to verify that I'm talking to the real server, and not a fake one. It doesn't seem like an attacker could intercept traffic with a man-in-the-middle (they can't quickly learn to impersonate me to the server, so the best they can do is pass on my salt and verifier and drop out). However, as soon as the attacker learned my verifier, they could start doing a dictionary attack against it, just as if they had obtained a password hash. Unfortunately, SRP isn't particularly designed to be resistant to dictionary attacks against the verifiers; a common implementation uses just two iterations of SHA-1 and a modular exponentiation. Even if it did use a good password hash, the fact that a password is strongly hashed with a good salt doesn't mean it's fine for an attacker to get the hash, and an attacker will still likely be able to brute-force weak passwords. If the attacker successfully does this, they now have a username and password combo which has a fair chance of working on some other more important websites.

The only way to prevent that attack would involve some form of out-of-band communication. For instance, TLS normally solves it with the X.509-based PKI (which is what protects registration over an HTTPS website).

The first biggest issue is that game development is not normally the place to design a new authentication system, because security is hard. It's much, much better if you stick to standard protocols. Furthermore, doing this will require implementing SRP yourself, and it's also better to stick to standard implementations. So, the best way of doing it would be to use a good SRP implementation as it's designed to be used, and use something else for registration (like TLS or something, where you might accept certificates from standard CAs, and allow self-signeds but warn the user).

  • Okay, thanks for the input. I have a couple of questions. Currently, the flow of the program is that when you start it, it gives you the option to enter the IP Address and port of the server you would like to connect to. That information would likely come from the server host's website, or forum thread. So would that be sufficient to avoid someone faking the server? The other question is, what if I randomly generated the public and private keys for each connection? – Zymus Jan 5 '15 at 6:47
  • @Zymus In general, using IP and port is not sufficient to prevent a connection hijacking (particularly on the local network). It makes it harder, but not impossible. For creating a new keypair per connection, that's the opposite of what you want to do to address this. The issue is that the server isn't authenticating itself to the client before the client sends the verifier. To let the server authenticate to the client, it needs a long-lasting keypair to authenticate itself. The first thing I'd think of is actually to use domain names and use a TLS certificate to authenticate the server. – cpast Jan 5 '15 at 7:36
  • Because of the nature of the game I am creating, that may be a bit difficult. People would be able to download the server, and host their own server with their own modifications made to it, so wouldn't it be up to the server operator to create their own certificate/domain name? Most people who would like to become server operators I feel would not like the idea that they have to invest in both a certificate from a trusted CA, and a domain name (the latter is less of an issue). Or do I misunderstand? – Zymus Jan 5 '15 at 7:44
  • I have updated the OP to include more information about how the hosting will work. – Zymus Jan 5 '15 at 17:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.