From the Android Keystore Docs
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.
I am not able to understand it completely.
by preventing extraction of the key material from application processes
What does it mean? Any application process in the device can not extract the key from the store?
So once key is put in the store, there's no way to get it from the store (in case I want to use it somewhere else as well).
So if I want to do that, how do I implement my own custom keystore, which allows to extract the key for only my app's process and no-one else.
What does it mean? Any application process in the device can not extract the key from the store?
"Preventing extraction" in the context of the documentation you linked means "preventing extraction of the key material by an adversary." It doesn't mean that your own application cannot use the key from the keystore to encrypt/decrypt data. It does means you will never be able to obtain something like a key file from the Android KeyStore, copy that somewhere else, and reuse it.
Furthermore, say you need to send encrypted messages between client and server on your app. You naively generate a key and store the file ("key material") in the internal storage for your app. An adversary gains root access to the device. They can now access your key file and use your key. Even if you use a password for the key, if your app process is compromised then because the adversary has access to the key material (i.e., the key file) there is still a danger.
The advantage being talked about in the documentation is exactly the opposite of these faults. The Android Keystore cryptographic transformation takes place outside of the application process (as a system process) and may be bound to secure hardware. None of the key material (key files etc.) is exposed for an adversary to reuse somehow (to decrypt messages or to sign an email, for instance).
Note, if you want a key to be used with multiple applications then you might need the KeyChain API rather than the keystore.
I would also add that privateKey.getEncoded() method will return null if you retrieve the privateKey from the AndroidKeyStore.
So considering the code below:
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyStore.Entry keyStoreEntry = keyStore.getEntry(alias, null);
PrivateKey privateKey = ((KeyStore.PrivateKeyEntry)
keyStoreEntry).getPrivateKey();
byte[] privateKeyData = privateKey.getEncoded();
privateKeyData will be null. This is what it means that
"Android Keystore system protects key material from unauthorized use"
Related
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.
I am looking to understand Android keystore for the purpose of storing passwords on device. (https://developer.android.com/training/articles/keystore.html)
In this article it says "Use the Android Keystore provider to let an individual app store its own credentials that only the app itself can access." This is exactly what I want.
So I think the way this will work is like:
1) I will generate a RSA key
2) Store the PrivateKey in the KeyStore
3) Store the PublicKey in some SharePrefs
4) Encrypt Password using the PublicKey
5) Encrypt Password using the PrivateKey.
However I think I am misunderstanding something because this article does not show
1) How to save PrivateKey to KeyStore (I don't see any API showing how keystore added the key)
2) Does not show how to decrypt data with PrivateKey
Infant why is this article talking about "Use a PrivateKey in the KeyStore to create a signature over some data." What does it mean to create a Signature over some data ??? (I want to decrypt data with PrivateKey). And why does it want to verify "signature previously made by a PrivateKey".
So I am lost at this point ... this article started me of in the right place but then by the end I am confused what it is trying to achieve.
Can someone suggest if what I am trying to do makes any sense at all ?
Or should I just save public and private key in my own db ? (not much security there but its the best I can do with given requirement of storing password on device).
Many thanks
Rgds !!!!
I am quoting this line from Using internal storage section of http://developer.android.com/training/articles/security-tips.html
By default, files that you create on internal storage are accessible only to your app. This protection is implemented by Android and is sufficient for most applications.
Now about encryption:
Keystore API is dealing with encryption of the data. And keys are used for secure communication and not for storing password. Passwords are usually irreversible hashes or maps. And do not require decryption but needs only matching.
For example: To communication if you send data encrypted other party involved in communication needs to know what the data is so required decryption key. So if you have sent "Hello I am Crypted" receiver must know you sent "Hello I am Crypted" as message.
For password if you enter some passphrase or passkey it needs to be matched with the stored counterpart. Like if "pass123" is your password stored as "rdi#$$+!#/b" then when you enter a password when process by checking algorithm it should match the stored value and you are authenticated it is not required to generate "pass123".
So, for your application you can use some mechanism(that generates almost unique and irreversible hash) to generate unique key/hash when password is entered and then store it in your app data.
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).
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.
I am downloading XML file via HTTP connection and now I need to have encrypted XML in my FTP and befaore download I will check XML signature (or decrypt it) before any other use of it. I have got my app signature (combination of 976 letters and numbers) and I don't know, can I use my signature string to verify my XML? Or private/public key solution? But how to create keys and how to store them in APK?
Thanks
The best way is to use a asymmetric key pair (RSA is most common) where you sign the data on the FTP site, keeping your private key, uh, private and the public key on the android device. You may use another key pair for encryption/decryption. You could use your signature string as a password to your private decryption key on the android device. Make sure your application is not vulnerable to padding oracle attacks (encrypt, then sign or don't notify the other side if decryption failed).
Note that implementing your own version of the XML sign/verify or XML encrypt/decrypt may be very hard to do (and fraught with pitfalls that at least match using XML security related libraries). I would recommend trying for wrapping your XML within a CMS container instead.
For other users, a link to the later question of yours:
Android - verify the signature of XML
owlstead is right, trying to reinvent the wheel is not the optimal choice. On the other hand, the internals of signing and verifying XML files are trivial if you really want to implement it, or learn how to do it. First, you generate a RSA public/private key pair. Then you take the hash of the XML file and encrypt the hash with your RSA key and ship the encrypted data along with the XMl file, which now makes your XML file signed. To verify the file, you simply take the hash of the XML file and compare it with the encrypted hash (after decrypting it) to see if they match. If so, file was not tempered with along the way.