Node JS | Password Hashing with Crypto module

In real life applications with User authentication functionality, it is not practical to store user password as the original string in the database but it is good practice to hash the password and then store them into the database.

Crypto module for Node JS helps developers to hash user password.

Examples:



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

Password Hashing with Crypto module

To demonstrate the use of Crypto module, we can create a simple login and signup API and test it using Postman.
We will use two functions:

  1. cryto.randomBytes(“length”) : generates cryptographically strong data of given “length”.
  2. crypto.pbkdf2Sync(“password”, “salt”, “iterations”, “length”, “digest”) : hashes “password” with “salt” with number of iterations equal to given “iterations” (More iterations means more secure key) and uses algorithm given in “digest” and generates key of length equal to given “length”.

Project Dependencies:

  • node JS: For Backend Server.
  • express module for creating server.
  • mongoose module for MongoDB connection and queries.
  • Crypto module for hashing.
  • body-parser for parsing json data.

Steps to perform the operation

  1. First create a directory structure as below :
    hashApp
    --model
    ----user.js
    --route
    ----user.js
    --server.js
    
  2. Create model/user.js file which defines user schema
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // 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);

    chevron_right

    
    

  3. Create route/user.js file :
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // 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();
      
        // Intialize 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 succesfully."
                });
            }
        });
    });
      
    // Export module to allow it to be imported in other files
    module.exports = router;

    chevron_right

    
    

  4. Create server.js file :
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // Importing modules
    var express = require('express');
    var mongoose = require('mongoose');
    var bodyparser = require('body-parser');
      
    // Intialize 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);
    });

    chevron_right

    
    

  5. Run server.js file using command node server.js from the hashApp directory
  6. Open Postman and create a post request to localhost:3000/api/user/signup as below:

    You will get the response as below:

    User data is stored in the database as below:

    {
        "_id": {
            "$oid": "5ab71ef2afb6db0148052f6f"
        },
        "name": "geeksforgeeks",
        "email": "geek@geeksforgeeks.org",
        "salt": "ddee18ef6a6804fbb919b25f790005e3",
        "hash": "bbf13ae4db87d475ca0ee5f97e397248a23509fc10c82f1e3cf110
         b352c3ca6cc057955ace9d541573929cd7a74a280a02e8cb549136b43df7704caaa555b38a",
        "__v": 0
    }
    
  7. From Postman create a post request to localhost:3000/api/user/login as below:

    You will get the response as below:

Applications:

  • Hashing password is necessary for practical application.
  • Crypto module makes hashing easy to implement.
  • Hashing passwords ensure user’s privacy.

References:



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : ssshivyasaxena20



Article Tags :

1


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.