什么时候发生此错误,为什么?
回答: 加载Android密钥并从密钥库存储公共密钥时,如果状态为锁定或未初始化,则可能会发生此错误。
错误生成部分代码如下:
@NonNull public static AndroidKeyStorePublicKey loadAndroidKeyStorePublicKeyFromKeystore( @NonNull KeyStore keyStore, @NonNull String privateKeyAlias) throws UnrecoverableKeyException { KeyCharacteristics keyCharacteristics = new KeyCharacteristics(); int errorCode = keyStore.getKeyCharacteristics(privateKeyAlias, null, null, keyCharacteristics); if (errorCode != KeyStore.NO_ERROR) { throw (UnrecoverableKeyException) new UnrecoverableKeyException( "Failed to obtain information about private key") .initCause(KeyStore.getKeyStoreException(errorCode)); // this exception is generated } ...... ...... ...... }KeyStore有10个响应代码。他们是
// ResponseCodesNO_ERROR = 1;LOCKED = 2;UNINITIALIZED = 3;SYSTEM_ERROR = 4;PROTOCOL_ERROR = 5;PERMISSION_DENIED = 6;KEY_NOT_FOUND = 7;VALUE_CORRUPTED = 8;UNDEFINED_ACTION = 9;WRONG_PASSWORD = 10;
KeyStore具有3个状态。它们是解锁的,锁定的,未初始化的
NO_ERROR仅在状态为UNLOCKED时发生。对于您的升级情况,状态第一次为LOCKED或UNINITIALIZED,因此错误仅发生一次。
状态检查代码如下:
public State state() { execute('t'); switch (mError) { case NO_ERROR: return State.UNLOCKED; case LOCKED: return State.LOCKED; case UNINITIALIZED: return State.UNINITIALIZED; default: throw new AssertionError(mError); }}资源链接:
- AndroidKeyStoreProvider Java类
- KeyStore Java类
更新:
从您的错误日志中,现在很清楚
W/System.err﹕ Caused by: android.security.KeyStoreException: Invalid key blob
这是当用户尝试从LOCK / UNINITIALIZED解锁时引起的主要问题。默认情况下,它被定义为30秒计时。 这个问题是与API相关的实现问题。
private static final int AUTHENTICATION_DURATION_SEConDS = 30;
对于加密/解密,仅当用户刚刚通过设备凭据进行身份验证时,带有生成的密钥的某些数据才有效。错误发生于
// Try encrypting something, it will only work if the user authenticated within// the last AUTHENTICATION_DURATION_SEConDS seconds.cipher.init(Cipher.ENCRYPT_MODE, secretKey); // error is generated from here.
从这里抛出实际错误。您的错误是由产生的
InvalidKeyException。
解:
您必须
InvalidKeyException从catch参数中删除该类。这样仍然可以检查
InvalidKeyException。检查后,您必须再次尝试使用代码,以便该问题不会立即出现在眼睛中,但进行两次检查可能可以解决您的问题。我尚未测试代码,但应如下所示:
try {....KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) this.keyStore.getEntry("alias", null);....} catch (final Exception e) { e.printStackTrace(); if (e instanceof InvalidKeyException) { // bypass InvalidKeyException ....... // You can again call the method and make a counter for deadlock situation or implement your own pre according to your situation if (retry) { keyStore.deleteEntry(keyName); return getCypher(keyName, false); } else { throw e; } }}资源链接:
- MainActivity.java



