I have been doing an Android project involving restful web services. What is the best way to keep API key safe. I have read a lot online. Many say it is safe to keep key in the server and use it and that it will be safe. I don't understand what that means. By my understanding saving key in the server means that the app needs to fetch it during operation by using volley or any other httpclient by providing an url. The attacker can decompile the apk file and see the url from which the key is obtained, get the key and do his nasty work. Am I getting things wrong? How can storing API key in the server be safe? Please help me understand.
you should write something like a SecureStorage using the Android Keystore and SharedPreferences and put the string inside it. We are currently developing such a library --> have a look at it here
Related
A few days ago one person decompiled my app and show me an issue in my source code. I was hardcoding the links and the password of my server in source code of the app, I didn't know through decompiling anyone can see my source code. I use proguard but proguard doesn't obfuscate strings. This left me wondering how is the right way to do this? How can my app make api calls and the server can authenticate it? I did a research but I did't see much content talking about this. My app doesn't manage users and passwords. The user and password that I store in my code are the ones to login in the server.
Yes, it is pretty easy to see decompiled Java code to get keys and the like.
There are a few things to do:
Ensure the "application keys" or "tokens" are not a secret with deep admin privileges. Many SaaS / API Providers give you multiple keys. One is a client key that is limited in privileges/actions that can be performed, and a server key that has more privileges but won't be leaked out via client code. In you case, you shouldn't share the same server login/admin passwords. Leverage Principle of least privilege (https://en.wikipedia.org/wiki/Principle_of_least_privilege)
Ensure the string is a static final. In this case, Compiler and Proguard which allow string inlining. This makes it a little harder to know what the string is for. If you have a single "Config" class, it's pretty easy to search for 'facebook' in facebookAppId, 'secret' googleSecret, etc.
To be really secure, you can perform some encryption, or other algorithm on the string, but this means you also store the encryption secret in the code itself also.
In general, I believe (1) gives the most since you should always assume any string in client can be found/hacked, whether Android/Java with Proguard or minified javascript.
I am deciding the mechanism to protect Android App and data. I did some research, but don't know if below solutions are enough or not. See if any expert can provide me some advice:
For SQLite database-level protection: Use SQLCipher
For SQLite data-level protection: Use AES256 to encrypt and decrypt (But don't know where to store the secret key is better?)
For Android data to Web Service(PHP): Use SSL and Post method
For Web Service(PHP) Json to Android: Use SSL and Post method
To prevent Android APK to re-engineering: Use Proguard
To make Web Service(PHP) can only access by the Android app: Hard-code a secret key inside the app, send it in HEAD with SSL everytime to the server. Or use android application licensing?
Thanks!!!
For SQLite database-level protection: Use SQLCipher
Correct.
For SQLite data-level protection: Use AES256 to encrypt and decrypt (But don't know where to store the secret key is better?)
You could but it might not be that necessary since SQLCipher already do the job on data protection in database-level. But if you do want to do double encryption, AES256 could do the job for you. Store the key somewhere that is hard to decode: ndk or in Java code. But don't forget to encrypt secret key as well. Decrypt it when you want to use.
For Web Service(PHP) Json to Android: Use SSL and Post method
Not enough. It is still be able to do repeated request attacked. Add two more mechanics, nonce (number used once) and request signing to your API. It will be far more safe.
For Android data to Web Service(PHP): Use SSL and Post method
SSL + Post + nonce + Request Signing + Certificate Pinning (to prevent man-in-the-middle attack).
To prevent Android APK to re-engineering: Use Proguard
Correct.
To make Web Service(PHP) can only access by the Android app: Hard-code a secret key inside the app, send it in HEAD with SSL everytime to the server. Or use android application licensing?
Just attach some variable, that indicated that the transaction was sent from your android app, to the request.
What would be the best most secure way to handle confidential text in an Android app?
The basic structure is (text/int) and some similar variations of it.
The app only shows a selection of the (readable text /readable int) at a time, so decryption will only be done for very few pairs at a time.
I need to make sure that extracting the complete (text/int) information is practically impossible - if possible :-)
Is there any standard library/scheme to handle this?
Many thanks
EDIT (after getting some very interesting responses to this question):
It seems that even when the data is encrypted one could easily take the de-compiled code from the app, combine this with a self-written extraction routine, and hereby get all the decrypted info to a file. Since the encryption key has to be provided to users of the app, everybody could potentially get to the data this way.
So in summary there is no real good solution?
You can save your text/int pair into the SharedPreference.
Because it's not secure, you can encryt the data before saving it into the SharedPreference in the same way as Google do in the Application Licensing package.
More details can be found in the Implementing an Obfuscator part.
The code source of the AESObfuscator can be found in the SDK in the market_licensing/library/src/com/android/vending/licensing folder.
I think in your application you can use a symmetric cryptography and you can store your key in the Keystore. This key should be protected with password. Every time, when you run your application, it will ask the user for the password. If the password is correct then the key is extracted from the Keystore and used to decrypt your data. In this case, there is no difference where you store your data (text/int pairs) because all data will be encrypted. For Android SDK look at the package java.security and to the class java.security.KeyStore
If you want to supply your application with the data that you don't want to be extracted then obfuscation is a possible solution if you write in Java. If you want this functionality to be written in C/C++ then use Android NDK.
My application would be frequently connecting to the web service to get some data in json.
Is there a way this data can be encrypted on server side and decrypted on application side so that data transferred is secure and safe?
Also, if the applicaiton comes with its own database (sqlite db file), is it possible for anyone using this application to look at this database (tables, fields and content)?
Regards,
Sapan
Your easiest option for transferring the data encrypted is to use SSL (i.e. https) for the communication between the app and the web service.
If you need to set up your own self-signed certificate for the server (instead of buying one) you might have problems getting android to talk with it, but it's doable. See this SO question for tips.
Regarding reading the database, it might be possible. I would assume that an attacker that got access to the phone could read the database, if they were determined enough. If you want the data to be really secure, you would have to store the database in an encrypted file and require the user to enter a password each time they open your app.
You have to decide how much security you really need.
You should definitely go for SSL encryption of the data when you transfer it over the network, though.
You can use crypto to encrypt/decrypt json in both android and server.In it very simple and secure. Using Base64 is not a efficient way, because anyone can decrypt. In this, you can use a secret key to encrypt and decrypt the String. If using wrong key to decrypt, the output will be wrong.
http://www.androidsnippets.com/encryptdecrypt-strings
I use Base64 encoding and decoding to encryt data over the network.
Depending on the type of webservice you are using, it will or will not have Base64 encoding and decoding. You can always google for code made by others.
Depending on the Android version you are targeting.
From API level 8 and up: http://developer.android.com/reference/android/util/Base64.html
For lower: http://www.frankdu.com/notes/2011/01/27/base64-encoding-with-android-2-1-or-earlier/
You could also write your own encoding and decoding systems of course. ;)
I've got an app that can save stuff you like to Google Storage for Developers. Assuming, of course, that you have an account and associated access keys. Their web based key management tool allows you to create keys and associated secrets. My question is regarding how a user can most easily install these in their copy of my app, allowing them to use the cloud storage.
A key is a 20 character alphanumeric string, and an associated secret is a 40 character Base-64 encoded string. It is clearly impractical for the user to enter these manually. Cut and paste across activities seems way awkward to me. How do you suggest getting two strings from a web page to two activity EditText fields - or to a tmp file I can read and then dispose - or ??
thanks.
The best way to go about it would be the API from Google
If you have access to a web page, there are these values are residing, you can download it, parse, and get these values.
Since it doesn't look like Google provides an API specifically for getting keys, your best bet would probably be to use an HTTP GET to pull the web page containing the keys and secret keys.
If you need to be authenticated with Google to do this (presumably you'd have to be), you could use SignPost to handle OAuth and make secure HTTP requests. After you pull the page, parse through the HttpResponse content and store the keys in a text file or a SharedPreferences file.