Hashing vs. Criptografia: Como Sua Senha Está Sendo Armazenada no Servidor

Vamos supor que você criou uma conta no VerySecureWebsite.com. Você digita seu endereço de e-mail e senha e configura sua conta. Um pouco depois, você recebe um e-mail informando que, ironicamente, o site foi invadido, e os nomes de usuário e senhas de todos os usuários, que estavam armazenados em texto simples, agora estão à venda na dark web. Enquanto você começa a mudar a senha de todas as suas contas (você só usa uma, seu monstro), você se pergunta: “ Não é uma má ideia? Minha senha não deveria estar em algum tipo de código secreto para que os hackers não possam simplesmente lê-la?

Você está correto. Qualquer aplicativo web ou serviço que utiliza um sistema de login por nome de usuário/senha deve estar armazenando as senhas de seus usuários usando um hash salgado, possivelmente até mesmo um hash salgado lento, talvez com uma pimenta. Se isso está começando a parecer mais café da manhã do que criptografia, não se preocupe: ao contrário de sua senha (esperançosamente), o armazenamento seguro de senhas não é um tópico muito difícil de entender.

Leia também: Por que as Restrições de Senhas em Sites Não Mantêm Você Seguro

Texto simples e criptografia básica

password-storage-plaintext

Nome de usuárioSenha inseridaForma armazenada
UnwittingUserWeakPasswordWeakPassword

Armazenar senhas em texto simples em um banco de dados conectado à Internet é uma péssima ideia: se o banco de dados for invadido, qualquer pessoa que reutilizou uma dessas senhas estará em risco. E, no entanto, um número perturbador de sites ainda faz isso, provavelmente porque as atualizações de segurança são mais para o cliente do que para a empresa. Se você deseja testar se um site está fazendo isso, tente selecionar a opção “esqueci a senha”. Se eles apenas enviam sua senha em vez de um link de redefinição, ela está armazenada em texto simples.

Nome de usuárioSenha inseridaCriptografada com chave AES-128: WeakKey
UnwittingUserWeakPassword38MkoXVXoKe01uAOROBLpQ==

A criptografia pode parecer uma forma eficaz de armazenar senhas, mas é, na verdade, apenas um passo acima do texto simples. Uma senha criptografada geralmente pode ser decifrada com uma chave, e se os hackers puderem encontrá-la ou adivinhá-la, a criptografia é inútil.

Hashing > criptografia

password-storage-hashing

Nome de usuárioSenha inseridaString a ser hasheadaHasheada com SHA-256

| UnwittingUser | WeakPassword | WeakPassword | 252E2406732308F9A7
B378ED94E78467D14
077D19C8282443FCD
3D6190FCABFA |

Uma função de hash é basicamente apenas uma criptografia unidirecional: você converte a senha em texto simples para um código secreto, mas não há chave para convertê-la de volta, o que significa que você nunca pode derivar a senha real da versão hasheada.

É assim que a maioria dos sites seguros gerencia suas senhas:

  1. O usuário cria uma conta
  2. A senha do usuário é passada pela função de hash e armazenada no banco de dados
  3. Sempre que o usuário faz login, o banco de dados hashea a senha que ele inseriu e verifica se o hash inserido corresponde ao hash que eles têm registrado.
  4. Se sim, o usuário pode fazer login

Com um hash, o aplicativo/site nunca armazena sua senha real em lugar algum, e um hacker que conseguir invadir só obtém uma lista de letras e números que não podem ser decifrados. Dependendo de quão forte é o algoritmo, esses hashes podem ser bastante difíceis de quebrar.

No entanto, os hashes não são à prova de hackers. Tudo o que um atacante precisa fazer é passar um dicionário de senhas potenciais pela função de hash e, em seguida, comparar esses hashes com os hashes no banco de dados. Quando dois hashes correspondem, o hacker pode simplesmente olhar para qual senha gerou aquele hash.

Para economizar tempo e poder computacional, muitos atacantes simplesmente usam uma tabela de consulta (ou uma “tabela arco-íris”, uma versão que economiza espaço de tabelas de consulta), uma tabela pré-gerada cheia de senhas potenciais e seus hashes. Na verdade, você pode tentar hashear uma palavra em texto simples e então usar uma tabela de consulta no hash você mesmo; não é muito difícil. Essencialmente, se sua senha for de alguma forma comum, o hash dessa senha provavelmente já está em uma tabela de consulta. Essa é uma ótima razão para não usar senhas comuns.

