直接使用从密钥库加载的SecretKey时,未对密钥用户进行身份验证 [英] Key user not authenticated when using a SecretKey directly as loaded from keystore

查看:115
本文介绍了直接使用从密钥库加载的SecretKey时,未对密钥用户进行身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用在KeyStore中加载的带有SecretKey的Cipher加密数据,但始终会收到此错误:

I'm trying to encrypt data use Cipher with SecretKey loaded in KeyStore but always got this error :

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

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

I tried creating SecretKeySpec myself it worked. I'm using android Q to test.

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

Can anyone help me explain the problem?

我的代码

    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 "";
    }

推荐答案

我的问题抛出的原因是:

My issue throw because :

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

I encrypt using the cipher before the key has been flagged for successful user authentication. So move encrypt in onAuthenticationSucceeded and it's worked.

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

Hope my answer will help someone else.

这篇关于直接使用从密钥库加载的SecretKey时,未对密钥用户进行身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