Secure Secrets in iOS app

Shahrukh Alam
Swift India
Published in
6 min readNov 13, 2020

How do we store our secrets on the client-side? Are we really vulnerable to attacks? Is it really worthwhile to take the measures to store them securely?

Almost all the iOS apps have some secret keys to protect like:

  • API keys
  • Private Headers
  • Cryptographic Keys
  • Passwords

These keys are needed:

  • to set up third-party SDKs
  • to authenticate with backend APIs
  • to automate build process or to use in any developer tools, such as communicating to Apple Developer Account or App Store Connect

But imagine a situation, where they are compromised, for instance, if someone gets hold of our Firebase API key, now he/she can easily misuse or overuse our paid credentials if he/she is determined & skilled to hack into few other related keys.

Q: Are our keys really this vulnerable to attacks?

A: Yes & No
Yes: If we hardcode them in the source code or if we push them on the source control.
No: If we take some basic measures to secure them, also it takes little determination and a lot of skills from a hacker to extract or debug them from the binary.

Q: Is it really worthwhile to take the measures to store them securely?

A: Yes & No
Yes: Because they are our App Secrets

If you would keep your secret from an enemy, tell it not to a friend.
- Benjamin Franklin from NSHipster

No: Because we can’t make it 100% hack-free

Be aware you should authenticate users, not authenticate an app. It’s mathematically impossible to hide data perfectly yet still be able to access it from your code.
- Chris Hulbert from Splinter

The only way to keep a secret is to never have one.
- Julian Assange from NSHipster

How do we store our secrets on the client-side?

There are various ways to do it, it’s covered beautifully in this NSHipster Article by Mattt. The most effective one is Obfuscating which is discussed in length by Chris Hulbert here & here.

We are going to discuss the easiest, yet quite effective Apple’s way, by using Xcode Configurations and Info.plist.

Step 1:

We start with an initial commit to SecureAPIKeys Project.

Step 2:

We add a New Config File in the Project

Step 3:

Please make sure you don’t check any Targets which is also the default in Xcode

Step 4:

Let’s add an API Key in the Config.xcconfig

Step 5:

Add Config.xcconfig to the gitignore. This step is very important as we don’t want it to be available to everyone who has access to our repo.
If due to some reason our repo is compromised, the hacker won’t get hold of our secrets.

Step 6:

Let’s add the API Key to our info.plist. The API_KEY in our Config.xcconfig acts as a User-defined Variable which can be accessed by $(API_KEY) on the info.plist.

Step 7:

Let’s set the Config.xcconfig to the Configurations to our App Project.
You can always create different xcconfigs for Debug & Release, for simplicity of this article we will keep one.

Step 8:

Let’s do a simple check if we can access our API Key in the code.

Now let’s build & run for both Debug & Release, it should look something like this in both:

Validation:

Let’s add a hardcoded API Key just to see how it can be hacked but the API Key from xcconfig might not.

Now let’s create an Archive. Find the Archive by Show in Finder from Organiser. Go to App Executable folder by Show Package Contents on the Archive -> Products -> Applications. Find the App Binary by Show Package Contents on App Executable. It will look something like this:

cd to this folder in Terminal & run strings command on the App Binary. You can find HARDCODED_API_KEY, but not API_KEY from xcconfig.
There are many tools like hex editor or MachOView out there which makes this hack & peek really easy.

Now the question might come, where is our API_KEY from the xcconfig? It’s sitting on the info.plist in App Executable.

If you would open it, you can find the API_KEY with its value exposed.

Here, someone might argue that it’s easily hackable, may be easier than our HARDCODED_API_KEY. But, I believe if someone has an access to our Archive, then he/she is an inside man/woman who already knows the value and he/she is the one who created it in the first place.

Now, let’s talk about a hacker, an outsider. He/She can hack into our repo or the App Binary. In either case, he/she won’t get to know about our Config.xcconfig from the repo or the API_KEY from the App Binary.

Now, let’s talk about a rare, but a critical scenario where the hacker gets the entire code from an employee’s machine. In this situation, most of the methods would fail including the one we discussed.

If you have gone through the NSHipster article, let’s go through how all the methods might fail:

  • Hard-Code Secrets in Source Code: This is too easy.
  • Xcode Configuration and Info.plist: This is also very easy as the hacker can find the Config.xcconfig given to the employee secretly/separately for the project to work.
  • Obfuscate: The hacker would know the Salt used to encode or decode the keys.
  • Cocoapod-Keys: Key names are in the Podfile. The generated Objective-C classes are stored in the Pods/CocoaPodsKeys directory. Someone skillful can easily break the scrambled versions of the keys.

The only ways left are:

  • Don’t Store Secrets On-Device: Store them on your own Server or iCloud. Once a secure connection is made, store them in the client’s Secure Enclave like Keychain. But, is it worth it?

A secret in Secure Enclave is safe, but that is not what secrets are for.
- Mattt from NSHipster

  • Don’t Store Secrets at all: It’s the most difficult, but the best way to go about the secret keys.
Courtesy: Bob Dylan

Conclusion:

Try to avoid using Secret Keys wherever possible. If not, try adding some measures to hide them from attackers.
Use Secure Network Connections like Transport Layer Security (TSL) by using Apple’s Network Framework or App Transport Security of URLSession as explained in the WWDC Video 2019 (13:00).
Use SSL Certificate Pinning to stay safe from Bots, Proxies, or Man-in-the-Middle Attacks.

You could find the full code on Github: SecureAPIKeys

Happy Coding & Sharing 😍
Cheers 🍺
Shahrukh Alam

--

--