O que faz uma forma de armazenamento recuperável
Quatro formatos de armazenamento, classificados por recuperabilidade:
| Formato | Recuperável? | Exemplo | Método de Recuperação |
|--------|-------------|---------|---------------------|
| Texto claro | Sim | password: hunter2 | Ler o arquivo |
| Base64 | Sim | cGFzc3dvcmQ= | base64 --decode |
| Cifra reversível (AES) | Sim | ENC[AES256:...] | Descriptografar com a chave |
| Hash de uma única direção (bcrypt) | Não | $2b$12$... | Não pode ser revertido; deve ser forçado a brute-force |
Texto claro, base64 e cifra reversível: todos recuperáveis. Um único dump de banco de dados de credenciais fornece um atacante todas as senhas em texto claro, para todos os usuários, ao mesmo tempo. Uma invasão; exposição total.
O Exemplo do Mailman 2.x
Mailman 2.x (gerenciador de lista de correio GNU): armazenava senhas de assinante em texto claro. E-mail de lembrete de senha mensal: enviava todas as senhas dos assinantes em texto claro. Dois defeitos separados, ambos MOAD-0006:
1. Armazenamento: texto claro no banco de dados da lista. Uma comprometimento do servidor expõe todas as senhas dos assinantes.
2. Transmissão: envio mensal do e-mail envia a senha em texto claro para o servidor de e-mail do assinante via SMTP. O e-mail viaja em texto claro em vários saltos SMTP.
O time do Mailman projetou ambos os comportamentos. Recuperação foi o recurso: os assinantes poderiam recuperar senhas esquecidas. O nome Seguro de Vidro vem disso: o seguro armazena credenciais em forma visível. Quem chegar ao seguro pode ler todos os conteúdos ao mesmo tempo.
O Princípio Já Furtado
Uma credencial armazenada em forma recuperável é uma credencial já furtada. O atacante ainda não chegou. A invasão ainda não aconteceu. Mas a arquitetura garante: quando uma invasão ocorre, todas as credenciais caem ao mesmo tempo. Nenhuma invasão ocorre isoladamente; todas as credenciais em armazenamento recuperável passam para o atacante na mesma operação.
MOAD-0006 vs MOAD-0004
MOAD-0004 (Segredo Logado): credenciais escritas em logs por acidente. A escrita do log não era a intenção; era um efeito colateral da habilitação de log de cabeçalho para depuração.
MOAD-0006 (Seguro de Vidro): credenciais armazenadas em forma recuperável pelo design. Recuperação foi a intenção. O recurso de lembrete de senha exigia armazenar a senha. O recurso de exibição da senha exigia armazená-la. O compromisso arquitetônico com a recuperação criou o defeito.
Distinção em uma linha: MOAD-0004 coloca credenciais em logs por acidente; MOAD-0006 armazena credenciais em forma recuperável propositalmente. As correções operam em camadas diferentes.
Estrutural vs Acidental
A distinção arquitetural entre MOAD-0006 & MOAD-0004 determina a estratégia de correção. Uma escrita acidental para logs: corrija a camada de serialização. Um armazenamento projetado para recuperação: redesenhe a feature que exigia recuperação.
Por que o bcrypt Funciona
Uma função de hash de uma maneira aceita uma senha e produz um digest de comprimento fixo. Dado o digest, a senha original não pode ser recuperada. Não 'difícil de recuperar': impossível de inverter. A função funciona apenas em uma direção.
Três propriedades necessárias para o armazenamento de credenciais:
1. Uma maneira (resistência a pré-imagem). Dado hash(senha), nenhum algoritmo recupera senha mais rápido do que brute-force. bcrypt, scrypt e argon2 satisfazem essa propriedade.
2. Sal. Um valor aleatório anexado à senha antes do hash. A mesma senha, sal diferente, hash diferente. Propósito: derrotar tabelas-arco-íris (dicionários de hashes pré-computados). Sem sal: um atacante calcula hash('password123') uma vez e verifica todos os 1 milhão de usuários ao mesmo tempo. Com sal: cada usuário tem um hash único mesmo com a mesma senha.
3. Lento por design. bcrypt aceita um fator de trabalho. Fator de trabalho maior: mais iterações, mais tempo de computação por tentativa de hash. Login: 300ms para hashar uma vez. Aceitável. Força-bruta: 300ms por tentativa. Em 1 bilhão de tentativas: 9,5 anos por senha. Inaceitável para um atacante. A lentidão: uma característica, não um defeito.
import bcrypt
# Armazenamento: hash unidirecional com sal
def store_password(plaintext: str) -> bytes:
return bcrypt.hashpw(plaintext.encode(), bcrypt.gensalt(rounds=12))
# Verificação: hash o candidato e compare os digestos
def verify_password(plaintext: str, stored_hash: bytes) -> bool:
return bcrypt.checkpw(plaintext.encode(), stored_hash)
# NUNCA armazenado: a senha em texto claro
# NUNCA recuperado: o texto claro do hash
# Recuperação de senha, não lembrete de senha
O Compromisso
A hash unidirecional torna a recuperação de senha impossível. Um usuário que esquece sua senha não pode recebá-la de volta. Um e-mail de lembrete de senha não pode existir. A experiência do usuário muda: 'esqueceu sua senha? redefina-a.' Não é uma degradação: uma barreira de segurança. O sistema que não pode recuperar uma senha não pode vazá-la.
Uma violação de banco de dados que expõe hashes bcrypt: todos os hashes visíveis, nenhum senha visível. Um atacante deve forçar a brute-force de cada hash individualmente, a 300ms por tentativa, com sal por usuário derrotando tabelas pré-calculadas. Uma violação que expõe senhas em texto claro: exposição total e imediata.
Criptografia Forte Não É O suficiente
Uma auditoria de segurança identifica um sistema de armazenamento de credenciais. As senhas são armazenadas usando a encriptação AES-256-CBC com uma chave do lado do servidor. O relatório de auditoria o marca como um defeito Glass Safe.
A equipe de engenharia responde: 'AES-256 é o símptro cifra simétrica disponível. A chave vive em um módulo de segurança de hardware. Nenhum atacante pode descriptografar essas senhas.'