leitura de
Encontrou um problema no conteúdo? Por favor, deixe seu comentário!

Tenho alguns artigos (beeem antigos) aqui no blog onde falo sobre encriptação/hashing de senhas usando sha1, md5 e etc.

Esses métodos de hashing atendem - de forma satisfatória - quem está começando a trabalhar com programação e desenvolvimento, mas são notavelmente inseguros se comparados à outros métodos (como o bcrypt).

Recomendo a leitura de um artigo meu (não tão antigo assim), onde falo sobre a bcrypt se baseia.

Desde então, eu tenho procurado me aprofundar um pouco mais no assunto, e recentemente comecei a usar o bcrypt nos meus projetos…

Suporte ao bcrypt

O PHP suporta hashing via crypt() que está presente desde o PHP 4, e serve pra trabalhar com hashings de mão única (como o MD5 e SHA1).

Usando o bcrypt

O bcrypt precisa - obrigatóriamente - receber dois “parâmetros” pra funcionar: o salt e o custo de processamento. O salt nada mais é do que a sua garantia de que, dado um salt aleatório, a mesma senha nunca será igualmente hasheada duas vezes… não importa que você criptografe a mesma senha 100 vezes, se o salt for diferente nas 100 vezes, o resultado final será sempre diferente. Para o bcrypt funcionar:

  1. O salt precisa ser uma string de 22 caracteres que respeite a expressão regular ./0-9A-Za-z.
  2. O custo deve ser um número inteiro entre 4 e 31, outro detalhe é que o custo precisa ter dois dígitos, então números menores que 10 precisam ter zero à esquerda

Fiz alguns testes e meu computador quase parou quado usei um custo de 15 – O custo é a potência de 2, então 2^15 equivale a 32.768 ciclos, já 2^31 equivaleria a 2.147.483.648 ciclos

O custo de processamento influencia diretamente nas tentativas de ataque de força bruta, quanto maior, mais lento, quanto mais lento, melhor.

Criptografando senhas usando bcrypt

Basicamente, pra criptografar a senha “olá mundo”, com o salt “Cf1f11ePArKlBJomM0F6aJ” à um custo de processamento de 8, você faria algo assim:

O que fizemos foi passar dois valores para a função crypt(): o valor a ser criptografado (a senha em si), e uma string ‘$2a$08$Cf1f11ePArKlBJomM0F6aJ$’, que é composta por três partes (separadas por cifrão):

  1. O método de hashing -- 2a -- que fará com que o bcrypt/blowfish seja usado
  2. O custo -- 08
  3. O salt -- Cf1f11ePArKlBJomM0F6aJ

Isso no vai gerar o seguinte hash:

$2a$08$Cf1f11ePArKlBJomM0F6a.EyvTNh6W2huyQi5UZst5qsHVyi3w5x.

Que é o valor que você deve salvar no banco de dados.

Caso essa mesma senha seja criptografada com o mesmo salt e o mesmo custo, o resultado será idêntico… caso você mude o salt (que deve ser gerado de forma aleatória) o resultado seria diferente.

Vale lembrar que o hash gerado terá sempre 60 caracteres, então você pode modelar a sua coluna que armazena a senha como CHAR(60) ou VARCHAR(60) se você estiver usando o MySQL. ;)

Verificando e validando senhas usando bcrypt

Agora suponhamos que o seu usuário está fazendo o login, e o único valor que você tem é o nome de usuário (ou email, tanto faz) e a senha que ele digitou no formulário (ola mundo), como comparar isso com o valor que está no banco para verificar se os dados estão válidos?

Já que você está trabalhando com um salt gerado aleatoriamente, é impossível gerar um novo hash que seja igual ao hash que está no banco… correto? ERRADO! :)

Para comparar uma senha texto-plano com um já hasheado, é só usar esse próprio valor hasheado como hash da senha text-plano, vejam como é simples:

É ou não é sensacional? Você pode gerar o mesmo hash, tendo a senha original e o hash resultado, sem precisar do salt original! :) Isso garante que você pode gerar um salt aleatório sempre que for criptografar a senha de alguém.

E é aí que o custo entra em jogo… mesmo durante um ataque de força bruta, o atacante pode tentar diferentes combinações de “senha original” mas o custo vai tornar a operação toda tão lenta que não vai valer o esforço.

Uma pequena classe para facilitar a sua vida

Criei uma pequena classe Bcrypt que ajuda a fazer esse trabalho todo através de dois métodos bem simples de usar..

Primeiro, o código completo da classe:

Agora como você pode usar os métodos:

Espero que tenham gostado! :)

Thiago Belem / Blog

Thiago Belem


Publicado

Thiago Belem / Blog

Thiago Belem / Blog

Artigos e tutoriais sobre desenvolvimento WEB

Continue lendo