Unexposing secret information such as API Key, secret key and others
These days there are so many SDK or services requires API key or secret keys, and often run into sample code for the usage of their sercice something like this. Ok, it’s clear that SDK requires some secret infomation to pass to SDK.
I know some developer embeed those secret information to Info.plist, and read them by code. But if you have inspect your ipa of your app. You will find those secret keys are in info.plist without encrypted. You may wonder what hacker can do with those keys.
MyGreateService(apiKey: "1234", secretKey:"abcd")
Or you may, hard coded like above but hacker may disabbembly your code to get theose secret value. Of cause it may not be easy,
but imagine this SDK is public, and you can build a project using this SDK, you have own api-key
6789 and secret-key
then build you app, you sence that this
wxyz is embbed somewhere in your app binary. So you can search
and you will find the binary code around the part, then you can take a look at targetted application binary to find the simmilar
binary pattern. I have not tried, but I am wonderig it may be easier to crack the code than you think.
I am not a security expert but I like to solve this problem. Yes, there may be better way out there. But I like to solve this probelm for my brain excerrise.
This solution is not for security agency level, I don’t expect to protect the secret keys from NSA class agency for cracking. It should be sufficient to prevent cracking from average casual hackers.
.credencials directory this is where you can play with credencial information. To add or not to add this directory
to source control is depends on your use case. It may be better not to begin with dot for this directory, but I can change it
later when necessary.
There is a property lis file
credentials.plist in the directory, to make this solution simple, this solution assume there is
credentials.plist and all sensitive informations are kept in the form of
.plist. So you can add as many key value based
secret information as possible, but remember do not place large binary or large number of key and value pairs. Try make it
small as possible.
Then you run this script. This script reads
credentials.plist and produce
Credentials.swift which can be added to
your Xcode project.
Please be aware that you should never add
credentials.plist to your project, it ruins all this processes.
codegen.swift as a script, it may affect by updating swift version, so we may need some
mechanisms to prevent swift version issues, but for now, just be aware of the issue.
Here is the produced swift source code. Remember when you made any changes to
credentials.plist, don’t forget to execute
Your Xcode project
Now you can safly use credencial information for you app.
let my_api_key = CREDENTIALS.shared["MY_API_KEY"] as! String let my_secert_key = CREDENTIALS.shared["MY_SECERT_KEY"] as! String MyGreateService(apiKey: my_api_key, secretKey:my_secert_key)
What the heck is CBBA33F3DC70A4502851183DCF579CB1E?
This code uses CREDENTIALS as a typalias of CBBA33F3DC70A4502851183DCF579CB1E. Because class CREDENTIALS can be exposed by
class dump or other equvalent tools. So this solution creates UUID like class name with CREDENTIALS typalias. Then name
CREDENTIALS may not be exposed as a symbol.
You may change
MY_SECERT_KEY to random generated string but code readabilty way down hard to read the code.
So it is up to you for the key name.
Why shared key is not saved as a file?
Since both shared key and encrypted contents are kept in the same source, when the shared key is changed its encrypted contents are chnaged anyway, so it is okay to re-generate shared key as many as you want.
Here is the swift version at this moment of writing this article.
swift-driver version: 1.75.2 Apple Swift version 5.8 (swiftlang-188.8.131.52.2 clang-1403.0.22.11.100) Target: arm64-apple-macosx13.0