Secure Storage es un conjunto de métodos y tecnologías para proteger datos confidenciales en un dispositivo: tokens, claves de encriptación, información de pago y datos personales de los usuarios. Según OWASP Mobile Top 10 (2024), el almacenamiento inseguro de datos se encuentra entre los tres riesgos más críticos. Una implementación adecuada de Secure Storage evita la filtración de datos incluso con acceso físico al dispositivo.
Puntos clave
Secure Storage es la práctica de almacenar datos confidenciales de una aplicación móvil de manera que sean inaccesibles para otras aplicaciones, malware y atacantes con acceso físico al dispositivo. A diferencia del almacenamiento normal, Secure Storage utiliza encriptación, aislamiento y protección por hardware.
No todos los datos requieren Secure Storage: las imágenes de perfil o la caché de noticias pueden almacenarse en el sistema de archivos normal. Sin embargo, las claves de encriptación, los tokens de autenticación, los datos de pago, las claves privadas y las plantillas biométricas deben estar protegidos. Según Google Security Blog (2025), el 67% de las vulnerabilidades en aplicaciones móviles están relacionadas con el almacenamiento de secretos en texto plano.
Cada plataforma móvil proporciona sus propios mecanismos de Secure Storage: Android — Keystore y EncryptedSharedPreferences, iOS — Keychain y Data Protection API. Estos mecanismos están integrados con módulos de seguridad de hardware (TEE, Secure Enclave) y garantizan que los datos no puedan leerse incluso tras hacer jailbreak o root al dispositivo.
La elección correcta del método de Secure Storage depende del tipo de datos, el escenario de uso y los requisitos de rendimiento. Comprender la arquitectura de cada mecanismo permite al desarrollador tomar la decisión arquitectónica correcta.
La plataforma Android proporciona varios niveles de protección de datos, desde el almacenamiento de claves por hardware hasta SharedPreferences encriptadas. La elección depende de la sensibilidad de los datos y los requisitos de rendimiento.
Android Keystore es un proveedor criptográfico que genera y almacena claves en un entorno de ejecución aislado (TEE — Trusted Execution Environment) en dispositivos con soporte de protección por hardware. Las claves nunca salen del TEE: las operaciones criptográficas se realizan dentro de un área protegida inaccesible incluso para el sistema operativo.
A partir de Android 9 (API 28), Keystore admite StrongBox Keymaster — un chip de seguridad dedicado con su propia CPU, generador de números aleatorios verdaderos (TRNG) y memoria protegida. StrongBox está certificado según Common Criteria EAL 4+ y es el nivel más alto de seguridad de almacenamiento de claves en Android. Para usar StrongBox, debes especificar explícitamente el flag inStrongBox() al generar una clave.
Keystore admite los algoritmos: AES/GCM/NoPadding (256 bits), EC (secp256r1, secp384r1), RSA (2048–4096 bits) y HMAC-SHA256. Todas las claves pueden vincularse a la autenticación biométrica mediante setUserAuthenticationRequired(true).
EncryptedSharedPreferences es una librería del paquete AndroidX Security que encripta automáticamente todos los datos guardados a través de la API SharedPreferences. Los valores se encriptan con una clave AES-256 GCM y las claves se encriptan con AES-256 SIV (IV sintético), lo que evita ataques de diccionario sobre los nombres de las claves.
La clave de encriptación principal se almacena en Android Keystore, proporcionando una protección de dos niveles: Keystore protege la clave maestra, EncryptedSharedPreferences protege los datos. El rendimiento de encriptación es inferior a 5 ms por operación de lectura/escritura para datos típicos (token, configuraciones), lo que hace que la librería sea adecuada para escenarios de usuario.
EncryptedSharedPreferences no está diseñada para grandes volúmenes de datos (más de 5 MB) — para ellos, usa una base de datos encriptada mediante SQLCipher o Room con encriptación.
SQLCipher es una extensión de SQLite que encripta toda la base de datos página por página usando AES-256-CBC. Cada página de la base de datos se encripta con una clave separada derivada de la contraseña maestra mediante PBKDF2. SQLCipher añade aproximadamente un 5–15% de sobrecarga de rendimiento dependiendo del tamaño de los datos.
La integración con Android se realiza a través de la librería net.zetetic:android-database-sqlcipher, que proporciona una API compatible con el SQLiteOpenHelper estándar. Se recomienda almacenar la contraseña de SQLCipher en Keystore, no en el código ni en SharedPreferences.
La plataforma iOS proporciona Keychain Services como almacenamiento seguro principal, así como la API Data Protection para encriptación de archivos a nivel de SO.
Keychain es una base de datos SQLite encriptada donde iOS almacena contraseñas, claves de encriptación, certificados y notas. Cada elemento de Keychain (SecItem) se almacena en forma encriptada usando una clave de hardware única del dispositivo. El acceso a un elemento se controla mediante una ACL (Access Control List), que puede requerir autenticación biométrica (Face ID, Touch ID) o un código de acceso.
Keychain admite clases de protección que determinan cuándo los datos son accesibles: kSecAttrAccessibleWhenUnlockedThisDeviceOnly — los datos son accesibles solo cuando el dispositivo está desbloqueado y no se transfieren durante la copia de seguridad. Esta clase se recomienda para la mayoría de escenarios de almacenamiento de tokens de autenticación.
En iOS 15+, el Security framework está disponible con soporte de claves por hardware a través de Secure Enclave — un procesador dedicado de Apple que maneja operaciones criptográficas y almacena claves privadas en memoria aislada. Secure Enclave admite los algoritmos ECDSA (secp256r1) y ECDH para generar claves que no pueden extraerse del chip.
Data Protection es un mecanismo de iOS que encripta cada archivo a nivel del sistema de archivos (APFS) usando una clave vinculada al código de acceso del dispositivo. El desarrollador especifica el nivel de protección mediante el atributo NSFileProtectionType al crear un archivo: NSFileProtectionComplete — el archivo es accesible solo cuando el dispositivo está desbloqueado.
Data Protection funciona automáticamente en todos los dispositivos con iOS 5+ si hay un código de acceso configurado. La encriptación se realiza a nivel de hardware mediante el Dedicated AES Engine del procesador Apple, lo que garantiza un alto rendimiento — la latencia de encriptación es prácticamente imperceptible para el usuario. Para activar la protección en una aplicación, basta con establecer el atributo de protección al crear un archivo mediante FileManager.
Data Protection no reemplaza a Keychain para almacenar claves — se usa para encriptar archivos, bases de datos de Core Data y otros grandes volúmenes de datos. La combinación de Keychain (para claves) y Data Protection (para archivos) proporciona un ciclo completo de almacenamiento seguro en iOS.
Veamos ejemplos prácticos de Secure Storage usando las API integradas de Android y iOS.
El ejemplo muestra la inicialización de EncryptedSharedPreferences con una clave maestra de Android Keystore. Todas las operaciones posteriores de lectura y escritura se encriptan y desencriptan automáticamente.
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val prefs = EncryptedSharedPreferences.create(
context,
"secure_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
prefs.edit()
.putString("auth_token", "eyJhbGciOiJIUzI1NiJ9...")
.apply()
El ejemplo demuestra cómo guardar y leer datos de iOS Keychain usando Security framework. El código utiliza kSecAttrAccessibleWhenUnlockedThisDeviceOnly para máxima protección.
import Security
func saveToKeychain(key: String, data: Data) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecValueData as String: data,
kSecAttrAccessible as String:
kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]
SecItemDelete(query as CFDictionary)
SecItemAdd(query as CFDictionary, nil)
}
func readFromKeychain(key: String) -> Data? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var result: AnyObject?
let status = SecItemCopyMatching(
query as CFDictionary, &result
)
return status == errSecSuccess ? result as? Data : nil
}
Un ejemplo de conexión a una base de datos SQLite encriptada mediante SQLCipher con una contraseña almacenada en Android Keystore.
import net.sqlcipher.database.SQLiteDatabase
import net.sqlcipher.database.SQLiteOpenHelper
class SecureDBHelper(context: Context) :
SQLiteOpenHelper(context, "secure.db", null, 1) {
private val password = getKeyFromKeystore()
override fun onCreate(db: SQLiteDatabase) {
db.execSQL("CREATE TABLE tokens (id INTEGER PRIMARY KEY, value TEXT)")
}
override fun onUpgrade(
db: SQLiteDatabase, oldVersion: Int, newVersion: Int
) {
onCreate(db)
}
}
// Uso: pasamos la contraseña al abrir
val helper = SecureDBHelper(context)
val db = helper.getWritableDatabase(password)
El uso adecuado de Secure Storage requiere seguir varios principios fundamentales que previenen errores comunes de los desarrolladores.
Define la clasificación de datos: qué datos requieren protección por hardware (Keystore / Secure Enclave), cuáles requieren encriptación a nivel de SO (EncryptedSharedPreferences / Data Protection) y cuáles pueden almacenarse en el sistema de archivos normal. Los tokens de autenticación, las claves privadas y los datos de pago — solo nivel de hardware. La configuración del usuario (tema, idioma) — EncryptedSharedPreferences es suficiente. Los datos de sesión (cachés temporales) pueden almacenarse en memoria o en un directorio temporal.
Nunca almacenes secretos en el código: las cadenas con claves de API, contraseñas o frases semilla en el código fuente son un gravísimo error de seguridad. Cualquier ingeniería inversa expondrá estos datos al instante. Usa Keystore para las claves y, para la configuración, carga desde el servidor al iniciar la aplicación (remote config).
Usa vinculación biométrica para operaciones críticas: Android Keystore e iOS Keychain admiten la vinculación de claves a la autenticación biométrica. Cada vez que se accede a una clave, el sistema solicita Face ID, Touch ID o la biometría de Android (BiometricPrompt). Esto garantiza que incluso con control total del dispositivo, un atacante no pueda usar los datos almacenados sin el propietario.
Prueba la seguridad: usa herramientas de análisis de seguridad — MobSF (Mobile Security Framework) para análisis estático, objection para pruebas en tiempo de ejecución y Frida para evitar la protección. Verifica que los datos sean inaccesibles tras hacer root o jailbreak. Android permite comprobar el acceso root mediante SafetyNet Attestation o Play Integrity API, iOS — mediante verificación de integridad de Secure Enclave.
Actualiza regularmente las librerías criptográficas: las vulnerabilidades en las librerías de encriptación se descubren regularmente. Monitorea los CVE de AndroidX Security, SQLCipher y los wrappers de Keychain. Implementa un sistema de notificaciones automáticas de nuevas versiones mediante Dependabot o Renovate.
Según Apple Security Research (2025), una implementación correcta de Secure Storage previene el 96% de los ataques dirigidos al robo de datos del dispositivo. El 4% restante son ataques con acceso físico y exploits de día cero, contra los cuales la vinculación biométrica es efectiva.
Preguntas frecuentes
iOS Keychain es una base de datos encriptada para almacenar contraseñas, claves y certificados con control de acceso mediante ACL. Android Keystore es un proveedor criptográfico que genera y almacena claves en un entorno aislado (TEE/StrongBox) y no permite extraer la clave privada.
EncryptedSharedPreferences usa AES-256 GCM para encriptar valores y AES-256 SIV para encriptar claves. La clave maestra se almacena en Android Keystore, proporcionando protección de dos niveles. Adicionalmente, se usa HMAC-SHA256 para verificar la integridad.
Sí, HTTPS protege los datos solo en el canal de transmisión. En el dispositivo, los datos se almacenan en texto plano tras el descifrado. Si un atacante obtiene acceso físico al dispositivo o instala malware, HTTPS no protegerá los datos almacenados. Encripta siempre los datos a nivel de almacenamiento.
Usa Android Keystore con el flag setUnlockedDeviceRequired(true), que bloquea el acceso a las claves en dispositivos rooteados. Adicionalmente, verifica la integridad mediante Play Integrity API y si se desvía de los valores de referencia, borra todos los secretos del almacenamiento.
No, UserDefaults almacena datos en texto plano en un archivo plist dentro del sandbox. Cualquier aplicación con herramientas de ingeniería inversa (mediante copia de seguridad o jailbreak) puede leer los tokens. Solo Keychain es el único lugar seguro para almacenar secretos en iOS.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también