Node JS | Password Hashing with Crypto module

06 Dec, 2019
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:
cryto.randomBytes(“length”) : generates cryptographically strong data of given “length”.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”.
cryto.randomBytes(“length”) : generates cryptographically strong data of given “length”.
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
First create a directory structure as below :hashApp
--model
----user.js
--route
----user.js
--server.js
Create model/user.js file which defines user schema// Importing modulesconst mongoose = require('mongoose');var crypto = require('crypto');  // Creating user schemaconst 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 passwordUserSchema.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 notUserSchema.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 filesconst User = module.exports = mongoose.model('User', UserSchema);Create route/user.js file :// Importing modulesconst express = require('express');const router = express.Router();  // Importing User Schemaconst User = require('../model/user');  // User login apirouter.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 apirouter.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 filesmodule.exports = router;Create server.js file :// Importing modulesvar express = require('express');var mongoose = require('mongoose');var bodyparser = require('body-parser');  // Initialize express appvar app = express();  // Mongodb connection urlvar MONGODB_URI = "mongodb://localhost:27017/hashAppDb";  // Connect to MongoDBmongoose.connect(MONGODB_URI);mongoose.connection.on('connected', () => {    console.log('Connected to MongoDB @ 27017');});  // Using bodyparser to parse json dataapp.use(bodyparser.json());  // Importing routesconst user = require('./route/user');  // Use user route when url matches /api/user/app.use('/api/user', user);  // Creating serverconst port = 3000;app.listen(port, () => {    console.log("Server running at port: " + port);});Run server.js file using command node server.js from the hashApp directoryOpen 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
}
From Postman create a post request to localhost:3000/api/user/login as below:You will get the response as below:
First create a directory structure as below :hashApp
--model
----user.js
--route
----user.js
--server.js

hashApp
--model
----user.js
--route
----user.js
--server.js

Create model/user.js file which defines user schema// Importing modulesconst mongoose = require('mongoose');var crypto = require('crypto');  // Creating user schemaconst 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 passwordUserSchema.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 notUserSchema.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 filesconst User = module.exports = mongoose.model('User', UserSchema);
// Importing modulesconst mongoose = require('mongoose');var crypto = require('crypto');  // Creating user schemaconst 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 passwordUserSchema.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 notUserSchema.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 filesconst User = module.exports = mongoose.model('User', UserSchema);
Create route/user.js file :// Importing modulesconst express = require('express');const router = express.Router();  // Importing User Schemaconst User = require('../model/user');  // User login apirouter.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 apirouter.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 filesmodule.exports = router;
// Importing modulesconst express = require('express');const router = express.Router();  // Importing User Schemaconst User = require('../model/user');  // User login apirouter.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 apirouter.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 filesmodule.exports = router;
Create server.js file :// Importing modulesvar express = require('express');var mongoose = require('mongoose');var bodyparser = require('body-parser');  // Initialize express appvar app = express();  // Mongodb connection urlvar MONGODB_URI = "mongodb://localhost:27017/hashAppDb";  // Connect to MongoDBmongoose.connect(MONGODB_URI);mongoose.connection.on('connected', () => {    console.log('Connected to MongoDB @ 27017');});  // Using bodyparser to parse json dataapp.use(bodyparser.json());  // Importing routesconst user = require('./route/user');  // Use user route when url matches /api/user/app.use('/api/user', user);  // Creating serverconst port = 3000;app.listen(port, () => {    console.log("Server running at port: " + port);});
// Importing modulesvar express = require('express');var mongoose = require('mongoose');var bodyparser = require('body-parser');  // Initialize express appvar app = express();  // Mongodb connection urlvar MONGODB_URI = "mongodb://localhost:27017/hashAppDb";  // Connect to MongoDBmongoose.connect(MONGODB_URI);mongoose.connection.on('connected', () => {    console.log('Connected to MongoDB @ 27017');});  // Using bodyparser to parse json dataapp.use(bodyparser.json());  // Importing routesconst user = require('./route/user');  // Use user route when url matches /api/user/app.use('/api/user', user);  // Creating serverconst port = 3000;app.listen(port, () => {    console.log("Server running at port: " + port);});
Run server.js file using command node server.js from the hashApp directory
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
}

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
}

From Postman create a post request to localhost:3000/api/user/login as below:You will get the response 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:
https://nodejs.org/api/crypto.html
https://nodejs.org/api/crypto.html#crypto_crypto_pbkdf2_password_salt_iterations_keylen_digest_callback
ssshivyasaxena20
shubham_singh
nidhi_biet
Node.js
GBlog
Technical Scripter
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
GEEK-O-LYMPICS 2022 - May The Geeks Force Be With You!
Geek Streak - 24 Days POTD Challenge
How to Learn Data Science in 10 weeks?
What is Hashing | A Complete Tutorial
GeeksforGeeks Jobathon - Are You Ready For This Hiring Challenge?
GeeksforGeeks Job-A-Thon Exclusive - Hiring Challenge For Amazon Alexa
What is Data Structure: Types, Classifications and Applications
Roadmap to Learn JavaScript For Beginners
Axios in React: A Guide for Beginners
A Freshers Guide To Programming