Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can we extract public/private keys from the Android Keystore?

Regarding Android Keystore system article,

Key material never enters the application process. When an application performs cryptographic operations using an Android Keystore key, behind the scenes plaintext, ciphertext, and messages to be signed or verified are fed to a system process which carries out the cryptographic operations. If the app's process is compromised, the attacker may be able to use the app's keys but cannot extract their key material (for example, to be used outside of the Android device)

So, my question is why is in BasicAndroidKeyStore, developer able to get the KeyPair object and then print its public/private keys?

If developer can access the keys, how this system can be considered to be secured? It's not. If an attacker compromises the app process, he can easily retrieve the kays and use outside of the device.

like image 826
frogatto Avatar asked Sep 18 '18 07:09

frogatto


People also ask

Where are Android encryption keys stored?

The Android Keystore system lets you store cryptographic keys in a container to make it more difficult to extract from the device. Once keys are in the keystore, they can be used for cryptographic operations with the key material remaining non-exportable.

What can be stored in Android keystore?

The Android Keystore system lets you store cryptographic keys in a container to make them more difficult to extract from the device. Once keys are in the keystore, you can use them for cryptographic operations, with the key material remaining non-exportable.

How do I find my private key in keystore?

First call keytool -list -keystore myStore to know which alias to look for, then call this program with the passwords and parameters. In case of a private key entry, it shows the key itself and additionally a self-signed certificate which contains the public key, in a readable form.


1 Answers

The example code that you pointed to from BasicAndroidKeyStore does not log the public key as getPublic() from the KeyPair class only returns a reference the the public key object, not the public key itself.

Log.d(TAG, "Public Key reference is: " + kp.getPublic().toString());

Logs:

D/KeyStoreFragment: Public Key reference is: android.security.keystore.AndroidKeyStoreRSAPublicKey@b8004e8f

The same goes for getPrivate().

Log.d(TAG, "Private Key reference is: " + kp.getPrivate().toString());

Logs:

D/KeyStoreFragment: Private Key reference is android.security.keystore.AndroidKeyStoreRSAPrivateKey@5da42c27


Now, as you point out in your comment, kp.getPublic().getEncoded() will return the actual public key, but a public key's original purpose is not meant to be secret.

The private key is meant to be secret and while using a hardware-backed keystore with keys supported in the device's secure hardware, the secret keys are stored safely in the TEE/SE and cannot be extracted by the app itself or another bad actor with root privileges. You can see it in this example:

Log.d(TAG, "Private Key is " + Arrays.toString(kp.getPrivate().getEncoded()));

Logs:

D/KeyStoreFragment: Private Key is null


To verify your keys are supported by your device's secure hardware, you can use some variation of this code to suit your needs. You can paste this snippet after the same Log.d mentioned above in the example app's createKeys() method.

    KeyFactory factory = KeyFactory.getInstance(kp.getPrivate().getAlgorithm(), "AndroidKeyStore");
    KeyInfo keyInfo = null;
    try {
        keyInfo = factory.getKeySpec(kp.getPrivate(), KeyInfo.class);
    } catch (InvalidKeySpecException e) {
        e.printStackTrace();
    }
    if (keyInfo.isInsideSecureHardware())
        Log.d(TAG, "Key is supported in secure hardware");
    else
        Log.d(TAG, "Key is not supported in secure hardware");
like image 86
Steve Miskovetz Avatar answered Oct 19 '22 14:10

Steve Miskovetz