Colton Weaver
Colton Weaver

Reputation: 53

Storing a secret key in Android KeyStore using API 18 and Above

Security is not my area of expertise but I have a question regarding storing a secret key in the Android KeyStore using API 18 and above. I use the following code to try and store my key:

KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);

KeyStore.SecretKeyEntry sKeyEntry = new KeyStore.SecretKeyEntry(ivKey);

ks.setEntry(ALIAS, sKeyEntry, null); // This is where the issue is

I understand that "null" should be a KeyProtection param that I build but this isn't available for API 18. Is there a workaround for this issue? I have been having difficulty finding anything that works.

EDIT I should mention that leaving it as null throws the error:

java.security.KeyStoreException: Protection parameters must be specified when importing a symmetric key

Upvotes: 4

Views: 5605

Answers (2)

Dhaval
Dhaval

Reputation: 2874

For creating a RSA(Public/Private) key using AndroidKeyStore you can use following methods.

Getting a KeyStore

val keyStore = KeyStore.getInstance("AndroidKeyStore")
keyStore.load(null)

Check if KeyStore contains our key or not

If KeyStore does not contains key, then create keys

    if (!keyStore.containsAlias(KEY_NAME)) {

        val keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore")
        keyPairGenerator.initialize(
            KeyGenParameterSpec.Builder(
                KEY_NAME,
                KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
            )
                .setAlgorithmParameterSpec(RSAKeyGenParameterSpec(2048, F4))
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
                .build()
        )

        val keyPair = keyPairGenerator.generateKeyPair()
        val publicKey = keyPair.public
        val privateKey = keyPair.private
    }

Retrieve keys using KEY_NAME

val privateKeyEntry = keyStore.getEntry(KEY_NAME, null) as KeyStore.PrivateKeyEntry
val privateKey = privateKeyEntry.privateKey
val publicKey = privateKeyEntry.certificate.publicKey

For more information you can refer this:

Upvotes: 0

divegeek
divegeek

Reputation: 5032

AndroidKeyStore did not support secret keys until API level 23. To do what you're trying to do you have to target 23 or above.

What you could do is use AndroidKeyStore's support for public/private key pairs (e.g. RSA) to encrypt the secret key material, then store it in a local file. When you want to use it, you'd need to use the private key to decrypt it, then once you have the key material use the normal Java crypto APIs (i.e. don't specify "AndroidKeyStore") to do cipher operations with it.

To see how to use AndroidKeyStore RSA key pairs to encrypt and decrypt, take a look at http://www.androidauthority.com/use-android-keystore-store-passwords-sensitive-information-623779/

However, I don't think that actually achieves anything from a security perspective. What security goals are you trying to achieve?

Upvotes: 1

Related Questions