I'm working on an Android app (minimum Android version is 5.0 - API Level 21) that stores data in a local database via RoomDatabase. However, the data needs to be encrypted for which I used SQL Cipher. My question is what is the safest way to store the key used for SQL Cipher. So far, I have two options and a major 'concern' for both of them:
Using the Android Keystore - however my biggest concern here is whether a user with root privileges can access the Keystore?
Using NDK to create a key - from what I've seen the file can easily be decompiled and the key can be extracted somewhat easily.
The app itself is simple so asking the user for a pin/password would not be a way to solve this. The same applies for getting a key from a server since the app doesn't require constant Internet access.
Using Firebase may be the answer because:
It does not need constant network access it will cache the data.
The saved key is not in your app, it is in the web or inside the cache of Firebase service.
It is simple to setup.
You can use one of these products to save your key at Firebase:
Cloud Firestore, Cloud Functions or Cloud Storage.
Or you may use Firebase Authentication instead of saving key.
Related
My question is that there is a section in the gradle file called signingConfigs.
Is it a problem if the password is entered here?
Should I be worried about this?
Thanks.
We should NOT do this. These params are there for testing convenience.
We should NEVER store ANY crucial, personal, sensitive information as plaintext.
The testing key passwords and stuff just use dummy values. The actual release key we generate via AndroidStudio or Java keystore directly.
For PlayStore app releases, key files I usually let Google assign, manage and maintain via Developer Dashboard.
I have a Spring Boot App that is a consumer of a cloud API. The API key for that API is externalized using an #Value annotation. Generally, we create a separate run.sh file that looks something like this:
java -DaccessToken=abc123 -jar my-app.jar
One of our customers, wanted us to encrypt the run.sh file, so the API key wouldn't be stored in plain text on the file system, which we did using this method.
Now, that same customer also wants us to automate their rotation of the API keys every 90 days. It's fairly simple to request a new API key within the APP and then delete the old API key, but is there a way to securely store the API key in such a way that the APP can be restarted if the host computer restarts, but the API key is not stored in plain text on the OS. I can't think of a way to do this without storing something unencrypted.
Thanks in advance for your help.
I use yandex and google translate in my application and of course have unique API key, but everyone can steal it by decompiling my application. How can I hide it?
If i were you i will rent a server (maybe amazon) and create a database and insert our api key with simple encrypted string (hash etc.).
ID - Name - androidKey - key
1 - GoogleAPI - AJKBSASHUA9 - yourAPIKey
2 - YandexAPI - 5A6S5D6A53C - yourAPIKey
.
.
.
Then you can create a service which is run by your android packageName;
http://example.com/API/getAPIKey/
?packageName="yourPackageName"
&androidKey="AJKBSASHUA9"
And if you use POST method it is safe for you.
Simply, you can't do that inside your APK at all or inside the application. If someone want to get it, they will get it.
You are going to decipher them, I'll find the key inside the app.
You are going to put them in the web and fetch them after installation, I'll root my phone and get them.
And why would you hide them on the first place, they are assigned with the SHA1 fingerprint of your [Release|Debug] keystore and your package name and no one can have your release keystore and its password.
While you may not be able to achieve 150% security, you may want to take steps in your app to slow possible attackers down. This will result in some of them turning away from exploiting your application, simply because it is not worth the effort.
The OWASP Mobile Security Project has published their collection of "Top Ten Mobile Risks", of which especially the topics "Broken Cryptography" and "Lack Of Binary Protections" are interesting in your case. While even this link does not provide you with a simple "how to", I think it can help you to assess your situation.
In desktop Java there exists a sun.security.mscapi.SunMSCAPI cryptoprovider that we can use with KeyStore to access Windows system certificates stores.
I know that there are similar stores on Android, but I can't find a way to manage these stores (list, add, delete certificates).
What I found is:
1) use KeyChain, but this requires additional interaction with user via Activities;
2) use KeyStore like on desktop and load storage files directly, but a path to these files isn't constant on all devices.
Are are any other approaches that I'm not aware of?
KeyChain is a relatively new addition. Its only available from API 14 (Ice Cream Sandwich) and higher. Nicolay Elenkov has a good blog entry on it at Using the ICS KeyChain API.
KeyStore is an even newer addition. Its only available on API 18 (Jelly Bean MR2) and higher. Nicolay Elenkov has a another good blog entry on it at Credential storage enhancements in Android 4.3.
You might also be interested in Unifying Key Store Access in ICS from the Android Developer's Blog. It tells us the KeyStore has been around since API 4 (Donut), but only the system could use it and it was only used for VPN secrets (Wifi was added later).
The user certificate store was kind of broken until recently. To remove a certificate from the store, you had to delete the entire store (even the certificates and private keys you wanted to keep). See User key/cert management in ICS.
The system's certificate store used to be stored in ROM. That changed after the Diginotar failure because Android had to build new images to remove the compromised Diginotar root. Given that so many carriers don't support their devices, there's literally millions (perhaps billions) of defective devices still out there.
If you want something that appeals to the largest selection of Android devices, then you probably need to use your own store. Perhaps a Java Keystore or SQLciper would be a good choice. Just be sure the database is encrypted with a key that derives from something the user inputs (like a secret). Combine the user's secret with a random value stored on the file system in your sandbox or KeyStore for maximum effect.
If you don't take the user's input, then you hit the "Unattended Key Storage" problem. And that's a problem without a solution. See, for example, Peter Guttman's Engineering Security.
The app I am working on gets all the files from the sdcard but these files are really important and the app should maintain a security issue .So is there a way that the folder or directory that contains the file may be encrypted or locked with a key and only be used by my app?
Please help I am newbie and stuck at this point.
On Android, anything stored on the SD card is not protected by permissions and can be accessed by any application that has permission to touch the SD card (and by anything/anyone that can pull the card out and read it elsewhere). Basically, you need to assume that if you put resources there, they can be accessed by anyone. So, you are correct, you want to encrypt these resources so that even with that access, no one can access them.
Android includes plenty of support for well-known cryptography. In this case, you'll want to use symmetric encryption. The current best practice here is to use AES with 256-bit keys, all of which are natively supported in the Android class libraries. There are plenty of resources on how to do this in the developer documentation online and there is a complete rundown of all the issues you need to think about, and code examples of the entire process, in Application Security for the Android Platform (disclaimer: I'm the author of this book).
You do need a key to encrypt this data, and you need to keep that key secret (anyone that knows it can decrypt the data). You have two options...(1) ask the user for a password every time they use the application and then derive the key from that password, or (2) store the password in your application. (2) is dangerous as Android applications can be readily reverse engineered, where an attacker can simply look into your application and find the key. (1) is preferred as then there is no key stored for an attacker to recover...the tradeoff is that your users need to type in a password to use your application. What you should do here is a function of the risk analysis...how important is this data? Do you need it protected in a strong manner, or are you protecting it to just make things harder for an attacker? Only you can answer that, based on your use cases and the sensitivity/risk of your data.
Have a look at those resources:
http://source.android.com/tech/encryption/android_crypto_implementation.html
http://developer.android.com/reference/javax/crypto/package-summary.html
You should be aware that of course you shouldn't store the key to the encrypted data in cleartext but rather encrypt that itself with a password a user can choose or similar.
This is how to make a new folder:
String SaveFolder = "/Save";
String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
File mySaveFolder = new File(extStorageDirectory + SaveFolder);
mySaveFolder.mkdir();
Got this code in the public void onCreate
Now it makes a folder with the name "Save".
Edit:
I looked there is not a way to set a password or something.
Though I read here http://developer.android.com/guide/topics/data/data-storage.html#filesInternal it is possible to save files in the internal memory, where users can't get acces too, but I never used that, so I can't help you with that.