首页 > 解决方案 > KeyStore“不支持的保护参数”

问题描述

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

当我运行它时,我似乎得到了以下异常:

java.security.KeyStoreException:不支持的保护参数

当我调用keyStore.setEntry(...).

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

@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();
}

标签: javaandroidcryptographyandroid-keystore

解决方案


原来我遇到的问题是在我的KeyStore.getInstanceKeyGenerator.getInstance行中。其中一个正在使用KeyStore.getDefaultType()where 另一个正在使用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();
}

推荐阅读