views:

280

answers:

4

I'm building a client/server iPhone game, where I would like to keep third-party clients from accessing the server. This is for two reasons: first, my revenue model is to sell the client and give away the service, and second I want to avoid the proliferation of clients that facilitate cheating.

I'm writing the first version of the server in rails, but I'm considering moving to erlang at some point.

I'm considering two approaches:

  1. Generate a "username" (say, a GUID) and hash it (SHA256 or MD5) with a secret shipped with the app, and use the result as the "password". When the client connects with the server, both are sent via HTTP Basic Auth over https. The server hashes the username with the same secret and makes sure that they match.

  2. Ship a client certificate with the iPhone app. The server is configured to require the client certificate to be present.

The first approach has the advantage of being simple, low overhead, and it may be easier to obfuscate the secret in the app.

The second approach is well tested and proven, but might be higher overhead. However, my knowledge of client certificates is at the "read about it in the Delta Airlines in-flight magazine" level. How much bandwidth and processing overhead would this incur? The actual data transferred per request is on the order of a kilobyte.

+2  A: 

Who is your adversary here? Both methods fail to prevent cracked copies of the application from connecting to the server. I think that's the most common problem with iPhone game (or general) development for paid apps.

However, this may protect the server from other non-iPhone clients, as it deters programmers from reverse engineering the network packet interfaces between the iPhone and the server.

notnoop
Good point: see revised question. In any case the cracked copies will always be an issue -- hopefully running the service is cheap enough that serving a bunch of people who wouldn't have bought the app anyway won't really affect my bottom line.
Frank Schmitt
Thanks, I think you've got my thinking reoriented a little closer to reality :).
Frank Schmitt
+3  A: 

No way is perfect--but a challenge/response is better than a key.

A certificate SHOULD use challenge/response. You send a random string, it encrypts it using the certificate's private key, then you get it back and decrypt it with the public key.

Depending on how well supported the stuff is on the iPhone, implementing the thing will be between trivial and challenging.

A nice middle-road I use is xor. It's slightly more secure than a password, trivial to implement and takes at least an hour or two of dedication to hack.

  1. Your app ships with a number built in (key).
  2. When an app connects to you, you generate a random number (with the same number of bits as the key) and send it to the phone
  3. The app gets the number, xor's it with the key and sends the result back.
  4. On the server you xor the returned result with the key which should result in your original random number.

This is only slightly hacker resistant, but you can employ other techniques to make it better like changing the key each time you update your software, hiding the random number with some other random number, etc. There are a lot of tricks to hiding this, but eventually hackers will find it. Changing the methodology with each update might help.

Anyway, xor is a hack but it works for cases where sending a password is just a little to hackable.

The difference between xor and public key is that xor is EASILY reversible by just monitoring a successful conversation, public key is (theoretically) not reversible without significant resources and time.

Bill K
A question and a comment: Wouldn't a SHA256 or MD5 of the concatenation of the token and the secret be better than XOR, without being any harder to implement? Also I'd like to use an access control system that's already baked into HTTP(s), so that I don't need to do any extra round trips (i.e. GET a token, and then do a second GET to grab the game state).
Frank Schmitt
It would be better, but I'm not sure how it gets easier than sendToServer( encryptedValue ^ key ); I guess the reason I use xor is that I don't have to have a library--it's just in my brain, but it's not "good" :)
Bill K
+1  A: 

Have your game users authenticate with their account through OAuth, to authorize them to make game state changes on your server.

If you can't manage to authenticate users, you'd need to authenticate your game application instance somehow. Having authentication credentials embedded in the binary would be a bad idea as application piracy is prevalent and would render your method highly insecure. My SO question on how to limit Apple iPhone application piracy might be of use to you in other ways.

Alex Reynolds
I'm trying eliminate the concept of an "account" as far as the user is concerned. They will only ever access the game through my app, so I don't want to burden them with picking a username that's probably already taken and password that's probably weak.
Frank Schmitt
That link wins you the "answered" credit.
Frank Schmitt
A: 

What about HTTPAuth over SSL?

Libo Cannici