Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to employ keyed-hash message authentication code (HMAC) with Android Keystore

I am investigating the use of the Android KeyStore for Marshmallow and above.

I would like to simultaneously verify both the data integrity and the authentication of my data by employing HMAC's.

How do I go about achieving this?

I am current generating an Encrypt/Decrypt key as follows:-

        mKeyStore = KeyStore.getInstance(keyStoreName);
        mKeyStore.load(mKeyStoreLoadStoreParameter);

        if (mKeyStore.containsAlias(keyStoreAlias)) {
            mSecretKey = (SecretKey) mKeyStore.getKey(keyStoreAlias, KEY_STORE_PASSWORD);
        } else {
            final KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, keyStoreName);
            final int keyPurpose = KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT;

            keyGenerator.init(
                    new KeyGenParameterSpec.Builder(keyStoreAlias, keyPurpose)
                            .setKeySize(KEY_STORE_KEY_SIZE)
                            .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                            .setRandomizedEncryptionRequired(true)
                            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                            .build());

            mSecretKey = keyGenerator.generateKey();

I have found this sample for generating HMAC's

SecretKey key = ...; // HMAC key of algorithm "HmacSHA512".

 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 keyStore.load(null);
 keyStore.setEntry(
         "key1",
         new KeyStore.SecretKeyEntry(key),
         new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN).build());
 // Key imported, obtain a reference to it.
 SecretKey keyStoreKey = (SecretKey) keyStore.getKey("key1", null);
 // The original key can now be discarded.

 Mac mac = Mac.getInstance("HmacSHA512");
 mac.init(keyStoreKey);

However, how do I use this when encrypting/decrypting my data?

EXPLANATION

I have a number of choices/decisions to make when implementing security/cryptography within any Android application.

1). Do I implement cryptography of any sort Yes or No? 2). If Yes then... I should attempt to achieve the "most" secure solution possible.

If I am going to employ cryptography then I need to ensure the following.

a). I store passwords/secret keys in a "Safe Place" e.g. Android Key Store. b). I use the "strongest" cryptography available. c). I would like to simultaneously verify both the data integrity and the authentication of my data, e.g. I would like to detect if my encrypted data has been tampered with.

As I understand what I have read about HMAC's, they provide this functionality. I would like to know how I code the use of HMAC's into my Android application to ensure both the data integrity and the authentication of my data.

like image 601
Hector Avatar asked Oct 20 '17 13:10

Hector


1 Answers

You can apply HMAC to the plain text HMAC(plain text) before encrypting and recompute the HMAC after decrypting to check that the original message is the same.

It may be redundant because if the cipher text is altered you will not be able to decrypt it.

First generate a HMAC key inside AndroidKeyStore. I found an example here

KeyGenerator keyGenerator = KeyGenerator.getInstance(
         KeyProperties.KEY_ALGORITHM_HMAC_SHA256, "AndroidKeyStore");
keyGenerator.initialize(
         new KeyGenParameterSpec.Builder(hmacKeyAlias, KeyProperties.PURPOSE_SIGN).build());
SecretKey key = keyGenerator.generateKey();

Then Apply HMAC to the original data and store the result somewhere

Mac mac = Mac.getInstance("HmacSHA256");
mac.init(key);
byte hmacOriginalData[] = mac.doFinal(dataToEncrypt);
//Store hmacOriginalData 

After decrypting, get HMAC key from AndroidKeyStore, recompute HMAC and check both macs are equal

Key key = keyStore.getKey(hmacKeyAlias, null);
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(key);
byte hmacDecryptedData[] = mac.doFinal(decryptedData);
//Check equals(hmacDecryptedData, hmacOriginalData);
like image 58
pedrofb Avatar answered Nov 05 '22 14:11

pedrofb