Introdução
A Lei Geral de Proteção de Dados (Lei nº 13.709/2018), em vigor desde setembro de 2020, estabelece um marco regulatório abrangente para o tratamento de dados pessoais no Brasil. Para desenvolvedores de aplicativos móveis, a conformidade com a LGPD não é apenas uma obrigação legal — é um diferencial competitivo em um mercado cada vez mais consciente sobre privacidade.
Este guia técnico aborda os aspectos práticos da implementação de controles de segurança exigidos pela LGPD em aplicativos Android e iOS, com foco especial nos Artigos 46 a 49 que tratam das medidas de segurança.
Fundamentos Legais
Quem Precisa se Adequar?
A LGPD aplica-se a qualquer operação de tratamento de dados pessoais realizada no território brasileiro, independentemente de onde a empresa esteja sediada. Isso inclui:
- Aplicativos que coletam dados de usuários brasileiros
- Empresas que oferecem serviços no Brasil
- Operações que visam oferecer bens ou serviços a indivíduos localizados no Brasil
| Elemento | Descrição | Exemplo em Apps | |----------|-----------|-----------------| | Dado Pessoal | Informação relacionada a pessoa identificada ou identificável | CPF, e-mail, localização GPS | | Dado Sensível | Dados sobre origem racial, convicção religiosa, saúde, biometria | Dados biométricos de autenticação | | Titular | Pessoa natural a quem os dados se referem | Usuário do aplicativo | | Controlador | Quem toma decisões sobre o tratamento | Desenvolvedor/empresa do app | | Operador | Quem realiza tratamento em nome do controlador | Provedor de cloud, SDK de analytics |
Bases Legais para Tratamento
Para tratar dados pessoais em seu aplicativo, você precisa fundamentar cada operação em uma das bases legais previstas no Art. 7º:
- Consentimento: Manifestação livre, informada e inequívoca do titular
- Execução de contrato: Necessário para prestação do serviço
- Legítimo interesse: Quando atende interesses legítimos do controlador
- Proteção do crédito: Para apps financeiros e de pagamentos
Requisitos Técnicos de Segurança
Art. 46 - Medidas de Segurança
O Artigo 46 da LGPD estabelece que agentes de tratamento devem adotar medidas de segurança técnicas e administrativas aptas a proteger os dados pessoais. Veja como implementar:
Criptografia em Repouso (Data at Rest)
Para dados armazenados localmente no dispositivo, utilize criptografia AES-256:
// Android: Criptografia usando EncryptedSharedPreferences
class ArmazenamentoSeguro(private val context: Context) {
private val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
private val prefsSeguras = EncryptedSharedPreferences.create(
context,
"dados_usuario_lgpd",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
fun salvarDadoPessoal(chave: String, valor: String) {
prefsSeguras.edit().putString(chave, valor).apply()
}
fun obterDadoPessoal(chave: String): String? {
return prefsSeguras.getString(chave, null)
}
fun removerDadoPessoal(chave: String) {
prefsSeguras.edit().remove(chave).apply()
}
}
// iOS: Armazenamento seguro com Keychain
class ArmazenamentoSeguro {
private let serviceName = "com.seuapp.dadospessoais"
func salvar(dado: String, paraChave chave: String) throws {
guard let dadosBytes = dado.data(using: .utf8) else {
throw ErroArmazenamento.conversaoFalhou
}
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: serviceName,
kSecAttrAccount as String: chave,
kSecValueData as String: dadosBytes,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]
// Remove entrada existente se houver
SecItemDelete(query as CFDictionary)
let status = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else {
throw ErroArmazenamento.falhaAoSalvar(status)
}
}
func recuperar(chave: String) throws -> String? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: serviceName,
kSecAttrAccount as String: chave,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var resultado: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &resultado)
guard status == errSecSuccess,
let dados = resultado as? Data,
let valor = String(data: dados, encoding: .utf8) else {
return nil
}
return valor
}
}
Criptografia em Trânsito (Data in Transit)
A LGPD exige proteção de dados durante a transmissão. Implemente TLS 1.2+ com certificate pinning:
// Android: Configuração de segurança de rede
// res/xml/network_security_config.xml
/*
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
<domain-config>
<domain includeSubdomains="true">api.seuapp.com.br</domain>
<pin-set expiration="2026-12-31">
<pin digest="SHA-256">SEU_HASH_BASE64_AQUI=</pin>
<pin digest="SHA-256">HASH_BACKUP_AQUI=</pin>
</pin-set>
</domain-config>
</network-security-config>
*/
// Configuração do OkHttp com certificate pinning
val certificatePinner = CertificatePinner.Builder()
.add("api.seuapp.com.br", "sha256/SEU_HASH_BASE64_AQUI=")
.add("api.seuapp.com.br", "sha256/HASH_BACKUP_AQUI=")
.build()
val clienteHttp = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.connectTimeout(30, TimeUnit.SECONDS)
.build()
Art. 46, §2º - Privacidade desde a Concepção
O conceito de Privacy by Design deve ser incorporado desde o início do desenvolvimento:
Minimização de Dados
Colete apenas o estritamente necessário:
// INCORRETO - Coleta excessiva
data class UsuarioExcessivo(
val nome: String,
val cpf: String,
val endereco: String,
val telefone: String,
val dataNascimento: String,
val nomeMae: String, // Necessário?
val rendaMensal: String, // Necessário?
val estadoCivil: String // Necessário?
)
// CORRETO - Apenas dados necessários para o serviço
data class UsuarioMinimo(
val nome: String,
val email: String,
val telefone: String? // Opcional, se realmente usado
)
Validação de Entrada
Implemente validação robusta para prevenir injeções e garantir integridade:
// iOS: Validação de dados de entrada
struct ValidadorDados {
static func validarCPF(_ cpf: String) -> Bool {
let numeros = cpf.replacingOccurrences(
of: "[^0-9]",
with: "",
options: .regularExpression
)
guard numeros.count == 11 else { return false }
// Verifica se não são todos iguais
let conjunto = Set(numeros)
guard conjunto.count > 1 else { return false }
// Validação dos dígitos verificadores
let digitos = numeros.compactMap { Int(String($0)) }
func calcularDigito(base: [Int], pesos: [Int]) -> Int {
let soma = zip(base, pesos).map { $0 * $1 }.reduce(0, +)
let resto = soma % 11
return resto < 2 ? 0 : 11 - resto
}
let primeiroDigito = calcularDigito(
base: Array(digitos[0..<9]),
pesos: [10, 9, 8, 7, 6, 5, 4, 3, 2]
)
let segundoDigito = calcularDigito(
base: Array(digitos[0..<9]) + [primeiroDigito],
pesos: [11, 10, 9, 8, 7, 6, 5, 4, 3, 2]
)
return digitos[9] == primeiroDigito && digitos[10] == segundoDigito
}
static func sanitizarEntrada(_ texto: String) -> String {
// Remove caracteres potencialmente perigosos
let caracteresProibidos = CharacterSet(charactersIn: "<>"';&")
return texto.components(separatedBy: caracteresProibidos).joined()
}
}
Art. 48 - Comunicação de Incidentes
A LGPD exige comunicação de incidentes de segurança à ANPD e aos titulares em prazo razoável. Implemente detecção e logging:
// Sistema de detecção e logging de incidentes
data class IncidenteSeguranca(
val id: String = UUID.randomUUID().toString(),
val timestamp: Long = System.currentTimeMillis(),
val tipo: TipoIncidente,
val severidade: Severidade,
val descricao: String,
val dadosAfetados: List<String>,
val titularesAfetados: Int?,
val acaoTomada: String?
)
enum class TipoIncidente {
ACESSO_NAO_AUTORIZADO,
VAZAMENTO_DADOS,
PERDA_DADOS,
ALTERACAO_INDEVIDA,
TENTATIVA_INTRUSAO,
DISPOSITIVO_COMPROMETIDO
}
enum class Severidade {
BAIXA,
MEDIA,
ALTA,
CRITICA
}
class GestorIncidentes(private val context: Context) {
private val TAG = "IncidentesLGPD"
fun registrarIncidente(incidente: IncidenteSeguranca) {
// Log local seguro
Log.e(TAG, "Incidente detectado: ${incidente.tipo}")
// Enviar para backend (se conectado)
enviarParaBackend(incidente)
// Notificar equipe de segurança
if (incidente.severidade == Severidade.CRITICA ||
incidente.severidade == Severidade.ALTA) {
notificarEquipeSeguranca(incidente)
}
}
fun detectarDispositivoComprometido(): Boolean {
return verificarRoot() || verificarEmulador() || verificarDebugger()
}
private fun verificarRoot(): Boolean {
val indicadoresRoot = listOf(
"/system/app/Superuser.apk",
"/system/xbin/su",
"/system/bin/su",
"/data/local/xbin/su",
"/data/local/bin/su"
)
return indicadoresRoot.any { File(it).exists() }
}
private fun verificarEmulador(): Boolean {
return (Build.FINGERPRINT.contains("generic") ||
Build.MODEL.contains("Emulator") ||
Build.MANUFACTURER.contains("Genymotion"))
}
private fun verificarDebugger(): Boolean {
return Debug.isDebuggerConnected()
}
}
Art. 49 - Padrões de Boas Práticas
A LGPD menciona a adoção de padrões de boas práticas e governança. Para aplicativos móveis, isso inclui:
Controle de Acesso Baseado em Funções (RBAC)
// Implementação de controle de acesso
enum class NivelAcesso {
TITULAR, // Acesso apenas aos próprios dados
ATENDENTE, // Acesso a dados de clientes atendidos
SUPERVISOR, // Acesso a relatórios agregados
ADMINISTRADOR // Acesso total (com auditoria)
}
class ControleAcesso(private val usuarioAtual: Usuario) {
fun podeAcessarDados(titularId: String, operacao: Operacao): Boolean {
return when (usuarioAtual.nivelAcesso) {
NivelAcesso.TITULAR -> usuarioAtual.id == titularId
NivelAcesso.ATENDENTE -> verificarRelacionamento(titularId)
NivelAcesso.SUPERVISOR -> operacao == Operacao.LEITURA
NivelAcesso.ADMINISTRADOR -> {
registrarAcessoAdministrativo(titularId, operacao)
true
}
}
}
private fun registrarAcessoAdministrativo(titularId: String, operacao: Operacao) {
val auditoria = RegistroAuditoria(
timestamp = System.currentTimeMillis(),
usuarioId = usuarioAtual.id,
titularId = titularId,
operacao = operacao,
justificativa = "Acesso administrativo"
)
LogAuditoria.registrar(auditoria)
}
}
Timeout de Sessão
// iOS: Gerenciamento seguro de sessão
class GerenciadorSessao {
private let tempoLimiteInatividade: TimeInterval = 300 // 5 minutos
private var ultimaAtividade: Date = Date()
private var timerVerificacao: Timer?
func iniciarMonitoramento() {
timerVerificacao = Timer.scheduledTimer(
withTimeInterval: 30,
repeats: true
) { [weak self] _ in
self?.verificarSessao()
}
}
func registrarAtividade() {
ultimaAtividade = Date()
}
private func verificarSessao() {
let tempoInativo = Date().timeIntervalSince(ultimaAtividade)
if tempoInativo > tempoLimiteInatividade {
encerrarSessao()
}
}
private func encerrarSessao() {
// Limpar dados sensíveis da memória
limparDadosSensiveis()
// Invalidar tokens
TokenManager.shared.invalidar()
// Redirecionar para tela de login
NotificationCenter.default.post(
name: .sessaoExpirada,
object: nil
)
}
private func limparDadosSensiveis() {
// Sobrescrever variáveis com dados sensíveis
// antes de liberar memória
}
}
Direitos dos Titulares
O Art. 18 da LGPD garante direitos aos titulares que seu aplicativo deve suportar:
Implementação do Direito de Acesso (Art. 18, II)
// Endpoint para exportação de dados do titular
class ExportadorDados(private val repositorio: RepositorioDados) {
fun exportarDadosTitular(titularId: String): RelatorioExportacao {
val dadosPessoais = repositorio.obterTodosDados(titularId)
val historico = repositorio.obterHistoricoTratamento(titularId)
val consentimentos = repositorio.obterConsentimentos(titularId)
return RelatorioExportacao(
titular = titularId,
dataGeracao = LocalDateTime.now(),
dadosPessoais = dadosPessoais.map { mascarar(it) },
categoriasColetadas = extrairCategorias(dadosPessoais),
finalidades = extrairFinalidades(historico),
compartilhamentos = obterCompartilhamentos(titularId),
retencao = obterPoliticaRetencao(),
consentimentos = consentimentos
)
}
private fun mascarar(dado: DadoPessoal): DadoPessoalMascarado {
// Mascara dados sensíveis mesmo na exportação
return when (dado.tipo) {
TipoDado.CPF -> dado.copy(valor = "${dado.valor.take(3)}.***.***-${dado.valor.takeLast(2)}")
TipoDado.CARTAO -> dado.copy(valor = "**** **** **** ${dado.valor.takeLast(4)}")
else -> dado.toMascarado()
}
}
}
Direito à Eliminação (Art. 18, VI)
// iOS: Implementação do direito à eliminação
class GestorEliminacao {
func solicitarEliminacao(titularId: String, motivo: String) async throws {
// 1. Verificar identidade do titular
guard await verificarIdentidade(titularId) else {
throw ErroLGPD.identidadeNaoConfirmada
}
// 2. Verificar se há base legal que exija retenção
let obrigacoesRetencao = await verificarObrigacoesRetencao(titularId)
if !obrigacoesRetencao.isEmpty {
throw ErroLGPD.retencaoObrigatoria(obrigacoesRetencao)
}
// 3. Executar eliminação segura
try await executarEliminacao(titularId)
// 4. Propagar para operadores
try await notificarOperadores(titularId)
// 5. Registrar para auditoria
registrarEliminacao(titularId: titularId, motivo: motivo)
}
private func executarEliminacao(_ titularId: String) async throws {
// Eliminação segura com sobrescrita
let arquivos = try await listarArquivosDoTitular(titularId)
for arquivo in arquivos {
try eliminarComSobrescrita(arquivo)
}
// Limpar de bancos de dados
try await limparBancoDados(titularId)
// Limpar de caches
limparCaches(titularId)
}
private func eliminarComSobrescrita(_ url: URL) throws {
let tamanho = try FileManager.default
.attributesOfItem(atPath: url.path)[.size] as! UInt64
// Sobrescrever 3 vezes com dados aleatórios
for _ in 0..<3 {
let dados = Data((0..<tamanho).map { _ in UInt8.random(in: 0...255) })
try dados.write(to: url)
}
try FileManager.default.removeItem(at: url)
}
}
Fiscalização da ANPD
A Autoridade Nacional de Proteção de Dados tem intensificado a fiscalização. Em 2024, a ANPD aplicou sanções superiores a R$ 50 milhões em multas.
Casos Recentes de Sanções
| Data | Empresa | Multa | Motivo | |------|---------|-------|--------| | Nov/2024 | Operadora de Telecom | R$ 14,4 milhões | Medidas de segurança inadequadas | | Out/2024 | Plataforma de E-commerce | R$ 7,2 milhões | Ausência de criptografia | | Set/2024 | App de Saúde | R$ 3,5 milhões | Vazamento via vulnerabilidade de API | | Ago/2024 | Fintech | R$ 9,8 milhões | Atraso na notificação de incidente |
O Que a ANPD Verifica
Durante fiscalizações, a ANPD costuma solicitar:
- Mapeamento de dados pessoais tratados
- Registro das operações de tratamento (Art. 37)
- Relatório de Impacto à Proteção de Dados (RIPD) quando aplicável
- Evidências de medidas de segurança implementadas
- Política de privacidade e termos de uso
- Registro de consentimentos obtidos
- Procedimentos de resposta a incidentes
Checklist de Conformidade para Apps Móveis
Controles Técnicos
- [ ] Criptografia AES-256 para dados em repouso
- [ ] TLS 1.2+ para todas as comunicações
- [ ] Certificate pinning implementado
- [ ] Armazenamento seguro (Keychain/Keystore)
- [ ] Detecção de root/jailbreak
- [ ] Timeout de sessão configurado
- [ ] Logs não contêm dados pessoais
- [ ] Dados sensíveis não em backups
- [ ] Ofuscação de código aplicada
- [ ] Validação de entrada implementada
Controles de Privacidade
- [ ] Coleta minimizada ao necessário
- [ ] Consentimento obtido de forma clara
- [ ] Política de privacidade acessível
- [ ] Mecanismo de revogação de consentimento
- [ ] Exportação de dados do titular
- [ ] Mecanismo de eliminação de dados
- [ ] Notificação de alterações de política
Documentação
- [ ] Registro de atividades de tratamento
- [ ] Mapeamento de fluxo de dados
- [ ] Relatório de Impacto (se aplicável)
- [ ] Procedimento de resposta a incidentes
- [ ] Contratos com operadores atualizados
Conclusão
A conformidade com a LGPD para aplicativos móveis requer uma abordagem holística que combine controles técnicos robustos, processos bem definidos e documentação adequada. Os requisitos de segurança dos Artigos 46 a 49 não são meras formalidades — são a espinha dorsal da proteção de dados pessoais dos seus usuários.
Pontos-chave a lembrar:
- A criptografia é essencial tanto em repouso quanto em trânsito
- Privacy by Design deve guiar todo o desenvolvimento
- Documentação é prova de conformidade
- Preparação para incidentes é obrigatória
- Direitos dos titulares devem ser tecnicamente suportados
A ANPD está cada vez mais ativa na fiscalização, e as multas são significativas. Mais importante ainda: a confiança dos usuários brasileiros em seu aplicativo depende da demonstração de compromisso real com a proteção de seus dados.
Verifique a conformidade do seu aplicativo com a LGPD. Inicie uma varredura agora.