views:

688

answers:

2

I need my application to use client's phone-number to generate unique ID for my web-service. Of course a phone-number is unique, but it must be secured. So it can be implemented with symmetric encryption (asymmetric will be later, because leak of resources), but I do not know where to store a encryption-key.

1.

I do not know why, but seems bad to store a key as a static field in code. May be because it's too easy to read it from here even not running an application.

2.

It seems better to store a key in Keychain and get it from here by request. But to avoid #1 it's necessary to install a key to Keychain while installation process. Is it possible? How to do that?

3.

I do not know what certificates do. Are they helpful to the problem?

4.

To transfer a key from server is also a bad idea, because it's very easy to sniffer it.

+2  A: 

I don't think you're going to be able to do what you want securely with symmetric encryption. With asym you can send the public key without worrying about it too much (only threat is someone substituting your key with their own) and validate the encrypted unique id on your server with the private key.

Patrick
Thanks for quick response.Firstly asym encryption is 100-1000 times longer to decrypt and cpu become a critical resource this way. So I decided to use sym encryption.Secondly, the problem of storing public key securely is still exists, because somebody who catches public key will be able to send data as another person.
slatvick
+4  A: 

The way you solve the sniffing problem is that you communicate over HTTPS for your web service. NSURLConnection will do this easily, and all web service engines I know of handle HTTPS without trouble. This will get rid of many of your problems right away.

On which machine is the 100-1000x decrypt the bottleneck? Is your server so busy that it can't do an asym decryption? You should be doing this so infrequently on the phone that it should be irrelevant. I'm not saying asym is the answer here; only that its performance overhead shouldn't be the issue for securing a single string, decrypted once.

Your service requires SMS such that all users must provide their phone number? Are you trying to automate grabbing the phone number, or do you let the user enter it themselves? Automatically grabbing the phone number through the private APIs (or the non-private but undocumented configuration data) and sending that to a server is likely to run afoul of terms of service. This is a specific use-case Apple wants to protect the user from. You definitely need to be very clear in your UI that you are doing this and get explicit user permission.

Personally I'd authenticate as follows:

  • Server sends challenge byte
  • Client sends UUID, date, and hash(UUID+challenge+userPassword+obfuscationKey+date).
  • Server calculates same, makes sure date is in legal range (30-60s is good) and validates.
  • At this point I generally have the server generate a long, sparse, random session id which the client may use for the remainder of this "session" (anywhere from the next few minutes to the next year) rather than re-authenticating in every message.

ObfuscationKey is a secret key you hardcode into your program and server to make it harder for third parties to create bogus clients. It is not possible, period, not possible, to securely ensure that only your client can talk to your server. The obfuscationKey helps, however, especially on iPhone where reverse engineering is more difficult. Using UUID also helps because it is much less known to third-parties than phone number.

Note "userPassword" in there. The user should authenticate using something only the user knows. Neither the UUID nor the phone number is such a thing.

The system above, plus HTTPS, should be straightforward to implement (I've done it many times in many languages), have good performance, and be secure to an appropriate level for a broad range of "appropriate."

Rob Napier
1.Where could I find that terms of service to be sure? 2. What iPhone SDK classes should I use to hash? 3. Thanks for that! I need a little time to think over and then ask more questions or accept.
slatvick
1. Read the "iPhone SDK Agreement" on the main iPhone developer portal. It of course references unspecified "Apple's best practices" which gets back to the fact that you cannot ever be 100% certain what you may and may not do. 2. SHA1 is good for this kind of hashing. Take a look at http://github.com/ameingast/cocoacryptohashing.
Rob Napier
Let me a little specify my needed: i have a client-server game and do not want players to be tired cause classic login-pass registration. It seems I can use a UUID instead, if it's legal. The sniffing problem is looked solved by using HTTPS, as I understand an entire HTTP-package is encrypted and impossible to be sniffed. It's seemed enough and the simplest way to substitute registration and protect from dishonesty, right?
slatvick
The UUID is likely a very good choice for this kind of problem, if what you are looking for is reasonable security for a game. UUIDs are not easily guessed, but they are a common identification token, so other developers can create large databases of these numbers and use them to impersonate other users. For keeping track of high-scores, this isn't a big deal, and so UUID is the recommended identification token by Apple. To be clear, we are discussing [[UIDevice currentDevice] uniqueIdentifier] when we say "UUID" here.
Rob Napier
Thanks. Decided to use UUID via https. It's save and efficient enough, although UUID is not short string as DB-key is)
slatvick