密钥库 "unsupported protection parameter"

KeyStore "unsupported protection parameter"

我正在尝试将 SecretKey 存储在 Android KeyStore 中,我什至直接按照此处找到的文档进行操作:KeyProtection: AES Key for Encryption / Description in GCM Mode,但仍然不起作用。

当我 运行 这个时,我似乎得到以下异常:

java.security.KeyStoreException: unsupported protection parameter

这个异常是在我调用keyStore.setEntry(...).

时专门引发的

我 运行宁 Android 10 在三星 Galaxy S10 上,如果这有什么不同的话。

@RequiresApi(23)
private static KeyStore.ProtectionParameter getProtectionParameter() {
    return new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
            .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
            .build();
}

@RequiresApi(23)
private static SecretKey getSecretKey() throws Exception {
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    keyStore.load(null);

    if (keyStore.containsAlias(KEY_ALIAS)) {
        final KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore
                .getEntry(KEY_ALIAS, null);
        return secretKeyEntry.getSecretKey();
    }

    final KeyGenerator keyGenerator = KeyGenerator
            .getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
    final KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(KEY_ALIAS,
            KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
            .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
            .build();

    keyGenerator.init(keyGenParameterSpec);
    SecretKey k = keyGenerator.generateKey();

    keyStore.setEntry(
        KEY_ALIAS,
        new KeyStore.SecretKeyEntry(k),
        getProtectionParameter()
    );

    return getSecretKey();
}

事实证明我遇到的问题是在 KeyStore.getInstanceKeyGenerator.getInstance 行中。其中一个使用 KeyStore.getDefaultType(),而另一个使用 AndroidKeyStore。改变这个摆脱了 unsupported protection parameter 问题。

此外,在修复该问题后,我 运行 遇到了更新保护参数的问题。

事实证明,以下代码部分不正确

SecretKey k = keyGenerator.generateKey();

keyStore.setEntry(
    KEY_ALIAS,
    new KeyStore.SecretKeyEntry(k),
    getProtectionParameter()
);

它尝试将密钥插入密钥库两次,因为 generateKey() 已经将它插入密钥库。

完整的工作代码如下所示

@RequiresApi(23)
private static SecretKey getSecretKey() throws Exception {
    KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
    keyStore.load(null, null);

    final KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore
                .getEntry(KEY_ALIAS, null);
    if (secretKeyEntry != null) {
        return secretKeyEntry.getSecretKey();
    }

    final KeyGenerator keyGenerator = KeyGenerator
            .getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
    final KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(KEY_ALIAS,
            KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
            .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
            .build();

    keyGenerator.init(keyGenParameterSpec);
    SecretKey k = keyGenerator.generateKey();
    return getSecretKey();
}