有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

谷歌像素设备上的java InvalidKeyException

我的应用程序使用安卓系统的密钥库,在用指纹进行身份验证后,对一些数据进行加密。Google Pixel设备的用户报告引发了以下异常:

爪哇。安全InvalidKeyException:仅支持SecretKey

我的加密代码基本上是这样做的:

_keystore.Load(null);
                _keyGen.Init(new KeyGenParameterSpec.Builder(_keyId,
                    KeyStorePurpose.Encrypt | KeyStorePurpose.Decrypt)
                    .SetBlockModes(KeyProperties.BlockModeCbc)
                    // Require the user to authenticate with a fingerprint to authorize every use
                    // of the key
                    .SetUserAuthenticationRequired(true)
                    .SetEncryptionPaddings(KeyProperties.EncryptionPaddingPkcs7)
                    .Build());
                _keyGen.GenerateKey();

Cipher _cipher = Cipher.GetInstance(KeyProperties.KeyAlgorithmAes + "/"
                                              + KeyProperties.BlockModeCbc + "/"
                                              + KeyProperties.EncryptionPaddingPkcs7);

KeyStore _keystore = KeyStore.GetInstance("AndroidKeyStore");
FingerprintManager _fingerprintManager = (FingerprintManager) Context.GetSystemService(Context.FingerprintService);

_keystore.Load(null);
var key = _keystore.GetKey(_keyId, null);
_cipher.Init(CipherMode.EncryptMode, key);
_cryptoObject = new FingerprintManager.CryptoObject(_cipher);
_fingerprintManager.Authenticate(_cryptoObject, _cancellationSignal, 0 /* flags */, this, null);

//OnAuthSucceeded:
var mySecret = _cipher.DoFinal(System.Text.Encoding.UTF8.GetBytes(textToEncrypt));

GetKey似乎返回null。这些新设备只支持非对称加密吗?这意味着我需要生成密钥对,还是有其他解决方案


共 (1) 个答案

  1. # 1 楼答案

    如果可以的话,试试我的代码

    public KeyStore getKeyStore() {
        try {
            return KeyStore.getInstance("AndroidKeyStore");
        } catch (KeyStoreException exception) {
            throw new RuntimeException("Failed to get an instance of KeyStore", exception);
        }
    }
    
    public KeyPairGenerator getKeyPairGenerator() {
        try {
            return KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
        } catch(NoSuchAlgorithmException | NoSuchProviderException exception) {
            throw new RuntimeException("Failed to get an instance of KeyPairGenerator", exception);
        }
    }
    
    public Cipher getCipher() {
        try {
            return Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        } catch(NoSuchAlgorithmException | NoSuchPaddingException exception) {
            throw new RuntimeException("Failed to get an instance of Cipher", exception);
        }
    }
    
    private void createKeyPair() {
        try {
            mKeyPairGenerator.initialize(
                    new KeyGenParameterSpec.Builder(KEY_ALIAS, KeyProperties.PURPOSE_DECRYPT)
                            .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
                            .setUserAuthenticationRequired(true)
                            .build());
            mKeyPairGenerator.generateKeyPair();
        } catch(InvalidAlgorithmParameterException exception) {
            throw new RuntimeException("Failed to generate key pair", exception);
        }
    }
    
    private boolean initCipher(int opmode) {
        try {
            mKeyStore.load(null);
    
            if(opmode == Cipher.ENCRYPT_MODE) {
                PublicKey key = mKeyStore.getCertificate(KEY_ALIAS).getPublicKey();
    
                PublicKey unrestricted = KeyFactory.getInstance(key.getAlgorithm())
                        .generatePublic(new X509EncodedKeySpec(key.getEncoded()));
    
                OAEPParameterSpec spec = new OAEPParameterSpec(
                        "SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);
    
                mCipher.init(opmode, unrestricted, spec);
            } else {
                PrivateKey key = (PrivateKey) mKeyStore.getKey(KEY_ALIAS, null);
                mCipher.init(opmode, key);
            }
    
            return true;
        } catch (KeyPermanentlyInvalidatedException exception) {
            return false;
        } catch(KeyStoreException | CertificateException | UnrecoverableKeyException
                | IOException | NoSuchAlgorithmException | InvalidKeyException
                | InvalidAlgorithmParameterException exception) {
            throw new RuntimeException("Failed to initialize Cipher", exception);
        }
    }
    
    private void encrypt(String password) {
        try {
            initCipher(Cipher.ENCRYPT_MODE);
            byte[] bytes = mCipher.doFinal(password.getBytes());
            String encrypted = Base64.encodeToString(bytes, Base64.NO_WRAP);
            mPreferences.getString("password").set(encrypted);
        } catch(IllegalBlockSizeException | BadPaddingException exception) {
            throw new RuntimeException("Failed to encrypt password", exception);
        }
    }
    
    private String decrypt(Cipher cipher) {
        try {
            String encoded = mPreferences.getString("password").get();
            byte[] bytes = Base64.decode(encoded, Base64.NO_WRAP);
            return new String(cipher.doFinal(bytes));
        } catch (IllegalBlockSizeException | BadPaddingException exception) {
            throw new RuntimeException("Failed to decrypt password", exception);
        }
    }