Java – Stores hmac keys in the Android keystore

Stores hmac keys in the Android keystore… here is a solution to the problem.

Stores hmac keys in the Android keystore

I’m using the following code to create an hmac key and return it as a string.

KeyGenerator keyGen = null;
    try {
        keyGen = KeyGenerator.getInstance("HmacSHA256");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    SecretKey key = keyGen.generateKey();
    byte[] encoded = key.getEncoded();
    String s=Base64.encodeToString(encoded, Base64.DEFAULT);
    Log.i("Hmac key before encrypt",s);

try {
        KeyStore keystore = KeyStore.getInstance("AndroidKeyStore");
        keystore.load(null, null);
        KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keystore.getEntry("temp", null);
        RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey();

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] cipherBytes = cipher.doFinal(encoded);

return Base64.encodeToString(cipherBytes,Base64.DEFAULT);

} catch (UnrecoverableEntryException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

How do I store it in an Android Keystore?. I tried the following code:

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

KeyStore.ProtectionParameter param = new KeyStore.PasswordProtection("test".toCharArray());
        keyStore.setEntry("key1",hmacKey,param);

Regardless of the format of hmacKey, I get the error message: String/Bytes or javax.crypto.SecretKey. Here are the errors:
If you pass the key hmacKey:

Wrong 2nd argument type. Found: 'java.security.Key', required: 'java.security.KeyStore.Entry'

The same is true in the case where I pass a string or byte array.

If I convert the parameter type to java.security.KeyStore.Entry, it still doesn’t work.

Is this the right thing to do? Anyone can point out how to store the HMAC key in the keystore using aliases. How do I convert hmack key to java.security.KeyStore.Entry?

Solution

The Android keystore was created so that you can use asymmetric keys and symmetric keys outside of your application code. For example< specify a href="http://developer.android.com/training/articles/keystore.html" rel="noreferrer noopener nofollow">in the training material :

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 will not be able to extract their key material (for example, to be used outside of the Android device).

Therefore, the idea of

generating keys inside the application code – and therefore outside of the key store – is not a good idea. API for the The keyGenParameterSpec class defines how keys are generated in the keystore for HMAC keys. :

KeyGenerator keyGenerator = KeyGenerator.getInstance(
         KeyProperties.KEY_ALGORITHM_HMAC_SHA256, "AndroidKeyStore");
keyGenerator.initialize(
         new KeyGenParameterSpec.Builder("key2", KeyProperties.PURPOSE_SIGN).build());
SecretKey key = keyGenerator.generateKey();
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(key);
...

 The key can also be obtained from the Android Keystore any time as follows:
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
key = (SecretKey) keyStore.getKey("key2", null);

Other key types can be found< a href="http://developer.android.com/reference/android/security/keystore/KeyProperties.html" rel="noreferrer noopener nofollow">in the KeyProperties class

Related Problems and Solutions