Crea una cuenta o inicia sesi贸n

隆Contin煤a aprendiendo sin ning煤n costo! 脷nete y comienza a potenciar tu carrera

Aprende todo un fin de semana sin pagar una suscripci贸n 馃敟

Aprende todo un fin de semana sin pagar una suscripci贸n 馃敟

Reg铆strate

Comienza en:

3D
15H
25M
52S

Hashing de contrase帽as con bcryptjs

5/20
Recursos

Aportes 13

Preguntas 1

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

Esta libreria es muy util para muchas otras cosas mas, porque hay ciertas legislaciones que sancionan si se tiene informaci贸n sencible de los usuarios sin estar protegida como por ejemplo, nombre completo, direcci贸n de email, direccion postal entre otras

con esta libreria se puede implementar una rutina que al momento de guardar informaci贸n sencible la encripte y luego la guarde en la base de datos y cuando deba ser consultada por usuarios esta infirmaci贸n sea desencriptada para luego ser mostrada. Asi la infirmaci贸n guardada si llega a ser comprometida no podr谩 ser desencriptada a menos que se dispongan de las claves de encriptaci贸n y desencriptaci贸n

El hashing de contrase帽as encripta (hashea) el password para poder guardarlo en la base de datos ya que por motivos de seguridad no es recomendado guardar el password en crudo.

Instalar bcrypt: npm i bcrypt

Para hashear una contrase帽a usando bcrypt se hace el uso de la funci贸n .hash(), esta funci贸n recibe como primer par谩metro la contrase帽a y despu茅s el n煤mero de salt. Esta funci贸n devuelve una promesa que se puede manejar con async/await, por ejemplo:

const bcrypt = require('bcrypt');

async function hashPassword() {
  const myPassword = 'admin1.2.3'
  const hash = await bcrypt.hash(myPassword, 10);
  console.log(hash);
}

hashPassword(); // $2b$10$GiP.RKuC7tdx8pIoWMRkZuyCwbQYs8aBhJLaqwwqa6bJ1LET.Msom

Para verificar la contrase帽a se necesita el password en crudo y el hash generado, con ello se hace el uso de la funci贸n .compare() que recibe como primer par谩metro la contrase帽a en crudo y despu茅s el hash. Esta funci贸n devuelve un booleano, por ejemplo:

const bcrypt = require('bcrypt');

async function verifyPassword() {
  const myPassword = 'admin1.2.3';
  const hash = '$2b$10$6.K1g7Nu7YrVUbLE1FhSJORhkeOg0.X3LVamYf7aZKssfNAWbOgya';
  const isMatch = await bcrypt.compare(myPassword, hash);
  console.log(isMatch);
}

verifyPassword(); // True

Para correr el c贸digo de forma directa instalen la extensi贸n code Runner

En el minuto 5:30 podemos ver que la salida de BCrypt es distinta a煤n para el mismo password. Esta es la funci贸n de salt (tambi茅n conocida como sal). Esta sal permite, por ejemplo, que si 2 o mas usuarios tuvieran el mismo password en la base de datos ver铆amos cadenas de texto distintas para cada uno de ellos

Por lo que estube investigando, el salt, no hace referencia a 鈥渟altos鈥, sino a una cadena de caracteres que se agrega a la password original y que es desconocida por el usuario, a fin incrementar la seguridad del proceso de hash. Esto es, evitar ataques de rainbow-tables o hashes pre-computados.

Al usar:

bcrypt.hash(myPassword, 10);

estamos pidiendole a bcrypt que nos auto-genere un salt por nosotros.

fuentes:

Entre mayor sea el numero de saltos mayor sera la dificultad de la encriptacion por tanto sera +SEGURA pero sera +LENTO conseguirla y el async tardara mas en responder

Interesant铆sima esta clase!

Un Hash es una funci贸n matem谩tica que a partir de una cierta cadena alfanum茅rica, se obtiene otra reducida. Es como si fuese un serial de la cadena original. La particularidad que tiene es que este proceso es irreversible. Teniendo un hash es imposible reproducir el original en forma directa.

Por eso en los sistemas en vez de almacenar las claves, es mas seguro hacerlo con el hash, ya que si estos son comprometidos, carecen de valor al no poder revertirlos.

Cabe tambi茅n aclarar, aunque es muy dif铆cil, que te贸ricamente dos cadenas alfanum茅ricas pueden dar como resultado el mismo hash.

npm i bcrypt

Clase #5: Hashing de contrase帽as con bcryptjs 5/20 馃敀

驴Qu茅 es el hash y para qu茅 sirve? 馃攼


Los hashes criptogr谩ficos se utilizan principalmente para proteger las contrase帽as y no guardarlas en texto claro en una base de datos (fuente: aqu铆).

驴Qu茅 significa agregar un 鈥榮alt鈥 a una contrase帽a / hash? 馃攺


Salt es un n煤mero de d铆gitos aleatorios (cadena) que se le agrega a la contrase帽a ya sea al principio o al final y que el usuario no conocer谩 (fuente: aqu铆).

Continuando con el Proyecto: 馃摑 :


C贸mo no podemos guardar el password en crudo, debemos usar un hashing de contrase帽as (encriptarlas).

Pasos:

  • Vamos a la terminal (dentro de la carpeta del proyecto) e instalamos:
npm i bcrypt


Al instalar correctamente debe salir: found 0 vulnerabilities

  • Vamos a VSC, creamos el archivo pass-hash.js y colocamos el siguiente c贸digo:
const bcrypt = require('bcrypt');

async function hashPassword() {
  const myPassword = 'admin 123 .202';
  //Con la funci贸n hash usando bcrypt,
  //se debe enviar el password y cu谩ntas veces va a generar el encriptado (saltos)
  const hash = await bcrypt.hash(myPassword, 10);
  console.log(hash);
}

hashPassword();


Cuando se quiere consultar a la API, se va a enviar una contrase帽a, en el c贸digo se encuentra la funci贸n hash() donde enviamos el password y un n煤mero que indica cu谩ntas veces se va a generar el encriptado (n煤mero de saltos); c贸mo este m茅todo es as铆ncrono, 茅ste devuelve una promesa. Con bcrypt se hace un hash.

  • Guardamos y para correrlo dentro de VSC, en la esquina superior derecha del archivo se encuentra el triangulo apuntando a la derecha, se presiona y se ejecuta el programa, abajo en el cuadro de dialogo, en la pesta帽a 鈥渙utput鈥 aparecer谩 el password transformado:
[Running] node "/home/marigabi/projects/platzi-backend-node-jwt/my-store-auth/pass-hash.js"
$2b$10$f.QqlNHMe/nr2oCbI98lpOxXP.ds5iwFkwalcxfCBr.h.l7Hyo0xu

[Done] exited with code=0 in 2.516 seconds


Despu茅s de los primeros d铆gitos, muestra el n煤meros de saltos que fueron necesarios para encriptar.

  • Para verificar si la contrase帽a es correcta, se crea un nuevo archivo en VSC llamado pass-veriy.js, el c贸digo queda:
const bcrypt = require('bcrypt');

async function verifyPassword() {
  const myPassword = 'admin 123 .202';
  //const hash = '$2b$10$.q.8/z3PP1KrruUqNuK9quJgCHQ.5S4w3.FyKmHEGEFqc19OVEqBW';
  const hash = '$2b$10$3UK/fRuvHueA/cPeSO2MVOuQQd2Z/xTB1FrzftPRP11VdUy3kg8gG';
  const isMatch = await bcrypt.compare(myPassword, hash);
  console.log(isMatch);
}

verifyPassword();


Con el m茅todo compare() si regresa un true, quiere decir que el password coincide y es correcto, de lo contrario el usuario no tiene permitido el acceso.

  • Guardamos y corremos con el bot贸n play (triangulo), en el panel de salida (output) sale:
[Running] node "/home/marigabi/projects/platzi-backend-node-jwt/my-store-auth/pass-verify.js"
true

[Done] exited with code=0 in 0.474 seconds

extensi贸n code runner para ejecutar el c贸digo de forma directa
https://marketplace.visualstudio.com/items?itemName=formulahendry.code-runner

AL parecer hay un problema al intentar instalar bcrypt en linux, o por lo menos tuve problemas al intentarlo en fedora.

En mi caso lo resolv铆 instalando bcryptjs( npm i bcryptjs -D), y listo. Tiene los mismos m茅todos que bcrypt, y funcionan igual.

Les dejo esta otra alternativa que utiliza el algoritmo Scrypt (incluido en node) para crear el hash de la contrase帽a, de forma que no necesitamos usar librerias externas para ello

Pero como indica este articulo la mejor protecci贸n son contrase帽as largas y con distintos caracteres

const { randomBytes, scryptSync } = require("crypto");

/**
 * Encrypts the user's password using the Scrypt algorithm
 * @param {string} password 
 * @returns {Promise<string>}
 */
async function hashPassword(password) {
   password = password.trim();
   const randomSalt = randomBytes(16).toString("hex");
   const hashedPassword = scryptSync(password, randomSalt, 16).toString("hex");

   const fullHash = `${randomSalt}:${hashedPassword}`;

   console.log(fullHash.length);
   return fullHash;
}

/**
 * Verifies if the password provided matches with the hash
 * @param {string} password
 * @param {string} passwordHash
 * @returns {Promise<string>}
 */
async function verifyPassword(password, passwordHash) {
   password = password.trim();
   const [salt, hashedPassword] = passwordHash.split(":");

   const compHash = scryptSync(password, salt, 16).toString("hex");

   return compHash === hashedPassword;
}

module.exports = {hashPassword, verifyPassword}