9 de fev de 2015

Como utilizar bcrypt em python?


Após o post Qual criptografia utilizar para armazenar senhas? algumas pessoas me pediram para explicar como utilizar o bcrypt em python. Pelo que percebi, não existe nenhum post sobre isso em português (pelo menos até onde eu procurei), e eu imagino que com certeza deve ter bastante gente que interessaria em utilizar. Sendo assim, segue esse "tutorial"..


Primeiramente, precisamos instalar o módulo do bcrypt, pois ele não vem por padrão. Para isso, basta digitar o seguinte comando no terminal:


sudo pip install bcrypt

Agora é só a gente utilizar o módulo. Vou postar um exemplo de uso e depois eu explico.


>>> import bcrypt
>>> 
>>> senha = '12345'
>>> salt = bcrypt.gensalt(8)
>>> 
>>> print salt
$2a$08$K02Yy9Sn2mDReCeHwu3zse
>>> 
>>> hash = bcrypt.hashpw(senha, salt)
>>> 
>>> print hash
$2a$08$K02Yy9Sn2mDReCeHwu3zseMpikne058OpGqfMhKHhuDLIYrnvNT9G
>>>

Primeiro importamos o módulo do bcrypt. Depois definimos qual será a senha que desejamos criptografar. No nosso caso é a senha '12345'.

Depois geramos um salto aleatório. Isso nos garante que criptografando a mesma senha diversas vezes, com o salto aleatório, a senha criptografada nunca será a mesma. A função que gera esse salto aleatório é a gensalt() e ela recebe um parâmetro. Esse parâmetro é a variável custo. O custo pode variar de 4 a 31. Quanto maior for o custo, mais poder de processamento será necessário para criptografar a senha. Você não pode escolher um custo muito baixo nem um muito alto. Se escolher um custo baixo, os ataques de força bruta serão eficazes. Se escolher um custo muito alto, seu servidor pode ficar muito lento. No meu pc, gerar uma senha com custo 16 demora cerca de 5 segundos. Eu recomendaria, para um servidor mais modesto, utilizar o custo 8 como padrão.

Continuando, quando imprimimos o salto gerado podemos notar algumas coisas.
A parte $2a nos fala sobre o tipo de criptografia que estamos utilizando, que no caso é o bcrypt. A parte $08 nos fala sobre qual foi a variável custo.

Agora para criptografar a senha, utilizamos a função hashpw() que recebe dois parâmetros. O primeiro é a senha em texto puro, e o segundo é o salto. Com isso geramos a hash correspondente à senha criptografada.

Agora, para compararmos uma senha em texto puro com a hash gerada fazemos o seguinte:



>>> senha_pura = '12345'
>>> salto = '$2a$08$K02Yy9Sn2mDReCeHwu3zse'
>>> senha_cript = '$2a$08$K02Yy9Sn2mDReCeHwu3zseMpikne058OpGqfMhKHhuDLIYrnvNT9G' 
>>> bcrypt.hashpw(senha_pura, salto) == senha_cript
True
>>> bcrypt.hashpw(senha_pura, senha_cript) == senha_cript
True
>>> 
>>> 
>>> salto += 'asdf12345'
>>> bcrypt.hashpw(senha_pura, salto) == senha_cript
True
>>>

O jeito mais fácil de comparar é fazendo o seguinte:

bcrypt.hashpw(senha_pura, senha_cript) == senha_cript

Porém, analisando melhor eu concluí que a função hashpw() na verdade utiliza apenas 29 caracteres do segundo argumento (senha_cript) e ignora o resto. Ele utiliza o segundo argumento para gerar uma nova hash, e a compara com a senha criptografada.

Não sei se consegui ser claro nisso que eu disse. Caso você não tenha entendido, ignore o que está acima e veja somente o que está abaixo.


>>> senha = '12345'                                                            '
>>> senha_cript = '$2a$08$K02Yy9Sn2mDReCeHwu3zseMpikne058OpGqfMhKHhuDLIYrnvNT9G' 
>>> 
>>> bcrypt.hashpw(senha, senha_cript) == senha_cript
True
>>> 



Espero que eu tenha sido claro nas explicações.
Valeu e até o próximo post.

Nenhum comentário:

Postar um comentário