I need to keep and use a 3DES key in an Android application in order to communicate with a legacy sytem. I would like to use the Android Keystore provider for its high security features, but it seems it doesn't support 3DES.
My understanding is that in an Android application, you can either use the default Keystore provider and manage your own protection passwords, or you can use the Android Keystore provider, which is far more secure and manages the protection passwords for you. I understand that if you don't provide a KeyStore.PasswordProtection when creating/loading a keystore with the default Keystore provider, the entire keystore is stored as plaintext and the keys are vulnerable to being directly extracted by an attacker.
What are the best choices for safely storing and using a 3DES key in Android?
My idea is to generate an AES key using the Android Keystore provider and generate a random password to protect my 3DES key. Then, I can create a default provider keystore, protect it with the generated password and store the 3DES key inside. Then, I use the AES key to encrypt the password and store the encrypted password in SharedPreferences. Now, I can fetch the encrypted password from SharedPreferences, decrypt it via the Android Keystore provider, use it to unlock the default Keystore Provider and then just use the 3DES key for encryption/decryption.
Does this approach have any critical vulnerability? Could you suggest another?
Related
I would like to use the Hardware Android Keystore, to safely encrypt sensitiv data and store it locally on the device. The standard implementation seems very easy and there are enough tutorials out there on how to implement it.
But the requirements I got require that a user provided secret (a user pin or password that the user has to enter) is included into the encryption of the senstive data. So that encryption/decryption of the data only works with the known user secret and not without it.
I haven't found a way to provide a user secret into the Android Keystore process.
How can I encrypt/decrypt data with the Android Keystore that needs a secret user input to actually work?
AndroidKeyStore does not provide any API to set user provided password for the generated secret. Only thing that you can do is, setting a KeyGenParameterSpec.Builder#setUserAuthenticationRequired flag to true for system provided user authentication (pin / pattern / fingerprint etc.. )
The real power of AndroidKeyStore is comes from the TEE and Secure Hardware. So that, any other option rather than using the key directly in the AndroidKeyStore should be considered as less-secure. So that, generating PBKDF2 using both user provided secret and key store encrypted secret doesn't makes your encryption more secure. Because, that new key should be managed in an application memory and is vulnerable (of course in compromised device) until you complete encryption and wipe all of the key bytes.
But in secure hardware, AndroidKeyStore doesn't even loads your keys in a memory. Every operation happens in a separated secure hardware.
If your requirement is not strictly "having one key" and "encrypt data only once", you may consider to encrypt your data twice using both of the secret from AndroidKeyStore and user key which is derived from user password.
And also, you may want to read this paper: http://www.cs.ru.nl/~joeri/papers/spsm14.pdf. In this paper, authors also mention Bouncy Castle keystore with user-provided password.
I have done an Android Application using an ECC Key pair. When I have developed it last year, I wanted to create the ECC key in the Android Keystore. Unfortunately, this ECC key is used to generate a session key thanks to ECDH, and ECDH is not supported by Android Keystore (this is what I have been said here: ECDH with key in Android Key Store )
I have followed the recommendations: I have created an AES key in the Android KeyStore and I have used it to encrypt the ECC key before storing it in the SharedPreferences. Android KeyStore ensures that the AES key cannot be extracted and that only my application can use it to decrypt the ECC key.
I now have a concern for which I would like your advices:
What if someone install my application on a rooted phone, gets the APK, uncompile and modify it to print the ECC key after that has been read and decrypted? I don’t have this skill but I guess that some hackers do.
If that’s feasible, it means that the protection that I have used is not efficient.
Using ECDH is non-negotiable in my case so what solution do I have to secure my ECC key pair?
Thanks
There is no way to ensure that the key is non-extractable unless it's backed by secure hardware.
And for the rooted phone case, attacker doesn't need to modify and reinstall your APK in order to use your key. Any app on that device with the root permission can hook into your app and behaves like it. Even in trusted environment they can use your hardware backed key. Only thing they can't do is, extracting the key from the device.
You may want to read the relatively old paper about TEE and AndroidKeyStore: http://www.cs.ru.nl/~joeri/papers/spsm14.pdf . Especially "Overview of the results for Device-binding"
In order to reduce attack surface, you can:
Protect your key with the user-provided password along with the AndroidKeyStore AES key
Use SafetyNet API to check device integrity: https://developer.android.com/training/safetynet/attestation
Is it possible to save a string in the keystore and then retrieve it?
I have an AES password already generated, I just want to store it in a safer place than the database.
All the examples I have seen store an AES key that is generated at the moment. I can use this solution if I could have access to the original key to send it to the server, is this possible?
You can store the AES key into AndroidKeyStore safely. The keying material can be used by your application without exposing it.
But a key in AndroidKeyStore is not extractable, so in order to be able to send the AES key to server you will need to generate the key outside, and wrap it using an additional encryption key managed by AndroidKeyStore. Then the encrypted AES key can be stored in the device or even in the server
Please see my answer here with all options explained: how to securely store encryption keys in android?
I am developing an android messaging app. When user signup rsa private and public key are generated and with these keys and aes messages are encrypted and decrypted.
Private key is stored in the phone and public key in the server. If the user resets or uninstall the app all keys are lost so there is no way to decrypt the old messages.
How can I retrieve old private keys without storing it in server when user uninstalls app?
Are you using Android Keystore to store the keys or using your own file storage?
Android keystore
With Android Keystore there is no way to recover keys because they can only be used by the application that created them and are discarded if there are substantial changes.
I guess you are using the RSA keys to negotiate an AES symmetric encryption key. Therefore you will need to backup the AES encryption key( for example in the server...), and stablish a mechanism to recover the key like the common "remember password" utilities
custom key storage
If you are storing the keys into the device without AndroidKeystore, you could define your own mechanism to restore the keys. For example, encrypt the key with a password and storing the key into a public directory of the device. Then the key can be recovered prompting user for the password
Note: Take into account the security risks in each case. For example a non-encrypted AES keys into server implies that a malicious server could decrypt messages. Or a weak recovery key mechanism will descrease the whole security level of the system
There are various ways to persist data in Android. Databases, SavedInstanceState, SharePreferences and files. Only files persist after you application is unInstalled by the user. Saving it in a file is about the only option you have.
I've read about Keystore which is in fact a repository of security certificates – either authorization certificates or public key certificates – used for instance in SSL encryption.(by Wikipedia).
Android developers use the Keystore to store their encryption keys in it, instead of
embedding the encryption key inside the android application. That's supposed to solve the problem of a hacker which is decompile their app and get the encryption key the is used by the app.
Whenever you want access the data inside the Keystore you have to specify a password. What prevents the hacker from decompiling the app, extracting the Keystore's password, and then gathering the encryption key inside the Keystore?
Or maybe I got it all wrong?
They are likely storing that key encrypted in the keystore itself. To access the key store, you will need some combination of the user's passcode for unlocking the android device and/or a device specific code such that only that device can decrypt the keystore.