Preferencias cifradas en Android

Buenas tardes Mi nombre es Dmitry y soy profesor del curso básico "Desarrollador de Android" en Otus. Hoy decidí compartir una traducción del artículo, que me parece interesante y creo que puede ser útil para muchos lectores de nuestro blog.







Almacenar datos en SharedPreferences es muy rápido y conveniente. También es fácil para los atacantes mirar los datos almacenados en SharedPreferences ... así que ten cuidado con lo que pones allí, y es posible que tengas que pensar cómo almacenar los datos en un formato cifrado.

Para pequeñas cantidades de datos que no justifican el uso de un motor de base de datos, como SqlCipher, nuestras capacidades fueron limitadas:

  • Métodos de cifrado nativos (si sabe lo que está haciendo)
  • Soluciones listas para usar como preferencias seguras, otras preferencias seguras, armadillo, etc.
  • Combatir los problemas más extraños del ciclo de vida del sistema Android Keystore en cada versión de Android

Esto funcionó antes, pero ahora tenemos la solución correcta y oficial .
Aunque todavía es alfa, funcionó bien durante un tiempo cuando lo usé en mis proyectos. El uso de EncryptedSharedPreferences es bienvenido (o puede usarlo), para todos los suyos con min-sdk 23+ .

Veamos un ejemplo de cómo usarlo:

Ejemplo de EncryptedSharedPreferences


SDK mínimo


Hoy 23 (Android 6.0)

minSdkVersion 23 

Agregar dependencias


 implementation "androidx.security:security-crypto:1.0.0-alpha02" 

Inicializar / Abrir


Simplemente cree o recupere la clave maestra del almacén de claves de Android y úsela para inicializar / abrir la instancia de EncryptedSharedPreferences:

 //  1:    -   /  val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) //  2.  /   EncryptedSharedPreferences val sharedPreferences = EncryptedSharedPreferences.create( "PreferencesFilename", masterKeyAlias, applicationContext, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) 

Guardar registros


Guarde los datos como siempre lo hizo con SharedPreferences:

 //  3.    EncryptedSharedPreferences sharedPreferences.edit() .putString("DATA", saveText.text.toString()) .apply() 


Leer notas


Lea los datos como siempre lo hizo con SharedPreferences:
 //  3:    EncryptedSharedPreferences val value = sharedPreferences.getString("DATA", "") 

¿Están los ajustes realmente encriptados?


Sí, y realmente bastante bien encriptado.

Digamos que puse el valor SharedPreferences en SharedPreferences . Así se verá el archivo:

 <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="DATA">akaita</string> </map> 

