Secure Storage é um conjunto de métodos e tecnologias para proteger dados confidenciais em um dispositivo: tokens, chaves de criptografia, informações de pagamento e dados pessoais dos usuários. De acordo com OWASP Mobile Top 10 (2024), o armazenamento inseguro de dados está entre os três riscos mais críticos. A implementação adequada do armazenamento seguro impede o vazamento de dados mesmo com acesso físico ao dispositivo.
Principais pontos
Secure Storage é a prática de armazenar dados confidenciais de aplicativos móveis de forma que fiquem inacessíveis para outros aplicativos, malware e invasores com acesso físico ao dispositivo. Ao contrário do armazenamento comum, o Secure Storage usa criptografia, isolamento e proteção por hardware.
Nem todos os dados precisam de Secure Storage: imagens de perfil ou cache de notícias podem ser armazenados no sistema de arquivos comum. No entanto, chaves de criptografia, tokens de autenticação, dados de pagamento, chaves privadas e modelos biométricos devem ser protegidos. De acordo com Google Security Blog (2025), 67% das vulnerabilidades em aplicativos móveis estão relacionadas ao armazenamento de segredos em texto simples.
Cada plataforma móvel fornece seus próprios mecanismos de Secure Storage: Android — Keystore e EncryptedSharedPreferences, iOS — Keychain e Data Protection API. Esses mecanismos são integrados com módulos de segurança de hardware (TEE, Secure Enclave) e garantem que os dados não possam ser lidos mesmo após jailbreak ou root do dispositivo.
A escolha correta do método de Secure Storage depende do tipo de dados, cenário de uso e requisitos de desempenho. Compreender a arquitetura de cada mecanismo permite ao desenvolvedor tomar a decisão arquitetônica correta.
A plataforma Android fornece vários níveis de proteção de dados, desde armazenamento de chaves por hardware até SharedPreferences criptografadas. A escolha depende da sensibilidade dos dados e requisitos de desempenho.
O Android Keystore é um provedor criptográfico que gera e armazena chaves em um ambiente de execução isolado (TEE — Trusted Execution Environment) em dispositivos com suporte a proteção por hardware. As chaves nunca saem do TEE: as operações criptográficas são executadas dentro de uma área protegida inacessível até mesmo para o sistema operacional.
A partir do Android 9 (API 28), o Keystore suporta StrongBox Keymaster — um chip de segurança dedicado com próprio CPU, Gerador de Números Aleatórios Verdadeiros (TRNG) e memória protegida. StrongBox é certificado conforme Common Criteria EAL 4+ e é o nível mais alto de segurança de armazenamento de chaves no Android. Para usar o StrongBox, você deve especificar explicitamente o sinalizador inStrongBox() ao gerar uma chave.
O Keystore suporta os algoritmos: AES/GCM/NoPadding (256 bits), EC (secp256r1, secp384r1), RSA (2048–4096 bits) e HMAC-SHA256. Todas as chaves podem ser vinculadas à autenticação biométrica através de setUserAuthenticationRequired(true).
EncryptedSharedPreferences é uma biblioteca do pacote AndroidX Security que criptografa automaticamente todos os dados salvos através da API SharedPreferences. Os valores são criptografados com uma chave AES-256 GCM e as chaves são criptografadas com AES-256 SIV (IV sintético), evitando ataques de dicionário nos nomes das chaves.
A chave de criptografia principal é armazenada no Android Keystore, fornecendo proteção de dois níveis: o Keystore protege a chave mestre, o EncryptedSharedPreferences protege os dados. O desempenho da criptografia é inferior a 5 ms por operação de leitura/escrita para dados típicos (token, configurações), tornando a biblioteca adequada para cenários de usuário.
EncryptedSharedPreferences não foi projetado para grandes volumes de dados (mais de 5 MB) — para esses, use um banco de dados criptografado através do SQLCipher ou Room com criptografia.
SQLCipher é uma extensão do SQLite que criptografa todo o banco de dados página por página usando AES-256-CBC. Cada página do banco de dados é criptografada com uma chave separada derivada da senha mestre através do PBKDF2. SQLCipher adiciona cerca de 5–15% de sobrecarga de desempenho dependendo do tamanho dos dados.
A integração com o Android é feita através da biblioteca net.zetetic:android-database-sqlcipher, que fornece uma API compatível com o SQLiteOpenHelper padrão. Recomenda-se armazenar a senha do SQLCipher no Keystore, não no código ou SharedPreferences.
A plataforma iOS fornece o Keychain Services como armazenamento seguro principal, além da API Data Protection para criptografia de arquivos em nível de SO.
Keychain é um banco de dados SQLite criptografado onde o iOS armazena senhas, chaves de criptografia, certificados e notas. Cada item do Keychain (SecItem) é armazenado de forma criptografada usando uma chave de hardware única do dispositivo. O acesso a um item é controlado através de uma ACL (Access Control List), que pode exigir autenticação biométrica (Face ID, Touch ID) ou código de acesso.
O Keychain suporta classes de proteção que determinam quando os dados estão acessíveis: kSecAttrAccessibleWhenUnlockedThisDeviceOnly — os dados estão acessíveis apenas quando o dispositivo está desbloqueado e não são transferidos durante o backup. Esta classe é recomendada para a maioria dos cenários de armazenamento de tokens de autenticação.
No iOS 15+, o Security framework está disponível com suporte a chaves de hardware através do Secure Enclave — um processador dedicado da Apple que lida com operações criptográficas e armazena chaves privadas em memória isolada. O Secure Enclave suporta os algoritmos ECDSA (secp256r1) e ECDH para gerar chaves que não podem ser extraídas do chip.
Data Protection é um mecanismo do iOS que criptografa cada arquivo no nível do sistema de arquivos (APFS) usando uma chave vinculada ao código de acesso do dispositivo. O desenvolvedor especifica o nível de proteção através do atributo NSFileProtectionType ao criar um arquivo: NSFileProtectionComplete — o arquivo está acessível apenas quando o dispositivo está desbloqueado.
Data Protection funciona automaticamente em todos os dispositivos com iOS 5+ se um código de acesso estiver configurado. A criptografia é realizada em nível de hardware através do Dedicated AES Engine do processador Apple, garantindo alto desempenho — a latência da criptografia é praticamente imperceptível para o usuário. Para ativar a proteção em um aplicativo, basta definir o atributo de proteção ao criar um arquivo através do FileManager.
Data Protection não substitui o Keychain para armazenar chaves — é usado para criptografar arquivos, bancos de dados Core Data e outros grandes volumes de dados. A combinação de Keychain (para chaves) e Data Protection (para arquivos) fornece um ciclo completo de armazenamento seguro no iOS.
Vamos ver exemplos práticos de Secure Storage usando as APIs integradas do Android e iOS.
O exemplo mostra a inicialização do EncryptedSharedPreferences com uma chave mestre do Android Keystore. Todas as operações subsequentes de leitura e escrita são automaticamente criptografadas e descriptografadas.
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()
O exemplo demonstra como salvar e ler dados do iOS Keychain usando o Security framework. O código usa kSecAttrAccessibleWhenUnlockedThisDeviceOnly para máxima proteção.
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
}
Um exemplo de conexão a um banco de dados SQLite criptografado via SQLCipher com uma senha armazenada no 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: passamos a senha ao abrir
val helper = SecureDBHelper(context)
val db = helper.getWritableDatabase(password)
O uso adequado do Secure Storage requer seguir vários princípios fundamentais que previnem erros comuns de desenvolvedores.
Defina a classificação dos dados: quais dados exigem proteção por hardware (Keystore / Secure Enclave), quais exigem criptografia em nível de SO (EncryptedSharedPreferences / Data Protection) e quais podem ser armazenados no sistema de arquivos comum. Tokens de autenticação, chaves privadas e dados de pagamento — apenas nível de hardware. Configurações do usuário (tema, idioma) — EncryptedSharedPreferences é suficiente. Dados de sessão (caches temporários) podem ser armazenados em memória ou diretório temporário.
Nunca armazene segredos no código: strings com chaves de API, senhas ou frases-semente no código fonte é um erro gravíssimo de segurança. Qualquer engenharia reversa exporá esses dados instantaneamente. Use o Keystore para chaves e, para configuração — carregamento do servidor na inicialização do aplicativo (config remota).
Use vinculação biométrica para operações críticas: o Android Keystore e o iOS Keychain suportam a vinculação de chaves à autenticação biométrica. Cada vez que uma chave é acessada, o sistema solicita Face ID, Touch ID ou a biometria do Android (BiometricPrompt). Isso garante que mesmo com controle total do dispositivo, um invasor não possa usar os dados armazenados sem o proprietário.
Teste a segurança: use ferramentas de análise de segurança — MobSF (Mobile Security Framework) para análise estática, objection para testes em tempo de execução e Frida para bypass de proteção. Verifique se os dados estão inacessíveis após root ou jailbreak. Android permite verificar o acesso root através do SafetyNet Attestation ou Play Integrity API, iOS — através da verificação de integridade do Secure Enclave.
Atualize regularmente as bibliotecas criptográficas: vulnerabilidades em bibliotecas de criptografia são descobertas regularmente. Monitore CVEs para AndroidX Security, SQLCipher e wrappers do Keychain. Implemente um sistema de notificação automática de novas versões via Dependabot ou Renovate.
De acordo com Apple Security Research (2025), a implementação correta do Secure Storage previne 96% dos ataques direcionados ao roubo de dados do dispositivo. Os 4% restantes são ataques com acesso físico e exploits de dia zero, contra os quais a vinculação biométrica é eficaz.
Perguntas frequentes
iOS Keychain é um banco de dados criptografado para armazenar senhas, chaves e certificados com controle de acesso via ACL. Android Keystore é um provedor criptográfico que gera e armazena chaves em ambiente isolado (TEE/StrongBox) e não permite extrair a chave privada.
EncryptedSharedPreferences usa AES-256 GCM para criptografar valores e AES-256 SIV para criptografar chaves. A chave mestre é armazenada no Android Keystore, fornecendo proteção de dois níveis. Além disso, HMAC-SHA256 é usado para verificação de integridade.
Sim, HTTPS protege os dados apenas no canal de transmissão. No dispositivo, os dados são armazenados em texto simples após a descriptografia. Se um invasor obtiver acesso físico ao dispositivo ou instalar malware, o HTTPS não protegerá os dados armazenados. Sempre criptografe os dados em nível de armazenamento.
Use o Android Keystore com o sinalizador setUnlockedDeviceRequired(true), que bloqueia o acesso às chaves em dispositivos com root. Além disso, verifique a integridade através da Play Integrity API e se desviar dos valores de referência, limpe todos os segredos do armazenamento.
Não, UserDefaults armazena dados em texto simples em um arquivo plist dentro da sandbox. Qualquer aplicativo com ferramentas de engenharia reversa (via backup ou jailbreak) pode ler os tokens. Apenas o Keychain é o único local seguro para armazenar segredos no iOS.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também