Criptografia em Node JS com Bcrypt

1 de agosto de 2022
Ronaldo B.

Conhecendo a lib Bcrypt

Segurança é sem dúvida a maior preocupação quando o assunto é dados, informações sensíveis como credenciais de acesso, dados privados e confidenciais. Num mundo totalmente conectado e disponível como os dias atuais, onde os sistemas estão online quase 99% do tempo, proteger as informações e os dados que trafegam na rede, é a principal missão dos desenvolvedores aliado a performance da aplicação. 

Entre as muitas opções de segurança disponíveis hoje, a biblioteca Bcrypt se destaca, criada por Niels Provos e David Mazières, criptógrafos e pesquisadores que criaram um sistema de criptografia  que utiliza um hash de senhas. Esse algoritmo é um dos mais seguros na atualidade, isso por que permite adicionar um código aleatório ao hash original, também permite aumentar a dificuldade de decifrar o hash por adicionar um salt. Permitindo utilizar o poder computacional para criptografar os dados. 

Por adicionar códigos ao hash original, evita ataques de força bruta, e ataques que tentem reverter a criptografia do hash, utilizando tabelas rainbow.

Utilizado para proteger o sistemas de senhas do OpenBSD além de distribuições linux como SUSE Linux, implementado nas principais linguagens de programação, também está disponível para o JavaScript, e neste artigo veremos seu uso com NodeJS. Embora esse mecanismo de criptografia utilize comumente 56 caracteres ou bytes, pode chegar até 72 bytes.

Este sistema é o mais recomendado para armazenar dados sensíveis em banco de dados, como senhas, CPF, RG, ou ID interno da empresa, uma vez que caso os dados sejam expostos, o invasor não conseguirá reverter para os dados em texto limpo, mesmo utilizando rainbow tables.

Como funciona a lib BcryptJS

Com Node.JS é possível utilizar a lib bcrypt utilizando o módulo de terceiro bcrypt. com cerca de 500.000 download da biblioteca no repositório NPM, a lib bcrypt está entre as mais populares no gerenciador de pacotes NPM.

Para o Node.JS versão 12.13 utilizamos a versão 3.0.6 ou superior da lib bcrypt.

npm i bcrypt

No exemplo a seguir aplicaremos a biblioteca bcrypt em um hash de senhas dentro de um laço de repetição for, que irá encriptar a senha utilizando salt que vão de 10 a 20. ao executar o script em Node.JS repare que até 14 a exibição é quase instantânea, dependendo da máquina que você utiliza, pode ser que de 15 a 20 demore um pouco para gerar a criptografia.

const bcrypt = require('bcrypt');
const pass = '!]m:#$xDY@p/QDeW';

//examinando o hash de 2^10 até 2^20
for (let saltRounds = 10; saltRounds <= 15; saltRounds++) { 
  bcrypt.hash(pass, saltRounds)
  .then((passHashed)=> {
    console.time(`Time: ${saltRounds}`);
        console.log(passHashed);
    console.timeEnd(`Time: ${saltRounds}`);
  });
}

Esse tempo adicional é útil para impedir ataques de força bruta, é recomendável que você utilize até 240 ms acima disso poderá consumir muito poder computacional. Em um notebook Dell Inspiron i7 com 8GB de RAM e Windows 10.

O resultado foi apresentado abaixo, repare que nesta máquina o salt 12 seria o ideal por estar até 240ms. você pode rodar esse script no seu servidor, não necessariamente até 20, com isso terá uma ideia de qual Salt você deveria utilizar. Salt tem haver com sal de comida mesmo, com o tempero que você coloca na comida. Você adiciona a quantidade de "tempero" ideal para rodar o seu script.

Fique atento a quantidade de milissegundos que a criptografia gera, até 240ms está excelente.

Repare que neste caso o número de Salt está claramente no hash, ele fica na 5 e 6 posição do hash começando a contar do $. Se você não deseja exibir o número de Salt em texto limpo, é possível gerar o Salt com o método bcrypt.genSalt, assim o número não ficará aberto.

Comparando as informações

Podemos utilizar o método bcrypt.compare() para comparar a senha ou dados informados com o que já possuímos armazenados em um banco de dados por exemplo. Assim o método compare irá encriptar a senha informada e comparar com o a senha encriptada. É possível utilizar async e await para realizar essa comparação.

No mesmo arquivo adicionaremos abaixo o método compare. salt.js

.
.
.
//informado&nbsp;no&nbsp;formulário
let&nbsp;userPass&nbsp;=&nbsp;'!]m:#$xDY@p/QDeW'

async&nbsp;function&nbsp;check(username,&nbsp;pass){


 &nbsp;&nbsp; //buscando&nbsp;no&nbsp;banco&nbsp;a&nbsp;senha&nbsp;do&nbsp;usuário
 &nbsp;&nbsp; let&nbsp;passHashedDB&nbsp;=&nbsp;'$2b$12$dbstSfo1FN9jnZOSQ96N7eMMMe9FFI2QmYWo6E44WhutEUg9kZOcW'
 &nbsp;&nbsp; 
 &nbsp;&nbsp; const&nbsp;match&nbsp;=&nbsp;await&nbsp;bcrypt.compare(pass,&nbsp;passHashedDB&nbsp;)

 &nbsp;&nbsp; if(match)&nbsp;{
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; console.log('Granted!')
 &nbsp;&nbsp;&nbsp;}else&nbsp;{
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; console.log('Access&nbsp;Denied')
 &nbsp;&nbsp;&nbsp;}
}

//chamando a função check
check('JediMaster',userPass)

Repare que ao rodar o script novamente, ao chegar no Salt 12 ele exibe Granted! ou seja está correto. No exemplo a variável userPass corresponde ao que um usuário informou em um formulário no front-end e foi enviado por meio do request. Já a variável passHashedDB é uma consulta que seria feita em um Banco de Dados MySQL, MongoDB ou outros, com a senha encriptada. Recomendamos sempre utilizar a versão assíncrona dos métodos da lib bcrypt, isso fará com que o servidor utilize o EventLoop do Node e threads de processadores assíncronos aumentando o desempenho da aplicação.

Comparando a senha fornecida com a senha criptografada, após o Salt 12: Granted!

Então é isso pessoal, hoje falamos um pouco sobre a lib bcrypt, se você deseja aprender mais sobre esta e outras libs, não deixe de consultar o nosso Curso Completo de NodeJS onde ensinamos de forma profissional os recursos do Node, bem como dicas valiosas como essas.

Para fazer o download do código utilizado neste tutorial acesse: https://github.com/hcodebr/bcrypt-tutorial

A gente se vê num próximo artigo!

Glaucio Daniel

Hcode: Utilizamos cookies para a personalização de anúncios e experiências de navegação dentro de nosso site. Ao continuar navegando, você concorda com as nossas Política de Privacidade.