Hashing de senhas
Para garantir a segurança de nossos usuários, não armazenamos suas senhas em formato legível, mas armazenamos apenas uma impressão digital (o chamado hash). A partir da impressão digital, não é possível reconstruir a forma original da senha. É importante usar um algoritmo seguro para criar a impressão digital. A classe Nette\Security\Passwords nos ajuda com isso.
O framework adiciona automaticamente ao contêiner DI um serviço do tipo Nette\Security\Passwords com o nome security.passwords, ao qual você pode acessar solicitando-o através de injeção de dependência.
use Nette\Security\Passwords; class Foo { public function __construct( private Passwords $passwords, ) { } } __construct ($algo=PASSWORD_DEFAULT, array $options=[]): string
Escolhemos qual algoritmo seguro usar para gerar o hash e configuramos seus parâmetros.
Por padrão, usa-se PASSWORD_DEFAULT, ou seja, a escolha do algoritmo é deixada para o PHP. O algoritmo pode mudar em versões mais recentes do PHP, se algoritmos de hashing mais novos e mais fortes aparecerem. Portanto, você deve estar ciente de que o comprimento do hash resultante pode mudar, e você deve armazená-lo de forma que possa acomodar caracteres suficientes, 255 é a largura recomendada.
Exemplo de configuração da velocidade de hashing com o algoritmo bcrypt alterando o parâmetro cost: (em 2020, o padrão é 10, o hashing da senha leva cerca de 80ms, para cost 11 é cerca de 160ms, para cost 12 cerca de 320ms, quanto mais lento, melhor a proteção, sendo que a velocidade 10–12 já é considerada proteção suficiente)
// vamos hashear as senhas com 2^12 (2^cost) iterações do algoritmo bcrypt $passwords = new Passwords(PASSWORD_BCRYPT, ['cost' => 12]); Usando injeção de dependência:
services: security.passwords: Nette\Security\Passwords(::PASSWORD_BCRYPT, [cost: 12]) hash (string $password): string
Gera o hash da senha.
$res = $passwords->hash($password); // Gera o hash da senha O resultado $res é uma string que, além do próprio hash, contém também o identificador do algoritmo usado, suas configurações e o sal criptográfico (dados aleatórios que garantem que para a mesma senha seja gerado um hash diferente). É, portanto, retrocompatível; se, por exemplo, você alterar os parâmetros, os hashes armazenados usando as configurações anteriores ainda poderão ser verificados. Todo esse resultado é armazenado no banco de dados, portanto, não é necessário armazenar o sal ou as configurações separadamente.
verify (string $password, string $hash): bool
Verifica se a senha fornecida corresponde à impressão digital fornecida. Obtenha $hash do banco de dados de acordo com o nome de usuário ou endereço de e-mail fornecido.
if ($passwords->verify($password, $hash)) { // senha correta } needsRehash (string $hash): bool
Verifica se o hash corresponde às opções especificadas no construtor.
É útil usar quando, por exemplo, você altera a velocidade de hashing. A verificação ocorre de acordo com as configurações armazenadas e, se needsRehash() retornar true, é necessário criar novamente o hash, desta vez com os novos parâmetros, e armazená-lo novamente no banco de dados. Desta forma, os hashes armazenados são “atualizados” automaticamente durante o login dos usuários.
if ($passwords->needsRehash($hash)) { $hash = $passwords->hash($password); // armazenar $hash no banco de dados }