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.
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 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.
The next Android app I am creating uses third party APIs for: 1. Google API for geolocation. 2. Google APIs for Translation and 3. Zopim APIs for support chat.
Now almost all such service providers uses 'KEY' to uniquely identify who is requesting data. To implement these services I need to use the unique KEY they give me while I sign up.
Now the KEY is nothing but a String. What concerns me is, it is very easy to decompile APKs to source code. In that case, is it possible that somebody can use my app's APK to read the KEY and misuse it?
If yes, what is the solution to it? There are many apps out there that uses such KEYS from service providers. What do they do?
You can save those keys encrypted in your app server and send them securely via SSL on log in
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 want to hide some data that is entered by user in user's phone encrypted. As far as I know I can encrypt/decrypt data using a key/seed value, but if I hide the key value in code, I know it can be found somehow (e.g. decompiling the Java code).
Do you have any suggestions to make the process harder?
It is impossible to hide the key in the app such that a resourceful hacker won't be able to pull it out. You can try to obfuscate the key and make it difficult to find but it will always be do able.
See this: https://www.excelsior-usa.com/articles/java-obfuscators.html#examples
The best option would be to require your users to specify a PIN or password and to use that as the encryption key. That way if the device is lost or stolen the key is still safe and it also prevents someone from decompiling your app and getting the encryption key for all instances of your application.
One of the new features in Ice Cream Sandwich (Android 4.0) is the keychain API. From the Platform Highlights page (emphasis mine):
Android 4.0 makes it easier for applications to manage authentication
and secure sessions. A new keychain API and underlying encrypted
storage let applications store and retrieve private keys and their
corresponding certificate chains. Any application can use the keychain
API to install and store user certificates and CAs securely.
If you're doing this for username/password data, you should checkout implementing an Authenticator.
Since android does not have any secure storage on it ( at least as of 2.2), you would have to write your own.
The only way to do this really securely is to encrypt with a key derived from a user supplied password (PBKDF2/ RFc2898 being the way to that). Crypto is only as secure as your key and if you store that on the phone in anyway, then someone can find it and use it. This allows you to have the user store the key without actually remembering a large AES key.
There may be libraries that do this for android. I wrote one for windows phone that can be found here if you want some basis for how to do it.
If encryption/decryption all happens on the handset, a determined hacker will be able to crack it. You can make life harder by using obfustication, or (if appropriate for your application), adding user input into the encrypt/decrypt code.
If your application requires network connectivity, it might be worth off-loading some of the code to a server running elsewhere, so that encrypted data lives on the device, but keys are downloaded at run-time. Still not hack-proof, but it reduces risks to confidential data on a stolen device.