从Android Keystore获取SecretKey并与Realm IO一起使用

时间:2016-08-08 07:07:47

标签: android realm android-keystore

我使用Realm作为我的本地数据库,需要加密。我试图使用Android Keystore来存储一个SecretKey,它似乎将它存储在KeyStore中,但是当我尝试使用SecretKey.getEncoded()时,它总是返回null。这是代码:

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        Enumeration<String> aliases = keyStore.aliases();

        while(aliases.hasMoreElements()) {
            Log.v("KEY ALIAS",aliases.nextElement());
        }


        SecretKey keyStoreKey = (SecretKey) keyStore.getKey(ALIAS, null);

        if(keyStoreKey == null) {
            Log.v("NO KEY","USING NEW KEY");
            KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(ALIAS,
                    KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT);
            KeyGenParameterSpec keySpec = builder
                    .setKeySize(512)
                    .setRandomizedEncryptionRequired(true)
                    .setUserAuthenticationRequired(true)
                    .setUserAuthenticationValidityDurationSeconds(5 * 60)
                    .build();

            KeyGenerator kg = KeyGenerator.getInstance("HmacSHA1", "AndroidKeyStore");
            kg.init(keySpec);
            keyStoreKey = kg.generateKey();

            keyStore.setEntry(ALIAS,
                    new KeyStore.SecretKeyEntry(keyStoreKey),
                    new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                            .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                            .build());
        } else {
            Log.v("GOT KEY","USING OLD KEY");
        }

        //THIS IS THE LINE THAT RETURNS NULL WHEN USING A KEY FROM KEYSTORE
        byte[] key = keyStoreKey.getEncoded();

然后我将在领域中使用字节数组'key'。代码在首次启动时(在创建密钥时)工作正常但如果它在密钥库中找到它,则在获取密钥的字节时它只返回null。

1 个答案:

答案 0 :(得分:2)

这是故意的。 Android KeyStore在保存后不会公开密钥材料,您只能要求KeyStore代表您执行操作。

一种解决方案是使用双层密钥。它的工作方式大致如下:

  1. 生成要用于解锁领域的密钥(keyA)。
  2. 生成第二个随机密钥(keyB)。
  3. 将KeyB保存在KeyStore中。
  4. 使用keyB加密keyA。这是一个随机字符串,你可以保存在任何地方。
  5. 将加密版本的keyA保存在SharedPreferences中。
  6. 打开Realm时,从KeyStore中的SharedPreferences解密加密的keyA(使用KeyB)并将其提供给Realm。
  7. 我们正在开展示范项目here(仍在进行中)。