Swift3 - How to Protect Secret Key

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

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.

Secure keys in iOS App scenario, is it safe?

Let me try to break down your question to multiple subquestions/assumption:

Assumptions:

a) Keychain is safe place

Actually, it's not that safe. If your application is installed on jailbroked device, a hacker will be able to get your keys from the keychain

Questions:

a) Is there a way to put some key into an app (binary which is delivered form AppStore) and be completely secure?

Short answer is NO. As soon as there is something in your binary, it could be reverse engineered.

b) Will obfuscation help?

Yes. It will increase time for a hacker to figure it out. If the keys which you have in app will "cost" less than a time spend on reverse engineering - generally speaking, you are good.

However, in most cases, security through obscurity is bad practice, It gives you a feeling that you are secure, but you aren't.

So, this could be one of security measures, but you need to have other security measures in place too.

c) What should I do in such case?*

It's hard to give you a good solution without knowing background what you are trying to do.

As example, why everybody should have access to the same Amazon S3? Do they need to read-only or write (as pointed out by Kendall Helmstetter Gein).

I believe one of the most secure scenarios would be something like that:

  • Your application should be passcode protected
  • First time you enter your application it requests a user to authenticate (enter his username, password) to the server
  • This authenticates against your server or other authentication provider (e.g. Google)
  • The server sends some authentication token to a device (quite often it's some type of cookie).
  • You encrypt this token based on hash of your application passcode and save it in keychain in this form
  • And now you can do one of two things:

    • hand over specific keys from the server to the client (so each client will have their own keys) and encrypt them with the hash of your application passcode
    • handle all operation with S3 on the server (and require client to send)

This way your protect from multiple possible attacks.

c) Whoooa.... I don't plan to implement all of this stuff which you just wrote, because it will take me months. Is there anything simpler?

I think it would be useful, if you have one set of keys per client.

If even this is too much then download encrypted keys from the server and save them in encrypted form on the device and have decryption key hardcoded into your app. I would say it's minimally invasive and at least your binary doesn't have keys in it.

P.S. Both Kendall and Rob are right.

Update 1 (based on new info)

First of all, have you seen in app purchase programming guide.

There is very good drawing under Server Product Model. This model protects against somebody who didn't buy new levels. There will be no amazon keys embedded in your application and your server side will hand over levels when it will receive receipt of purchase.

There is no perfect solution to protect against somebody who purchased the content (and decided to rip it off from your application), because at the end of days your application will have the content downloaded to a device and will need it in plain (unencrypted form) at some point of time.

If you are really concerned about this case, I would recommend to encrypt all your assets and hand over it in encrypted form from the server together with encryption key. Encryption key should be generated per client and asset should be encrypted using it.

This won't stop any advanced hacker, but at least it will protect from somebody using iExplorer and just copying files (since they will be encrypted).

Update 2

One more thing regarding update 1. You should store files unencrypted and store encryption key somewhere (e.g. in keychain).

In case your game requires internet connection, the best idea is to not store encryption key on the device at all. You can get it from the server each time when your app is started.

Saving Stripe's secret key in your flutter app

Mobile App Binary Static Analysis

How unsafe is to save your stripe secret key inside your app?

Extremely unsafe, because a lot of Open Source tools exists to help you achieve this task in minutes, like the MobSF - Mobile Security Framework

Mobile Security Framework is an automated, all-in-one mobile application (Android/iOS/Windows) pen-testing framework capable of performing static analysis, dynamic analysis, malware analysis and web API testing.

You can see how I have used MobSF tool to do it in my article
How to Extract an API key from a Mobile App with Static Binary Analysis:

The range of open source tools available for reverse engineering is huge, and we really can't scratch the surface of this topic in this article, but instead, we will focus in using the Mobile Security Framework(MobSF) to demonstrate how to reverse engineer the APK of our mobile app. MobSF is a collection of open-source tools that present their results in an attractive dashboard, but the same tools used under the hood within MobSF and elsewhere can be used individually to achieve the same results.

The article even shows you how you can use the strings command in Linux to find possible candidates for secrets in your mobile app binary.

How hard can it be?

I know you can decompile and reverse the APK or get access to the RAM and get the key from there, but how hard is it?

If you read the above linked article you already know by now how easy is to extract a secret from a mobile app binary.

From RAM is not so easy, but is also not too much harder, because once more a lot of open source tools exists to help you with this task, and the most popular one seems to be Frida:

Inject your own scripts into black box processes. Hook any function, spy on crypto APIs or trace private application code, no source code needed. Edit, hit save, and instantly see the results. All without compilation steps or program restarts.

Firebase

Or return it via Firebase Remote Config?

Well, this one is also not too much hard to overcome, because the attacker just needs to use Frida to hook at runtime to the function that returns or uses the secret and then extracts it.

Security is not an option

Is it worth doing stuff "In the easy way" at least for the beginning when your app isn't used that much?

No, it isn't, absolutely not. In this case, your secret represents money, it's a secret to access a payment gateway. Can you imagine the financial impact of an attacker using your Stripe account in your behalf?

But even in other scenarios, a secret stored in the mobile app can have a huge impact in financial losses for your business because normally they are used to access the third party paid services, thus if an attackers get its hands on it then he can use the service while you pay the bill, and normally you will only discover it when you provider sends you the bill or a high usage alert.

So do you really want to take the risk?

Third-Party APIs access

How unsafe is to save your stripe secret key inside your app? Or return it via Firebase Remote Config?

Never access third party APIs from within your mobile app, unless it's technically impossible to do it from your own backend or a Reverse proxy you have total control of.

You can learn more on my article Using a Reverse Proxy to Protect Third-Party APIs

In this article you will start by learning what Third Party APIs are, and why you shouldn’t access them directly from within your mobile app. Next you will learn what a Reverse Proxy is, followed by when and why you should use it to protect the access to the Third Party APIs used in your mobile app.

Do You Want To Go The Extra Mile?

In any response to a security question, I always like to reference the excellent work from the OWASP foundation.

For APIS

OWASP API Security Top 10

The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.

For Mobile Apps

OWASP Mobile Security Project - Top 10 risks

The OWASP Mobile Security Project is a centralized resource intended to give developers and security teams the resources they need to build and maintain secure mobile applications. Through the project, our goal is to classify mobile security risks and provide developmental controls to reduce their impact or likelihood of exploitation.

OWASP - Mobile Security Testing Guide:

The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.

How to hide API keys in GitHub for iOS (SWIFT) projects?

You can use a .plist file where you store all your important keys. It is very important to put this file into your .gitignore file.

In your case, you need to set your keys.plist file like this:
Sample Image

And use it inside your AppDelegate as follows:

    var keys: NSDictionary?

if let path = NSBundle.mainBundle().pathForResource("Keys", ofType: "plist") {
keys = NSDictionary(contentsOfFile: path)
}
if let dict = keys {
let applicationId = dict["parseApplicationId"] as? String
let clientKey = dict["parseClientKey"] as? String

// Initialize Parse.
Parse.setApplicationId(applicationId!, clientKey: clientKey!)
}

SWIFT 3 Update:

 if let path = Bundle.main.path(forResource: "Keys", ofType: "plist") {
keys = NSDictionary(contentsOfFile: path)
}


Related Topics



Leave a reply



Submit