In iOS, how can I store a secret "key" that will allow me to communicate with my server?

I want to store a secret key ("abc123") that I will use in the header of my REST API requests. My server will check this secret key. If it matches "abc123", then allow the request to be made.

I'm thinking about a simple solution like:

let secret = "abc123" 

But are there going to be any downfalls to this?

Answers


Crazy as it sounds, this is probably the best solution. Everything else is more complicated, but not much more secure. Any fancy obfuscation techniques you use are just going to be reverse engineered almost as quickly as they'll find this key. But this static key solution, while wildly insecure, is nearly as secure than the other solutions while imposing nearly no extra complexity. I love it.

It will be broken almost immediately, but so will all the other solutions. So keep it simple.

The one thing that you really want to do here is use HTTPS and pin your certificates. And I'd pick a long, random key that isn't a word. Ideally, it should be a completely random string of bytes, stored as raw values (not characters) so that it doesn't stand out so obviously in your binary. If you want to get crazy, apply a SHA256 to it before sending it (so the actual key never shows up in your binary). Again, this is trivial to break, but it's easy, and won't waste a lot of time developing.

It is unlikely that any effort longer than an hour will be worth the trouble to implement this feature. If you want lots more on the topic, see Secure https encryption for iPhone app to webpage and its links.


By hardcoding the string in your app, it's possible for attackers to decrypt your binary (via tools like dumpdecrypt) and get your string without much trouble (a simple hexdump would include any strings in your app).

There are a few workarounds for this. You could implement an endpoint on your REST API which returns your credentials, that you could then call on launch. Of course, this has its own non-trivial security concerns, and requires an extra HTTP call. I usually wouldn't do it this way.

Another option is to obfuscate the secret key somehow. By doing that, attackers won't be able to instantly recognize your key after decryption. cocoapods-keys is one option which uses this method.

There's no perfect solution here – the best you can do is make it as difficult as possible for an attacker to get a hold of your keys.

(Also, be sure to use HTTPS when sending requests, otherwise that's another good way to compromise your keys.)


While in-band tokens are commonly used for some schemes, you're probably eventually going to implement TLS to protect the network traffic and the tokens. This as Rob Napier mentions in another reply.

Using your own certificate chain here allows the use of existing TLS security and authentication mechanisms and the iOS keychain, and also gives you the option of revoking TLS credentials if (when?) that becomes necessary, and also allows the client to pin its connections to your servers and detect server spoofing if that becomes necessary.

Your own certificate authority and your own certificate chain is free, and your own certificates are — once you get the root certificate loaded into the client — are just as secure as commercially-purchased certificates.

In short, this certificate-based approach combines encryption and authentication, using the existing TLS mechanisms.


It looks like you are using access tokens. I would use Keychain for access tokens. For Client IDs, I would just keep them as a variable because client ids don't change while access tokens change per user, or even per refresh token and keychain is a safe place to store user credentials.


I have used the PFConfig object (a dictionary) that allows you to retrieve in your app values of variables stored as Server environment parameters. Similar to the environment variables that can be retrieved using ENV in web sites server side programming like Ruby or PHP. In my opinion this is about as secure as using Environment variables in Ruby or similar.

PFConfig.getConfigInBackgroundWithBlock{
      (config: PFConfig?, error: NSError?) -> Void in
      if error == nil {
        if let mySecret = config["mySecret"] as? String {
          // myFunction(mySecret)
        }

    }

If you store it like that and if someone tempers with your app, he/she can get an access to your secret key. I would recommend for you to start storing your secret as either #define or user default for now (so you can built your app first), and once you are close to app submission, use keychain Here is an example answer


Need Your Help

Allowing User to Download File from S3 Storage

ruby-on-rails-3 amazon-s3 paperclip

Right now I am using Amazon S3 and Paperclip which is allowing my users to upload an image that is associated with the event they are creating. My ultimate goal is since others can view this event,...

How to Simulate & Test URL rewrite rule in Apache 2, when on sharehosting RewriteLog is disabled/unallowed in .Htaccess?

apache mod-rewrite redirect url-rewriting apache2

How to Simulate & Check a URL rewrite rule in Apache 2, when on sharehosting RewriteLog is disabled and or NOT allowed to be set in .Htaccess? In other words, are there any tools/simulators to ...