Si agrego el valor akaita a EncryptedSharedPreferences , obtengo algo completamente diferente:

 <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="AVz2qCVxm1KudCCJKYuxuoaAXoPeWKjG0w==">ASnO9uni11t3m9sNgDJbiYllL/tE+i99TYKfQ0h8XV6AUN0O3rBxBsMmcpw2DCY=</string> <string name="__androidx_security_crypto_encrypted_prefs_key_keyset__">12a901eb372af4775b09f5b51d20d49428931c5d8e0b17dd103d2169c1879b8b13958274d7e25d3cc052f301461495fd40b70806ae244f456726802460318bdf19dce444e7a60f20c903c5a57140ea8e90a19a1b48559961d145a50000d1c0e22ca918b02ea0cc34e433900f44c00e9c791ecb678f26d293c0226d6c2a9e25e610616ec34241b06410481427a850eeedf85ee4c725d5dbd715b5a8d0e017be9a568a9f960989271d14d2d0531a4408a5d0dae705123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118a5d0dae7052001</string> <string name="__androidx_security_crypto_encrypted_prefs_value_keyset__">12880189e734bbbf9cfa3bc15b5e53ea8df03341269cf97112a60a1f6482732dd33248b3f821397fb04ef3372ff54336e9045a0b0c0fb7afdf475dbc98a1107d09de66afcc5ad063e5e5b59a7d616e14834e19769bc84de7e5c8716a811814a6cd7a6d72a1c64ce4317f2f482181c437b70f010219ca6407a98bac18f1101c02fd8e2c4a9009ad2a1ebbdc1a4408e9edbbce02123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118e9edbbce022001</string> </map> "> 12a901eb372af4775b09f5b51d20d49428931c5d8e0b17dd103d2169c1879b8b13958274d7e25d3cc052f301461495fd40b70806ae244f456726802460318bdf19dce444e7a60f20c903c5a57140ea8e90a19a1b48559961d145a50000d1c0e22ca918b02ea0cc34e433900f44c00e9c791ecb678f26d293c0226d6c2a9e25e610616ec34241b06410481427a850eeedf85ee4c725d5dbd715b5a8d0e017be9a568a9f960989271d14d2d0531a4408a5d0dae705123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118a5d0dae7052001 </ string> <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="AVz2qCVxm1KudCCJKYuxuoaAXoPeWKjG0w==">ASnO9uni11t3m9sNgDJbiYllL/tE+i99TYKfQ0h8XV6AUN0O3rBxBsMmcpw2DCY=</string> <string name="__androidx_security_crypto_encrypted_prefs_key_keyset__">12a901eb372af4775b09f5b51d20d49428931c5d8e0b17dd103d2169c1879b8b13958274d7e25d3cc052f301461495fd40b70806ae244f456726802460318bdf19dce444e7a60f20c903c5a57140ea8e90a19a1b48559961d145a50000d1c0e22ca918b02ea0cc34e433900f44c00e9c791ecb678f26d293c0226d6c2a9e25e610616ec34241b06410481427a850eeedf85ee4c725d5dbd715b5a8d0e017be9a568a9f960989271d14d2d0531a4408a5d0dae705123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118a5d0dae7052001</string> <string name="__androidx_security_crypto_encrypted_prefs_value_keyset__">12880189e734bbbf9cfa3bc15b5e53ea8df03341269cf97112a60a1f6482732dd33248b3f821397fb04ef3372ff54336e9045a0b0c0fb7afdf475dbc98a1107d09de66afcc5ad063e5e5b59a7d616e14834e19769bc84de7e5c8716a811814a6cd7a6d72a1c64ce4317f2f482181c437b70f010219ca6407a98bac18f1101c02fd8e2c4a9009ad2a1ebbdc1a4408e9edbbce02123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118e9edbbce022001</string> </map> "> 12880189e734bbbf9cfa3bc15b5e53ea8df03341269cf97112a60a1f6482732dd33248b3f821397fb04ef3372ff54336e9045a0b0c0fb7afdf475dbc98a1107d09de66afcc5ad063e5e5b59a7d616e14834e19769bc84de7e5c8716a811814a6cd7a6d72a1c64ce4317f2f482181c437b70f010219ca6407a98bac18f1101c02fd8e2c4a9009ad2a1ebbdc1a4408e9edbbce02123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118e9edbbce022001 </ string> <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="AVz2qCVxm1KudCCJKYuxuoaAXoPeWKjG0w==">ASnO9uni11t3m9sNgDJbiYllL/tE+i99TYKfQ0h8XV6AUN0O3rBxBsMmcpw2DCY=</string> <string name="__androidx_security_crypto_encrypted_prefs_key_keyset__">12a901eb372af4775b09f5b51d20d49428931c5d8e0b17dd103d2169c1879b8b13958274d7e25d3cc052f301461495fd40b70806ae244f456726802460318bdf19dce444e7a60f20c903c5a57140ea8e90a19a1b48559961d145a50000d1c0e22ca918b02ea0cc34e433900f44c00e9c791ecb678f26d293c0226d6c2a9e25e610616ec34241b06410481427a850eeedf85ee4c725d5dbd715b5a8d0e017be9a568a9f960989271d14d2d0531a4408a5d0dae705123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118a5d0dae7052001</string> <string name="__androidx_security_crypto_encrypted_prefs_value_keyset__">12880189e734bbbf9cfa3bc15b5e53ea8df03341269cf97112a60a1f6482732dd33248b3f821397fb04ef3372ff54336e9045a0b0c0fb7afdf475dbc98a1107d09de66afcc5ad063e5e5b59a7d616e14834e19769bc84de7e5c8716a811814a6cd7a6d72a1c64ce4317f2f482181c437b70f010219ca6407a98bac18f1101c02fd8e2c4a9009ad2a1ebbdc1a4408e9edbbce02123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118e9edbbce022001</string> </map> 

Además, el archivo encriptado cambiará cada vez que guardemos, lo que dificulta el acceso.

Gran advertencia: rendimiento


Hay una diferencia de rendimiento significativa entre SharedPreferences y EncryptedSharedPreferences.

Puede verificarlo usted mismo usando mi código de muestra o simplemente descargando la aplicación de muestra de Play Store. Yo mismo realizo varias pruebas en un dispositivo real, obteniendo los siguientes resultados:


EncryptedSharedPreferences vs. SharedPreferences


Gráfico "EncryptedSharedPreferences versus SharedPreferences"

Conclusión


EncryptedSharedPreferences es una solución confiable y muy simple para Android 6.0 y superior.

Tiene dos grandes ventajas:

  1. No necesitamos codificar nada en nuestro código. Simplemente usa Android Keystore para nosotros, eliminando la necesidad de lidiar con eso.
  2. el usuario no necesita configurar una pantalla de bloqueo. EncryptedSharedPreferences funcionará igual de bien sin un bloqueo de pantalla

Este es un reemplazo casi completo para SharedPreferences. Solo asegúrese de que la inicialización / apertura de EncryptedSharedPreferences no afecte negativamente a sus usuarios.

Esta decisión definitivamente permanecerá. Lo uso en cualquier escenario adecuado. Ahora solo quiero decir que los chicos de Android mejorarán su rendimiento, por lo que podemos preocuparnos aún menos :)

Ejemplo de aplicación


Solo para que sea más fácil probar y asegurarse de que todo esté bien conectado, creé una aplicación para usted. ¡Descárgalo o compila y pruébalo!

https://github.com/akaita/encryptedsharedpreferences-example

Ponga un punto a favor si encuentra útil el artículo, y con gusto responderé cualquier pregunta en los comentarios.

Source: https://habr.com/ru/post/473562/


All Articles