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.

Instalação e requisitos

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 $passwords): 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
}
versão: 4.0