Gerando hash seguro de senha

Esta seção explica as razões por trás do uso de funções de hash para proteger senhas, bem como fazê-lo de forma eficaz.

Por que eu deveria gerar hash das senhas fornecidas pelos usuários da minha aplicação?

Gerar hash de senha é uma das considerações mais básicas de segurança que deve ser feita ao projetar qualquer aplicativo que aceita senhas dos usuários. Sem gerar hash, todas as senhas armazenadas em seu banco de dados da aplicação podem ser roubadas, e então imediatamente usada para comprometer não só a sua aplicação, mas também as contas de seus usuários em outros serviços, se eles não usarem senhas únicas.

Aplicando um algoritmo de hash para a senha de seus usuários antes de armazenar em seu banco de dados, dificulta um atacante determinar a senha original, enquanto ainda é possível de comparar o hash resultante para a senha original no futuro.

É importante observar, entretanto, que hash de senhas só protege de comprometer em seu armazenamento de dados, mas não necessariamente protege de serem interceptadas por um código malicioso injetado em sua própria aplicação.

Por que são comuns funções de hash tais como md5() e sha1() inadequados para senhas?

Algoritmos de hash como MD5, SHA1 e SHA256 são projetados para serem muito rápidos e eficientes. Com técnicas modernas e equipamento de informática, tornou-se trivial de "força bruta" a saída desses algoritmos, a fim de determinar a entrada original.

Por causa da rapidez com que um computador moderno pode "inverter" esses algoritmos de hash, muitos profissionais de segurança sugerem fortemente contra a sua utilização para hash da senha.

Como devo criptografar minhas senhas, se as funções hash comuns não são adequadas?

Quando gerar hash de senhas, as duas considerações mais importantes o custo do cálculo, e do salt. O algoritmo de hash computacionalmente mais caro, mais tempo vai demorar para a força bruta produzir um resultado.

O PHP fornece uma API de hash de senha nativo que lida de forma segura tanto gerando hash e verificando senhas de forma segura.

Outra opção é a função crypt(), que suporta vários algoritmos de hash. Quando utilizar esta função, você tem a garantia de que o algoritmo que você selecionou está disponível, como PHP contém implementações nativas de cada algoritmo suportado, no caso de um ou mais não são suportados pelo seu sistema.

O algoritmo sugerido para usar ao gerar hash de senhas é Blowfish, que também é o padrão usado pela API de hash da senha, pois é significativamente mais caro computacionalmente que MD5 ou SHA1, enquanto continua a ser escalável.

Note que se você estiver usando crypt() para verificar uma senha, você terá que tomar cuidado para evitar ataques de tempo usando uma string de comparação de tempo constante. Nem operadores == e === do PHP nem strcmp() realizam comparações de seqüências de tempo constante. Como password_verify() vai fazer isso por você, você será fortemente incentivado a usar a API de hash de senha nativa sempre que possível.

O que é um salt?

Um salt de criptografia são dados que são aplicado durante o processo de hash, a fim de eliminar a possibilidade da saída ser analisada se numa lista de pares pré-calculadas de hashes e sua entrada, conhecida como uma tabela rainbow.

Em termos mais simples, um salt é um pouco de informação adicional, que faz com que seus hashes sejam significativamente mais difíceis de decifrar. Há uma série de serviços on-line que fornecem listas extensas de hashes pré-calculado, bem como a entrada original para os hashes. O uso de um salt faz com que seja improvável ou impossível encontrar o hash resultante em uma dessas listas.

password_hash() será criado um salt aleatório se não for fornecido, e isso geralmente é a abordagem mais fácil e mais segura.

Como faço para armazenar meus salts?

Ao usar password_hash() ou crypt(), o valor de retorno inclui salt como parte do hash gerado. Este valor deve ser armazenado na íntegra no seu banco de dados, uma vez que inclui informações sobre a função hash que foi usado e pode, então, ser dada diretamente para password_verify() ou crypt() ao verificar senhas.

O diagrama a seguir mostra o formato de um valor de retorno de crypt() ou password_hash(). Como você pode ver, eles são auto-suficientes, com todas as informações sobre o algoritmo e salt necessário para futura verificação da senha.

 Os componentes do valor retornado pelo password_hash e crypt: em ordem, o algoritmo escolhido, as opções do algoritmo, o salt utilizado, e o hash da senha.
To Top