Leia também: Crie uma Senha Forte Usando Estas Dicas e Ferramentas

Hashes com sal > hashes

password-storage-salt

| Nome de usuário | Senha inserida | String a ser hasheada | Hasheada com SHA-256,
sal = XcyKn42, prependido | | — | — | — | — | | UnwittingUser | WeakPassword | XcyKn42WeakPassword | 13EB660FF7FBD29A728FC5
92297D78DF19AFF8797363
15FBF1F1C4B7123BD10C |

Diferente de lesmas, o sal torna os hashes mais fortes. Como o hash inteiro muda mesmo que apenas uma letra da palavra em texto simples seja alterada, tudo o que um site precisa fazer para impedir tabelas de consulta é adicionar um pouco de texto simples à senha antes de ela ser hasheada. O atacante poderá ler o sal em texto simples, pois está armazenado no banco de dados, mas isso os obriga a recalcular todas as combinações possíveis de senhas potenciais e sais.

Claro que, hashes salgadas ainda podem ser quebradas. Hackers podem apenas adicionar o sal à senha que estão tentando adivinhar, hashear a combinação e esperar que correspondências apareçam – um ataque de dicionário padrão. Como as GPUs modernas podem fazer bilhões de palpites por segundo, isso não é de forma alguma inviável, mas torna o processo muito mais chato. Se isso falhar, ataques de força bruta são lentos, mas muito eficazes.

Tornando os hashes ainda mais fortes: outras táticas

password-storage-pepper

| Nome de usuário | Senha inserida | String a ser hasheada | Hasheada com Bcrypt,
sal = XcyKn42, prependido,
12 rodadas | | — | — | — | — | | UnwittingUser | WeakPassword | XcyKn42WeakPassword | $2y$12$6OleutQBO2iPoNvg
pyDndOU26Lqt9Y34f6PLEOx
mCELP5GoswrJT. |

Algoritmos de hashing lentos, como PBKDF2 ou bcrypt, usam uma técnica conhecida como “stretching de chave” para desacelerar ataques de dicionário e força bruta. Isso envolve basicamente configurar a função de hash para iterar um certo número de vezes (embora seja um pouco mais complexo do que simplesmente repetir a mesma coisa várias vezes), de modo que, para alcançar o hash correto, você tenha que usar muito poder computacional. Se um site estiver fazendo tudo isso, sua segurança é bastante boa.

| Nome de usuário | Senha inserida | String a ser hasheada | Hasheada com Bcrypt,
sal = XcyKn42, prependido,
12 rodadas,
pimenta = |4|\/|@p3pp3r, anexada | | — | — | — | — | | UnwittingUser | WeakPassword | XcyKn42WeakPassword|4|\/|@p3pp3r | $2y$12$njmWr5UMydCzdCE44ElW/
OIfYp2PH9sgonCATyVY.OVKSpmoSaZlu |

Para maior segurança, você também pode “pimentar” seus hashes – que, espera-se, já estão salgados. Uma pimenta, assim como um sal, é um conjunto de valores anexados à senha antes de ser hasheada. Diferente de um sal, no entanto, existe apenas um valor de pimenta, e ele é mantido em segredo, separado dos sais e hashes. Isso adiciona uma camada adicional de segurança ao hash salgado, mas se o atacante conseguir encontrá-la, não será mais muito útil, já que o atacante pode apenas usá-la para calcular novas tabelas de consulta.

Não faça uma bagunça do seu hash

A segurança das senhas fez grandes avanços – e assim também a arte de decifrar essa segurança. Infelizmente, os humanos ainda são ruins em gerenciamento de senhas, e os bancos de dados não atualizam a segurança tão frequentemente quanto deveriam. Em geral, assuma que sempre que você cria uma conta, a senha está sendo armazenada com segurança relativamente fraca. Se sua senha for comum ou uma palavra de dicionário, ela estará sob um risco bastante alto de ser quebrada. Faça suas senhas longas, misturando letras, números e símbolos, e você estará ajudando as funções de hash a fazerem seu melhor trabalho.