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.
Related
I want to use one secure key to encrypt and decrypt data on device without saving it in SharedPreferences or DataStore. I want to generate that key using in app authorization (passcode and biometrics).
I know generating secure key with biometrics is possible using AndroidKeyStore. I know I can generate another key by using passcode. Is there any cryptographic way to use one of those keys to encrypt/decrypt local data?
I have tried generating keys with biometrics and passcode. But I could not find a way to encrypt and decrypt data with either of those keys. For example: user logs in and sets passcode and fingerprint. App should encrypt data so it could be decrypted using one of those authentication methods.
I am wondering how do other secure Android apps solve this problem. Can someone provide me an example where could I look into that?
I'm trying to use firebase email authentication and enable biometrics.
The solution I am able to come to is:
enable biometrics and get the fingerprint token
encrypt the user's username+password with this token
store the encrypted username+password in app storage
when user authenticates using biometrics, app decrypts stored username+password and logs in firebase.
The issue is of-course the difficult choice of storing encrypted username+password locally.
Is there any better alternative like
saving an encrypted firebase token instead of username+password?
saving the token in a server?
How do professional apps do it with firebase?
Use Symmetric & Asymmetric keys concept with Android keystore
Follow the Salesforce Mobile SDKs strategy in using the Android Keystore
(more details here:https://developer.salesforce.com/docs/atlas.en-us.mobile_sdk.meta/mobile_sdk/auth_secure_key_storage_android.htm)
To summarize the steps :
The application upon installation and first run creates an asymmetric key pair and a symmetric key
The application stores the asymm. keys in the Android Key Store. Key Store access is granted only when the user unlocks phone (e.g. w/ pin code or biometrics. this step is optional. you can do it without this step)
The application encrypts the symmetric key with the public part of the asymm key pair and stores that in shared preferences
It is the symmetric key that is used to encrypt/decrypt the Firebase token or username + password whichever you want to use
To access the encrypted symmetric key, the app has to first obtain the private key from the Android Key Store, decrypt the symmetric key and then use it.
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.
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'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.