简体   繁体   English

Google PIxel设备上的InvalidKeyException

[英]InvalidKeyException on Google PIxel devices

My app is using Android's keystore to encrypt some data after authenticating with a fingerprint. 我的应用程序正在使用Android的密钥存储区,并在通过指纹验证后对一些数据进行加密。 Users of Google Pixel devices are reporting the following exception being thrown: Google Pixel设备的用户报告正在抛出以下异常:

java.security.InvalidKeyException: Only SecretKey is supported java.security.InvalidKeyException:仅支持SecretKey

My code for encryption basically does this: 我的加密代码基本上是这样做的:

_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));

It seems like GetKey returns null. 似乎GetKey返回null。 Do these new devices only support asymmetric encryption? 这些新设备仅支持非对称加密吗? Does this mean I need to generate a key pair or is there another solution? 这是否意味着我需要生成密钥对,或者还有其他解决方案?

try this code of mine if it can help 尝试我的这段代码是否有帮助

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM