Node JS | Hashing de contraseña con módulo Crypto

En aplicaciones de la vida real con funcionalidad de autenticación de usuario, no es práctico almacenar la contraseña de usuario como la string original en la base de datos, pero es una buena práctica codificar la contraseña y luego almacenarla en la base de datos.

El módulo criptográfico para Node JS ayuda a los desarrolladores a codificar la contraseña del usuario.

Ejemplos:

Original Password : portalforgeeks
Hashed Password : bbf13ae4db87d475ca0ee5f97e397248a23509fc10c82f
1e3cf110b352c3ca6cc057955ace9d541573929cd7a74a
280a02e8cb549136b43df7704caaa555b38a

Hashing de contraseña con módulo Crypto

Para demostrar el uso del módulo Crypto, podemos crear una API simple de inicio de sesión y registro y probarla con Postman.
Usaremos dos funciones:

  1. cryto.randomBytes(“longitud”): genera datos criptográficamente fuertes de una “longitud” dada.
  2. crypto.pbkdf2Sync(“contraseña”, “sal”, “iteraciones”, “longitud”, “resumen”): hash “contraseña” con “sal” con un número de iteraciones igual a las “iteraciones” dadas (Más iteraciones significa una clave más segura ) y usa el algoritmo dado en «resumen» y genera una clave de longitud igual a la «longitud» dada.

Dependencias del proyecto:

  • Node JS: para servidor backend.
  • módulo express para la creación de servidor.
  • módulo mongoose para conexión y consultas MongoDB.
  • Módulo criptográfico para hashing.
  • body-parser para analizar datos json.

Pasos para realizar la operación

  1. Primero cree una estructura de directorios como se muestra a continuación:
    hashApp
    --model
    ----user.js
    --route
    ----user.js
    --server.js
    
  2. Cree el archivo model/user.js que define el esquema del usuario

    // Importing modules
    const mongoose = require('mongoose');
    var crypto = require('crypto');
      
    // Creating user schema
    const UserSchema = mongoose.Schema({
        name : {
            type : String,
            required : true
        },
        email : {
            type : String,
            required : true
        },
        hash : String,
        salt : String
    });
      
    // Method to set salt and hash the password for a user
    // setPassword method first creates a salt unique for every user
    // then it hashes the salt with user password and creates a hash
    // this hash is stored in the database as user password
    UserSchema.methods.setPassword = function(password) {
         
     // Creating a unique salt for a particular user
        this.salt = crypto.randomBytes(16).toString('hex');
      
        // Hashing user's salt and password with 1000 iterations,
        64 length and sha512 digest
        this.hash = crypto.pbkdf2Sync(password, this.salt, 
        1000, 64, `sha512`).toString(`hex`);
    };
      
    // Method to check the entered password is correct or not
    // valid password method checks whether the user
    // password is correct or not
    // It takes the user password from the request 
    // and salt from user database entry
    // It then hashes user password and salt
    // then checks if this generated hash is equal
    // to user's hash in the database or not
    // If the user's hash is equal to generated hash 
    // then the password is correct otherwise not
    UserSchema.methods.validPassword = function(password) {
        var .hash = crypto.pbkdf2Sync(password, 
        this.salt, 1000, 64, `sha512`).toString(`hex`);
        return this.hash === hash;
    };
      
    // Exporting module to allow it to be imported in other files
    const User = module.exports = mongoose.model('User', UserSchema);
  3. Cree el archivo route/user.js:

    // Importing modules
    const express = require('express');
    const router = express.Router();
      
    // Importing User Schema
    const User = require('../model/user');
      
    // User login api
    router.post('/login', (req, res) => {
      
        // Find user with requested email
        User.findOne({ email : req.body.email }, function(err, user) {
            if (user === null) {
                return res.status(400).send({
                    message : "User not found."
                });
            }
            else {
                if (user.validPassword(req.body.password)) {
                    return res.status(201).send({
                        message : "User Logged In",
                    })
                }
                else {
                    return res.status(400).send({
                        message : "Wrong Password"
                    });
                }
            }
        });
    });
      
    // User signup api
    router.post('/signup', (req, res, next) => {
         
     // Creating empty user object
        let newUser = new User();
      
        // Initialize newUser object with request data
        newUser.name = req.body.name,
      
        newUser.email = req.body.email
      
                        // Call setPassword function to hash password
                        newUser.setPassword(req.body.password);
      
        // Save newUser object to database
        newUser.save((err, User) => {
            if (err) {
                return res.status(400).send({
                    message : "Failed to add user."
                });
            }
            else {
                return res.status(201).send({
                    message : "User added successfully."
                });
            }
        });
    });
      
    // Export module to allow it to be imported in other files
    module.exports = router;
  4. Crear archivo server.js:

    // Importing modules
    var express = require('express');
    var mongoose = require('mongoose');
    var bodyparser = require('body-parser');
      
    // Initialize express app
    var app = express();
      
    // Mongodb connection url
      
    // Connect to MongoDB
    mongoose.connect(MONGODB_URI);
    mongoose.connection.on('connected',() => {
        console.log('Connected to MongoDB @ 27017');
    });
      
    // Using bodyparser to parse json data
    app.use(bodyparser.json());
      
    // Importing routes
    const user = require('./route/user');
      
    // Use user route when url matches /api/user/
    app.use('/api/user', user);
      
    // Creating server
    const port = 3000;
    app.listen(port,() => {
        console.log("Server running at port: " + port);
    });
  5. Ejecute el archivo server.js usando el Node de comando server.js desde el directorio hashApp
  6. Abra Postman y cree una solicitud de publicación en localhost:3000/api/user/signup como se muestra a continuación:

    Obtendrá la respuesta de la siguiente manera:

    Los datos del usuario se almacenan en la base de datos de la siguiente manera:

    {
        "_id": {
            "$oid": "5ab71ef2afb6db0148052f6f"
        },
        "name": "geeksforgeeks",
        "email": "geek@geeksforgeeks.org",
        "salt": "ddee18ef6a6804fbb919b25f790005e3",
        "hash": "bbf13ae4db87d475ca0ee5f97e397248a23509fc10c82f1e3cf110
         b352c3ca6cc057955ace9d541573929cd7a74a280a02e8cb549136b43df7704caaa555b38a",
        "__v": 0
    }
    
  7. Desde Postman, cree una solicitud de publicación en localhost: 3000/api/user/login como se muestra a continuación:

    Obtendrá la respuesta de la siguiente manera:

Aplicaciones:

  • La contraseña hash es necesaria para la aplicación práctica.
  • El módulo criptográfico facilita la implementación del hashing.
  • Las contraseñas hash garantizan la privacidad del usuario.

Referencias:

Publicación traducida automáticamente

Artículo escrito por neerajnegi174 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *