I would like to have your opinion on the best way to hide an API key and secret key.
I found 2 ways :
Use NDK like that : https://medium.com/#abhi007tyagi/storing-api-keys-using-android-ndk-6abb0adcadad
Use Gradle like that : http://www.techjini.com/blog/securing-api-key-and-secret-key-in-android
I know that risk 0 does not exist but what is the most secure solution ?
Thank in advance
The NDK seems like your best bet, although not being 100% secure, but it sure is hard to reverse engineer. The gradle way doesn't seem secure at all.
For obfuscation and encryption purposes, you could also take advantage of DexGuard.
To hide secret keys in an Android app, we have developed a free open source alternative to Dexguard. Our hidden-secrets-gradle-plugin uses the NDK and XOR operator to obfuscate keys to prevent reverse engineering.
You can optionally provide a custom encoding/decoding algorithm to improve the security of your key.
Access to the plugin and all the details : https://github.com/klaxit/hidden-secrets-gradle-plugin
The best to secure the key is by not putting your keys in app, for that purpose if you are using a server that is highly secure (eg. Amazon Server) then put your keys on server and access them on run time. And also apply public/private encryption on both app and server side.
But if you want to stay with the app then using "NDK" or using "Proguard" both are highly secure mechanisms on app level.
If you are using oAuth to get a token you can setup a server with the client id and client secret on the your server. Your application gets the oAuth token from your server. This way you do not have to put the client id or client secret in your application that the user downloads and runs.
Related
My end goal is to keep safe my API credentials and that cannot be discovered by decompiling the apk.
Currently, my API credentials are hardcoded at buid.gradle(app module) file.
When I decompiled my own apk using this site I can able to find the API url and other credentials.
Now I am looking for a solution and more interested to know how "google-services.json" file is getting parsed.
If there is a solution to read **my-cred.json** file under app folder at runtime or compile time (the same directory where **google-services.json** exists), I think I can protect my credentials from decompiling the source( correct me if I am wrong)
Please tell me a way to read **my-cred.json** or any other solution to protect the app credentials
In my opinion there is no way to protect this kind of private keys on your Android device. So the solution is simply not to store it on the Android device. But you can store it on an external server. In my case this key is used onyly once per session, to generate a session token. So I simply created a small java app that create the session token from the user id and the api key. That app is hosted on Google App Engine, but any hosting service should do the work. Then your Android app has to invoke this app (servlet) to get a proper token, which is then used to invoke the API.
I know this does not directly answer your question - but it's quite simple to put in place and will avoid your key to be reverse-engineered.
This is only a partial answer, but before you get into complex obfuscation methods, I would recommend you to first check for each API how they actually authenticate your app: Most API services today require you to register the certificate of your app to work, so even with your API key, one wouldn't be able to use the quota of your app since one wouldn't have access to the private key used to sign your app.
After some research i found out you can't reliably hide an app credential into an android app. Several solutions are being described but none of them is 100% secure , as it is pretty easy to reverse an android app.
You can only obfuscate to make an attacker loose time...
Here are some ways to obfuscate your app credentials , but none of them are really secure even the C++/JNI one. https://rammic.github.io/2015/07/28/hiding-secrets-in-android-apps/.
Only way to have it 100% secure is to set up your own server to hold the credentials and do the login for you, or even requests. I think the best way would be using an OAuth2 authentication process.
It depends on the time you have and your security needs.
I'm developing an app that will use text messages to verify a user's telephone number, the usual "enter code" routine.
After reading a little bit it seems like a bad idea to store the private keys for whatever 3rd party I'll use in the app (twilio, nexmo, etc). Somebody could reverse engineer these from my binary and use them in their app.
However, having these on the server doesn't help either, somebody could just reverse engineer my server's endpoint that I use to send text messages and use that instead.
E.g. I could reverse engineer WhatsApp and get the private keys or API endpoints that they use for telephone number verification and just use that in my app, saving me thousand of dollars.
Any ideas on how to protect myself against such an attack?
Hiding API Keys on the server
However, having these on the server doesn't help either, somebody
could just reverse engineer my server's endpoint that I use to send
text messages and use that instead.
Yes it does help a lot.
If somebody gets access to the keys to your web service, they can only do, what your service allows them to do. This is a very good idea to have a web service that encapsulates all the 3d party keys and API - it's way more secure.
Nobody will ever get access to your sensitive keys, that'll allow them to do everything.
For example the 3rd party API allows deleting - your server wrapper API will not allow it.
Moreover, you can add any extra logic or alerts for suspicious behavior.
Hiding API Keys in the app
If somebody sets their mind to it, there's no way you can prevent getting your keys reverse engineered from your app. You can only make that harder. Computer security should never be about "how hard/complicated it is to do", but in this case we have no choice.
Ok, so you have to hardcode the API keys into your source files. It can be easily reverse-engineered.
You can obfuscate your keys, so that they can't be read directly. The result will be that they'll be scattered in a compiled file, rather than comfortably being placed in one place.
On iOS you can use something like this.
On Android you can use DexGuard, or any other way to obfuscate a string.
Encrypting the keys
Another layer of making it hard for hackers is to encrypt the keys.
Here's an example for iOS.
You can do the same for Android.
Perfect Scenario
Ok, so let's say you have a 3rd party API for video management.
The hacker wants to delete all videos on the server, because the 3rd API allows that.
First he has to glue up all the scattered strings in the file. If he manages to do that, he has to find a way to decrypt that.
Even if he manages to decrypt that, that'll give him the API keys to your server and your server and your server only allows to upload videos, not delete them.
I think firebase functions can help us in hiding the third party API keys.
The proposed solution-
Store API keys in firebase as environment variables.
Make a firebase https function that answers to only the authenticated users. If an authenticated user requests it, the secret API key from the firebase environment variable is returned as the response.
Android app does an anonymous login into firebase for the first time, obtains the token.
This token is used as Authorization token in headers while requesting firebase https function. The firebase function would be something like https://us-central1-{your_project_name}.net/{function_name}
I have discussed the approach in detail in this blog and made a sample project
I have a set of rest services exposed on a public host. There are mobile apps (android, iOS and windows) that will be consuming these services. For authentication purpose, I am using a secret key that has been shared with these apps and when they hit the services, the sent key is first matched with the actual key and services are served only when the key matches. My question is that is it possible for a hacker to reverse engineer the mobile apps and obtain that secret key (so that he can misuse the web services)? If yes, then how easy is it to do that and what is the solution to this problem?
The thing is how you are saving the secret key in your app .Now there can be many things
Encrypt you key
Use progaurd
Use private but not default shared-preferences(If saving the key in preferences)
Use HTTPS instead of HTTP
These are some ways with which you can secure your key and make it difficult to reverse the process, but again nothing is completely secure but my doing these steps you can make the much difference .
For iOS use the Keychain to securely save the key. There is a Keychain in Android but it works somewhat differently.
Use https to secure the commutations of the key to the server.
Consider an authentication scheme such as CHAP.
I develop a project with parse.com api. I use api key and client key
I use proguard to improve my app security if anybody can try decompile .apk
But in my app there is a API KEY and CLIENT KEY. How can I hide them or if anybody see those keys what happens?
thanks in advance
You can go through all sorts of machinations to obfuscate your Parse client key and app ID, but ultimately they're always going to be available to a clever person intent on discovering them. That's why protecting your data with proper ACL configurations is key. The suggestion of doing more in your Cloud functions is also a good idea if you want to hide details of your business logic which, if coded in your Android app, could be reverse engineered.
You should always assume those keys will become known, and secure your classes in Parse accordingly using Roles and ACLs.
For extra security use Cloud Functions that have extra security logic in them.
My Android app contains OAuth consumer secret for Twitter's API. At the moment it's in .properties file in plain text, so it takes zero effort for someone to look it up in APK.
Should I take steps to obscure it (like, rot13 or stored in obfuscated Java code)? Or should I actually avoid doing any of that, as it would create false sense of security?
How do people usually distribute/store OAuth secret in Android apps?
How common it is for the secret to be stolen and abused?
The real question is what does an attacker get from stealing it...
You should do your best to protect secrets but at the end, a highly motivated hacker can always get to it in an installed app. So it's the value of the secret vs. difficulty of extraction.
The value of the client secret is impersonating the application. It doesn't give any access to user data. However, since Twitter supports automatic issuance of credentials to previously approved apps (their sign-in with Twitter flow), an attacker can potentially build a web app with your secret and steal user data using a blind redirect.
The problem with Twitter's implementation is that they do not ask the developer about the nature of the application. If they did, they would not have issued you a secret to begin with, and would block anyone building a web application using your client credentials and stealing data from users who already approved it.
Obfuscating is one option, but a weak one. Moving the secret to a web server acting as an API proxy is another, but that just moves the problem elsewhere because now your app has to authenticate against the proxy server. However, this pattern can be reasonably secure if you require users to log into your site (which can use, via web views, Twitter to log in). This way, someone trying to abuse your proxy will need their users to open accounts on your service, which isn't very appealing.
In short, go ahead and obfuscate it. It doesn't hurt. Consider using the proxy pattern too. And maybe let Twitter know their security policies are "not great".
I would definitely read this analysis by one of the OAuth authors, Eran Hammer-Lahav, which cites another article dissecting Twitter's OAuth secret problems.
My advice would be to obfuscate the key so that it cannot trivially be extracted and you should be safe from chancers and spammers.
Hammer-Lahav's opinion is that OAuth secrets should not be revoked and should merely be used for gathering statistics. Hopefully Twitter are following this advice.
To hide your OAuth secret keys in your Android app you can use the gradle plugin we have developed. It is a free open source alternative to Dexguard. Our hidden-secrets-gradle-plugin uses the NDK and XOR operator to obfuscate keys to prevent reverse engineering.
You can optionally provide a custom encoding/decoding algorithm to improve the security of your key.
Access to the plugin and all the details : https://github.com/klaxit/hidden-secrets-gradle-plugin
Main point of 0Auth is that you do not store any precious sensitive information on device -
so it is ok to store secret on device (much better that real user credentials). In case your device secrets are stolen, user can always invalidate access without need to change his credentials