直接使用从密钥库加载的SecretKey时,未对密钥用户进行身份验证

时间:2020-08-31 04:04:32

标签: android encryption keystore

我正在尝试使用在KeyStore中加载的带有SecretKey的密码来加密数据,但总是会收到此错误:

原因:android.security.KeyStoreException:密钥用户未通过身份验证

我尝试自行创建SecretKeySpec。我正在使用android Q进行测试。

有人可以帮我解释一下问题吗?

我的代码

    public Cipher createCipher() {
        Cipher cipher;
        try {
            cipher = Cipher.getInstance(
                    KeyProperties.KEY_ALGORITHM_AES + "/"
                            + KeyProperties.BLOCK_MODE_CBC + "/"
                            + KeyProperties.ENCRYPTION_PADDING_PKCS7);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new RuntimeException("Failed to get Cipher", e);
        }
        return cipher;
    }

    public boolean initCipher() {
        try {
            cipher = createCipher();
            SecretKey key = KeyStoreTools.getSecretKey(KEY_NAME);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return true;
        } catch (KeyPermanentlyInvalidatedException e) {
            KeyStoreTools.removeAlias(KEY_NAME);
            return false;
        } catch (Throwable e) {
            throw new RuntimeException("Failed to init Cipher", e);
        }
    }
    public static SecretKey getSecretKey(String keyName) {
        Key key = getKey(keyName);
        if (!keyExists(key)) {
            key = generateKey(keyName);
        }
        return (SecretKey) key;
    }

    public static SecretKey generateKey(String keyName) {
        SecretKey secretKey = null;
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
            KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(keyName,
                    KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT);
            builder.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                    .setUserAuthenticationRequired(true)
                    .setEncryptionPaddings(
                            KeyProperties.ENCRYPTION_PADDING_PKCS7);
            keyGenerator.init(builder.build());
            secretKey = keyGenerator.generateKey();
        } catch (NoSuchAlgorithmException | NoSuchProviderException exc) {
            exc.printStackTrace();
        } catch (Throwable e) {
            throw new RuntimeException("Failed to generateKey", e);
        }
        return secretKey;
    }

    public String encrypt(Cipher cipher, byte[] dataToEncrypt) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(dataToEncrypt);
            byte[] enc = cipher.doFinal(md.digest());
            String base64 = Base64.encodeToString(enc, Base64.DEFAULT);
            return base64;
        } catch (BadPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException e ) {
            e.printStackTrace();
        }
        return "";
    }

1 个答案:

答案 0 :(得分:0)

我的问题引发,因为:

在将密钥标记为成功进行用户身份验证之前,我使用密码进行加密。因此,在onAuthenticationSucceeded中移动加密就可以了。

希望我的回答对别人有帮助。