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.
Related
I'm working on an Android multi module (multiple apps) project and encountered a use case where I have to save some secret information that could be accessed by all these apps. My idea is to encrypt the secret information using a private key that is saved inside the KeyStore, and save this information in a file that I'm planning to store in the device (not external storage). My question is, would I be able to access this private key inside the KeyStore from another application and then use it to decrypt the secret information that is saved in the device?
I was looking at Android's KeyStore documentation, and if I understood it correctly, I can use the KeyStore APIs to save the cryptographic keys and use them with in the same application. But also the KeyChain documentation says I can use these cryptographic keys across multiple apps with in the system. I'm quite confused about how I can combine these two APIs and make it work for my use case. Any help is appreciated. Thank you.
My idea is to encrypt the secret information using a private key
You encrypt with a public key, never with the private key. The private key is used for decryption.
If you create public keys for all the apps then you can decrypt with individual private keys for these apps. Of course you'd have to trust these apps and the public key pair of each app in advance; I'm not familiar enough with your setup to make any recommendations in that regard.
To be honest the KeyChain API seems more about TLS authentication than anything else and I don't think it fits your use case. The API of the choosePrivateKeyAlias for instance only talks about authentication and a server requesting a key chain.
Key stores can be can in principle be distributed. Or course, to access / decrypt them you'd still need a key distributed within each app. You can share the information for specific signed applications only it seems. Possibly just the security of sharing the data privately without encryption already fulfills your use case? Key management is tricky, after all.
Caveat: I'm not terribly well known with the Android security model; hopefully my general knowledge of cryptography & security steers you in the right direction.
There is android:sharedUserId property. From the doc:
Apps with the same user ID can access each other's data and, if desired, run in the same process.
Unfortunately, it was deprecated in API 29 without proper replacement.
I'm reading about store a secretkey (to encrypt/to decrypt data) and seems there is no way achieve that. One can only increase difficult for an attacker accomplish this.
It's really like that?
What I've got so far:
Store in shared preference ( private mode ) - Rooted phone will be able to retrieve it.
NDK C/C++ native code, create .so file - Hard to decompile, but one could call this .so file and retrieve it.
A webserver to store the key, looks useless, if a have to send credentials, a malicious ware could log key taps.
Am I too paranoic?
Why do not you use Android Keystore?it is designed for this purpose
https://developer.android.com/training/articles/keystore.html
The Android Keystore system lets you store cryptographic keys in a container to make it more difficult to extract from the device
It has considerable advantages over shared preferences or private files like extraction prevention or key use authorization I do not consider storing private keys on the server
Security Features
Android Keystore system protects key material from unauthorized use. Firstly, Android Keystore mitigates unauthorized use of key material outside of the Android device by preventing extraction of the key material from application processes and from the Android device as a whole. Secondly, Android KeyStore mitigates unauthorized use of key material on the Android device by making apps specify authorized uses of their keys and then enforcing these restrictions outside of the apps' processes.
In some devices with dedicated hardware it is implemented on it. As a programmer you can know is a key is hardware-protected
The concept is similar to iOS KeyChain, but whereas IOS KeyChain can store passwords, generate and import cryptographic keys, Android KeyStore only allows to generate cryptographic secret keys by the application ( no import functions)
The keys also can be protected requiring user to unlock the device and / or presenting the fingerprint
For example, to secure a password, is possible to generate a cipher key protected with fingerprint, and use it to encrypt user's credentials that could be stored in preferences
You are correct. Most security experts will tell you there is no such thing as an absolutely secure system. The proper way to think of it is in terms of the level of resources an attacker must use to break your system.
You then balance your security measures between the value of the data and other considerations like the complexity of your solution and other costs.
To elaborate on your examples, assuming you aren't worried about the legitimate owner/user of the phone being the attacker, you can assess as follows:
Rooting a phone is a risk if an attacker gets physical possession. To assess, how valuable is the data versus the likelihood of a phone getting lost/stolen, the person who then has it caring to get the key and knowing how to root a phone.
Obscuring secret information is generally considered useless. I personally think it depends a little bit on the circumstances. Here, again, an attacker would need to root the phone, etc. The problem with obscuring secret information is it only takes one person to figure out what you've done and make that information available to completely lose the value in doing it.
If you have a key logger, what security do you have anyway?
You should look at the possibility of using a "secure element". See this post on the security Stack Exchange for some good information.
I have an interesting situation here. My app stores sensitive info input by the user such as a social service account of theirs. I use a master password input by the user to generate a SecretKey, and then use AES encryption and store its SHA1 hash and the encrypted data on device, but not the master password itself or the key.
The issue is that in case the user forgets their password, there is a secret question they can answer and change the master password. So when the master pass is changed, since the previous password (and the associated SecretKey) are forever gone, I can't decrypt the stored strings and show the decrypted data to the user.
Here are the solutions I can think of:
1 - Store the password, which I have heard is totally unsafe.
2 - Store the SecretKey, but I have heard this is unsafe too.
3 - Store user data in database unencrypted, which is unsafe I guess.
4 - Wipe the entire database everytime the user forgets their password, which is silly I think.
I need a way to overcome this and I simply can't think of a secure way to pull it off.
It is crucial that this be solved for my app to fly. Any and all help is really appreciated.
Well it's a bit unfair to remove all of user's data just because they forgot a password.
Then they shouldn't be storing stuff in a container that requires a passphrase. Next, you'll argue that anyone should be able to open any wall safe using a hockey ticket stub and some chewing gum, because somebody might forget the combination for the lock.
Please note that your line of inquiry assumes that the approach described in your opening paragraph is the correct way to build the app that has the security characteristics that you desire.
For example, the right answer to meet your requirements is to not encrypt the data at all, but instead force the user to have their device full-disk encrypted. You can use DevicePolicyManager to see if the device has full-disk encryption enabled, and you can refuse to run if they do not. Then, the data is encrypted, as is the rest of their device, but you are no longer having to deal with passphrases and recovery scenarios — that's up to Google and device manufacturers.
Isn't there any other way to decrypt the data?
Only if you have a vulnerability in your app (a.k.a., a backdoor). This is the ticket-stub-and-chewing-gum scenario. The point behind encrypting data is to make it so that it cannot be encrypted without the passphrase or equivalent security key.
So, another approach to your app is to dump all your key stuff and use KeyStore. Particularly on devices with a hardware-backed KeyStore, there's no way to really get at the key, short of unlocking the device. Here, you don't have to worry about the full-disk encryption (as you're encrypting the data) and you also don't have to worry about the user forgetting the key (because the user never has the key). It also saves you having to have the user enter a passphrase. But now you can't readily back up the data (as it's useless without the key), and if the user's device is run over by a bakery truck or otherwise destroyed, the data is gone. You could provide options for the user to back up their key (e.g., to removable media), but now you are reliant upon them remembering where they stored the backup, storing the backup key securely, etc.
Or make the same SecretKey as before?
Since nobody but you knows how you are creating this, nobody but you can answer your question.
I would also suggest that you read this paper, as it outlines how 88% of Android apps that they surveyed, who tried to cobble together their own crypto approach, screwed it up.
I am looking into making my user data secure for android. I come across keyczar. I found the android-keyczar-demo provided by Kenny Root who gives talk on android security at google-IO. However I have a nagging question. Since the keys are packaged in the app, isn't it the case that malicious user can also use that key to decrypt the sensitive data? From keyczar doc, keyczarTool is a command-line tool to create the keys, so it seems that it is not meant to be packaged in the app? I have noticed that keyczar's key can be password protected. However it comes back to hard coding the password in the source code. What am I missing to understand here?
What you are missing is that you can't semantically keep the key secret from your users if you also want those same users to be able to decrypt. That's why DRM will never work.
The reason keyczar has the keytool is that an important part of security is changing your key over time, and so keyczar provides a way to rotate your keys without breaking functionality.
The PBE keysets are there so that a user can enter a password to decrypt, it is definitely not intended to be hard coded. That way given a keyset for an app, you can protect the data from an adversary while providing decryption to your user, by requiring your user enter a password. (Unfortunately this feature is only present in the C++, Go, and C# versions of keyczar--not currently in the java version).
Also if you don't want every user to have the same key you don't have to include the keyset with your app, you could also generate it installation. But encryption in the mobile space is difficult, it's hard to say without knowing what you are trying to do, if it's possible for you to secure what you want or if keyczar is the right fit.
I haven't been able to find a way to open a password-protected SQLite database on Android. Since the device can easily be rooted, I am thinking of password protecting the database file. However, I am not having much luck finding anything built into the Android platform.
I don't think that Android framework supports password protection on databases. Your best bet is to encrypt your data. See SO question: Android Sqlite Password Encryption
You can encrypt SQLiteDatabases. Android does not support full-database encryption so you'd have to implement that yourself if you want to.
If you want to go down the encryption route, you're much better off just encrypting the sensitive information yourself and storing it in a database field, as per Morrison's answer.
All that said -- where are you putting the password for the encryption function? You'll probably need it somewhere in your application! In which case someone can just disassemble your code and then find the password, and decrypt the info (although it will be a bit more work).
Unless you're hashing info (one-way) then without hardware encryption on a device (and even that has flaws) you cannot store anything on the device perfectly securely -- you're always going to need to decrypt the info some time and for that the password has to be on the device somewhere.
If you want really robust security then store sensitive information on a server (preferably in a really secure location), not the device, and only communicate between the device and server over encrypted channels (HTTPS). You'll also need to authenticate the device in a secure manner. But to do that you need to store some sensitive information ON the device in order to authenticate the device with the server, unless you force the user to enter a password every time (recommended if security is a must).
If the information is stored on a server you can't necessarily prevent someone who shouldn't gaining access (by finding the password you have stored or phishing the user if it's stored in their head), but you can revoke access to the information.