java android keystore private-key java-security

java.security.UnrecoverableKeyException: no se pudo obtener información sobre la clave privada



android keystore (1)

Tengo las siguientes líneas para obtener la clave privada del almacén de claves en Android

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); // generating key pair code omitted KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) this.keyStore.getEntry("alias", null);

Todo funciona bien, excepto que cuando el sistema operativo se actualiza de Android 5.1.1 a Android 6.0.1, la tercera línea lanzará java.security.UnrecoverableKeyException: Failed to obtain information about private key para la primera ejecución. Pero funcionará bien de nuevo después. Ahora mi solución es ejecutar la línea 2 veces. Al mismo tiempo, también me pregunto si hay una mejor manera de evitar la excepción.

Actualizar

La traza de excepción

W/System.err﹕ java.security.UnrecoverableKeyException: Failed to obtain information about private key W/System.err﹕ at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStorePublicKeyFromKeystore(AndroidKeyStoreProvider.java:217) W/System.err﹕ at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(AndroidKeyStoreProvider.java:253) W/System.err﹕ at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStorePrivateKeyFromKeystore(AndroidKeyStoreProvider.java:263) W/System.err﹕ at android.security.keystore.AndroidKeyStoreSpi.engineGetKey(AndroidKeyStoreSpi.java:93) W/System.err﹕ at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:372) W/System.err﹕ at java.security.KeyStore.getEntry(KeyStore.java:645) W/System.err﹕ at com.example.keystoretest.MainActivity.onCreate(MainActivity.java:113) W/System.err﹕ at android.app.Activity.performCreate(Activity.java:6251) W/System.err﹕ at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) W/System.err﹕ at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) W/System.err﹕ at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) W/System.err﹕ at android.app.ActivityThread.-wrap11(ActivityThread.java) W/System.err﹕ at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) W/System.err﹕ at android.os.Handler.dispatchMessage(Handler.java:102) W/System.err﹕ at android.os.Looper.loop(Looper.java:148) W/System.err﹕ at android.app.ActivityThread.main(ActivityThread.java:5417) W/System.err﹕ at java.lang.reflect.Method.invoke(Native Method) W/System.err﹕ at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) W/System.err﹕ at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) W/System.err﹕ Caused by: android.security.KeyStoreException: Invalid key blob W/System.err﹕ at android.security.KeyStore.getKeyStoreException(KeyStore.java:632) W/System.err﹕ at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStorePublicKeyFromKeystore(AndroidKeyStoreProvider.java:218) W/System.err﹕ ... 18 more


¿Cuándo ocurre este error y por qué?

Respuesta: Cuando se cargan las claves de Android y se almacena una clave pública desde el Almacén de claves, este error puede ocurrir si el estado está bloqueado o sin inicializar.

El error que genera el código de la parte se da a continuación:

@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 tiene 10 códigos de respuesta. Son

// ResponseCodes NO_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 tiene 3 estados. Están DESBLOQUEADOS, BLOQUEADOS, ININITIALIZADOS.

NO_ERROR solo ocurre cuando el estado está DESBLOQUEADO. Para su caso de actualización, el estado es BLOQUEADO o SININICIALIZADO por primera vez, por lo que el error se produce solo una vez.

El código de verificación del estado se da a continuación:

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

Enlace de recursos:

  1. AndroidKeyStoreProvider clase java
  2. KeyStore java class

ACTUALIZAR:

De su registro de errores, ahora está claro que

W/System.err﹕ Caused by: android.security.KeyStoreException: Invalid key blob

este es el problema principal que se produce cuando el usuario intenta DESBLOQUEAR desde BLOQUEO / UNINITIALIZADO. Se define de forma predeterminada como 30 segundos para el tiempo. Este problema es su problema de implementación relacionado con la API.

/** * If the user has unlocked the device Within the last this number of seconds, * it can be considered as an authenticator. */ private static final int AUTHENTICATION_DURATION_SECONDS = 30;

Para el cifrado / descifrado, algunos datos con la clave generada solo funcionan si el usuario acaba de autenticarse mediante las credenciales del dispositivo. El error se produce desde

// 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.

El error real se produce desde aquí. Su error se genera desde InvalidKeyException .

Solución:

InvalidKeyException eliminar la clase InvalidKeyException del argumento catch. Esto aún le permitirá verificar si hay InvalidKeyException . Después de verificar, debe intentar el código por segunda vez para que el problema no se muestre a simple vista, pero si lo hace dos veces, puede resolver su problema. No he probado el código pero debería ser como a continuación:

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 code according to your situation if (retry) { keyStore.deleteEntry(keyName); return getCypher(keyName, false); } else { throw e; } } }

Enlace de recursos:

  1. MainActivity.java
  2. android.security.KeyStoreException: Blob de clave no válida