Tengo un APK de Android que se carga en archivos de contenido almacenados localmente protegidos por el cifrado AES, y quiero mantener en secreto la clave de cifrado de todos los usuarios. Solo la aplicación en sí debe poder leer la clave.
Mi pregunta es la siguiente: ¿cuál es la mejor práctica actual para evitar que todos los usuarios obtengan acceso a la clave de cifrado?
Opciones que he encontrado hasta ahora:
1) La clave de cifrado se almacena en el almacenamiento interno de la aplicación
2) La clave de cifrado está codificada de forma rígida en la aplicación en una forma muy confusa
3) La aplicación solicita la clave de cifrado a un servidor remoto que devuelve la clave de cifrado a través de SSL. La solicitud es autenticada por el servidor utilizando una clave de API que, a su vez, está codificada de forma rígida en el APK (también muy ofuscado).
Soy consciente de que el sistema operativo Android impide que las aplicaciones accedan a los datos de otras aplicaciones (cuando no están almacenadas en la tarjeta SD al menos), por lo que la clave podría almacenarse en el almacenamiento interno de la aplicación, pero no puedo confiar en esto porque los usuarios con teléfonos rooteados pueden simplemente leer todo. Así que la opción 1 está fuera.
Ninguna de las opciones restantes ofrece seguridad, solo oscuridad, y soy consciente de que codificar las claves secretas dentro de la APK es un poco de no-no.
La opción 2 al menos tiene la ventaja de ser mucho más sencilla de implementar.
La opción 3 ofrece el beneficio de la clave de cifrado que solo reside temporalmente en la memoria y nunca se almacena permanentemente en el dispositivo. Sin embargo, un atacante sin duda estaría buscando en el controlador de respuesta de la aplicación cualquier señal de la clave de cifrado. Hay eso, y la clave de la API está codificada en la aplicación, por lo que un atacante la puede descubrir.
¿Hay mejores opciones?
Editar: Con respecto al uso de claves derivadas de contraseñas: el contenido se cifra fuera de la aplicación (es decir, la aplicación nunca necesita cifrar, simplemente descifra) usando una clave predeterminada, por lo que usar una clave derivada de contraseña generada por la contraseña / PIN del usuario no funcionará como la clave resultante no coincidiría con la clave de cifrado. Además, la UX se vería afectada negativamente por este paso de contraseña adicional: queremos cargar y descifrar el contenido de forma silenciosa en segundo plano si es necesario.