It is possible to store key pairs unencrypted by omitting KeyPairGeneratorSpec.setEncryptionRequired(). In this case, the key pair is presumably stored in clear, rather than encrypted with a key derived from the device lock screen credentials.
It is also known that hardware-backed keys are not in fact stored in the TEE, but rather, in /data/misc/keystore/user_0.
If keys are stored in clear, wouldn't a root user with full access to the file system then be able to extract the private key material?
Related
I'm in need of storing in shared preferences a bunch of sensitive information. I know using EncryptedSharedPreferences would be ideal, but given its minSDKVersion of 23, its a no-go for me.
So, I chose to implement an hybrid cryptography system.
The first time I need to encrypt some data, I randomly generate an AES secret key
Then, I create a new entry in the keystore, so that I can use its public key to encrypt that AES secret key. Then, that final secret key is saved in shared prefs
Whenever I need to access that data, I'll get the encrypted key from shared prefs, decrypt it using the private key stored in the key store and, finally, decrypt the content with the AES key that I just retrieved.
Am I doing it the right way? I'm currently not using any IV or padding in the AES encryption. I figure this system will be just as secure as the RSA algorithm I used, no matter what the AES key is (as long as it is a random one generated at run time). Am I right or missing something? Should I take the extra step of using a padding and IV alongside AES?
I'm working on the topic on how to securely store sensitive data on an Android device. Of course there's no 100% secure method, I'd like to get as secure as possible.
I've read through the official recommendations.
Just as an example, I have an app that stores text (e.g. private diary). The text is stored in an xml file, which is encrypted (aes256) with a key, that is stored in the Android KeyStore.
This should mean that the data is stored securely in the encrypted xml file. A root user can still access the key from the KeyStore and decrypt it, or fetch the data once its decrypted by the app.
However, this also means that every app uses the same key. So I can install the app on my phone and use my key to decrypt xml diary files from other phones.
The question is, how do I create a key or at least the salt, that is unique per app installation?
The Key Derivation Function KFSs are just for this
From the Wikipedia;
In cryptography, a key derivation function (KDF) derives one or more secret keys from a secret value such as a master key, a password, or a passphrase using a pseudorandom function.
You can use Argon2 was the winner of Password Hashing Competition.
Choose the IMEI number as one of the parameters, the user's password and a random number from the phone.
Given that it is not possible to store a symmetric key using the Android KeyChain API, is the following a secure way to store a symmetric key:
Part One: Key Generation and Storage
Generate symmetric_key
Generate (private_key, public_key), store them in the KeyChain
Encrypt the symmetric_key using the public_key as follows: encrypted_symmetric_key = public_encrypt(symmetric_key)
Store encrypted_symmetric_key in local storage (SharedPreferences, SQLite, etc.)
Part Two: Using the symmetric_key
When the app wants to encrypt/decrypt something it:
Loads the private_key into memory from the KeyChain
Loads the encrypted_symmetric_key from disk
Obtains symmetric_key := private_decrypt(encrypted_symmetric_key)
encrypt(symmetric_key, some_message) or decrypt(symmetric_key, some_ciphertext)
Concerns:
Would a rooted user be able to obtain the (private_key, public_key) pair?
If the phone is not rooted, is the app that created the (private_key, public_key) pair the only user that can read the keypair?
According to the documentation (https://developer.android.com/reference/android/security/KeyChain.html):
The KeyChain class provides access to private keys and their corresponding certificate chains in credential storage.
Private key means that it's asymmetric (the private and public key are the two parts of an asymmetric key).
In your part 1 - you describe the preferred way to store a symmetric key on an Android device. Your part 2 is correct as well (at least to my knowledge).
As for your concerns - you are also correct. On a rooted device - the keys stored on the devices are vulnerable , and can be obtained by a person with access to that device. On a non rooted device - only the app will have access to the keys it creates.
In regard to rooting - you can use a root detection lib like RootShell (https://github.com/Stericson/RootShell) to detect if the device is rooted and then act accordingly (disable you app on that device or something similar) and you should also look into Google's SafetyNet (https://developer.android.com/training/safetynet/index.html) to detect if the device is tampered with (it detects rooting as well).
Hi what are the various RSA 2048 key generation and secure storage methods in Android.
I have an app where I need to generate pubic-private key pair in Android and sent public key to server.The private key must be securely stored at client side.How can I ensure that the private key is securely stored ? Is there any reliable key storage mechanism available in
android ?
I've thought of using AES to encrypt private is it a good method?Should I be using a static key in source code itself or based on some user's input ?
You need to use a Key Store in your app for secure key storage. Storing keys in you source is the 'anti secure' way. http://developer.android.com/reference/java/security/KeyStore.html
I'm currenlty investigating using the secured/improved Keystore introduced in Android 4.3.
I would like to store an encryption key inside this keystore, this key is used to encrypt a sqllite db and the values contained in my shared preferences.
When I take a look at the KeyStore Sample in the SDK I see the following:
public static final String ALIAS = "my_key"
If someone would be able to decompile my code they would be able to see the cleartext alias (= the key to retrieve the encryption key from the keystore) and hence they would be able to get a reference to my encryption key. How can I securly manage my ALIAS? or am I missing the point here?
The below answer is for 4.3+. There were big changes to KeyStore & KeyChain classes on this release. See here for more info
Keystore access is restricted by UID - your app is allocated a UID on install.
This is what prevents other apps / processes accessing your key pair / private key. The keystore deamon will enforce this.
This can optinally require a device pin for additional encryption. See http://developer.android.com/reference/android/security/KeyPairGeneratorSpec.Builder.html#setEncryptionRequired()
The whole point of using the software / hardware keystore is to get around the situation you describe - which is any hardcoded data in your app can be read on decompilation so it would not be secure.
#Duncans answer makes it seem that you need to keep a password around. I would advise you generate a key pair using the keystore and then use this to encrypt an AES key you can use to encrypt anything you want (much faster than using an RSA key)
You can use your hardware / sortware keystore backed private key like keyStore.getEntry(alias, null); and not pass any kind of password.
See SecretKeyWrapper.java for a good example of this
The alias is not sensitive information. Each keystore is associated with a password and each key has its own (optional) password too. Those are the values that must be kept safe.
Without the password(s), an attacker cannot read your key material despite knowing the alias.