java - bulletin - august security patch android
GetEntry() de KeyStore de Android y generaKeyPair() lanzan excepciones a veces (1)
Mi aplicación de Android necesita cifrar un archivo para que pueda descifrar y leerlo más tarde. Esto no debe ser descifrado por otra persona que no sea la aplicación, incluso el usuario.
A continuación es cómo estoy haciendo el cifrado y descifrado. Esto funciona la mayoría del tiempo, pero algunas veces para algunos usuarios esto está fallando. No es específico de un teléfono en particular (Nexus7, Samsung, Motorola, HTC; todos los tipos informan sobre este problema), pero no todos los usuarios lo están experimentando. Solo algunos usuarios ocasionalmente.
Aquí está el código relevante:
encrypt() {
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
final KeyStore.PrivateKeyEntry entry;
if (!ks.containsAlias(CERT_ALIAS)) {
Calendar cal = Calendar.getInstance();
Date now = cal.getTime();
cal.add(Calendar.YEAR, 50);
Date end = cal.getTime();
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
kpg.initialize(new KeyPairGeneratorSpec.Builder(getApplicationContext())
.setAlias(CERT_ALIAS)
.setStartDate(now)
.setEndDate(end)
.setSerialNumber(BigInteger.valueOf(1))
.setSubject(new X500Principal("CN=" + CERT_ALIAS))
.build());
KeyPair kp = kpg.generateKeyPair();
}
entry = (KeyStore.PrivateKeyEntry) ks.getEntry(
CERT_ALIAS, null);
pub = entry.getCertificate().getPublicKey();
// use the pub key to encrypt
}
decrypt() {
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
final KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) ks.getEntry(
CERT_ALIAS, null);
PrivateKey key1 = entry.getPrivateKey();
// use the private key decrypt
}
Este código a veces lanza
java.lang.RuntimeException: error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long
at com.android.org.conscrypt.NativeCrypto.ENGINE_load_private_key(Native Method)
at com.android.org.conscrypt.OpenSSLEngine.getPrivateKeyById(OpenSSLEngine.java:66)
at android.security.AndroidKeyStore.engineGetKey(AndroidKeyStore.java:86)
at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:372)
at java.security.KeyStore.getEntry(KeyStore.java:644)
Así que modifiqué encrypt () para intentar obtener la entrada y, si se produce una excepción, generar un nuevo par de claves.
final KeyStore.PrivateKeyEntry entry = null;
if (ks.containsAlias(CERT_ALIAS)) {
try {
entry = (KeyStore.PrivateKeyEntry) ks.getEntry(
CERT_ALIAS, null);
} catch (Exception e) {
}
}
if (entry == null) {
//generate new key pair
}
Pero incluso esto está fallando a veces con la siguiente excepción.
java.lang.IllegalStateException: could not generate key in keystore
at android.security.AndroidKeyPairGenerator.generateKeyPair(AndroidKeyPairGenerator.java:100)
at java.security.KeyPairGenerator$KeyPairGeneratorImpl.generateKeyPair(KeyPairGenerator.java:275)
- ¿Qué estoy haciendo mal?
- ¿Cómo lo arreglo / trabajo alrededor de él?
- ¿Estas excepciones indican que los archivos están siendo manipulados?
- ¿Esto sucede para usuarios con contraseña / pin de bloqueo de pantalla?
- Antes de generar un nuevo par, ¿debo eliminar la entrada? (KeyStore.deleteEntry ())
Observé que el almacén de claves devuelve nulo después de cambiar la contraseña de bloqueo de pantalla / pin. Algunos otros también parecen haber experimentado este problema ( KeyStore getEntry devuelve nulo después de cambiar la contraseña )
Me topé con el problema de could not generate key in keystore
con una de mis aplicaciones y después de profundizar en ella con uno de los teléfonos afectados, descubrí que algunos dispositivos configuran que el patrón de desbloqueo / paso / pin del teléfono es diferente al Contraseña que realmente desbloquea el almacenamiento de claves. Si también quiere verificar que ese es su problema, puede usar el trabajo aquí: http://nelenkov.blogspot.com/2012/05/storing-application-secrets-in-androids.html para obtener el valor real sistema privado y los objetos públicos de KeyPairGenerator están llamando y verifican el código de retorno. No estoy seguro de por qué Google decidió ocultar el código de retorno detrás de un booleano, pero ahí lo tienen.
Puede desencadenar un desbloqueo del almacén de claves manualmente llamando a startActivity(new Intent("com.android.credentials.UNLOCK"));
pero esto podría no ayudar mucho. Por lo que he visto, si un teléfono está en este estado, se debe a que alguna aplicación del Administrador de dispositivos bloqueó el almacén de claves en segundo plano para que pueda configurar VPN o las credenciales de correo electrónico. Esto significa que el usuario realmente no sabe la contraseña. Todavía estoy buscando una solución alternativa (posiblemente descubra cómo las aplicaciones del Administrador de dispositivos obtienen acceso al almacén de claves para poder desbloquearlo de esa manera), pero es un tema delicado, como mínimo. Intentaré actualizar esto si encuentro más información en mis exploraciones, con suerte esto al menos apunta a algunas personas en la dirección correcta.