How Hashing Works: A Clear Overview for Beginners

What is Hashing?

Hashing is a process used in computer science and cryptography to transform data into a fixed-size string of characters, which is typically a hash code.

This transformation is accomplished using a hash function, which takes an input (or 'message') and returns a unique hash value. The primary purpose of hashing is to enable fast data retrieval and to ensure data integrity.

Why should we use Hashing?

Password hashing is a special technique used to store passwords, making them hard to misuse securely. Instead of storing passwords directly in our database, we should convert them to hashes and then store them.

What is Salt?

A randomly generated value is added to the password before the hashing. This prevents attackers from using precomputed tables (rainbow tables) to crack passwords.

What is Salting?

Salting is a technique used with hashing to make passwords stronger. If two users have the same password, the hash will be the same, making it easy for an attacker to crack. Salting adds randomly generated text to the password and then converts it in the hash, so each hash value differs.

B-Crypt

B-Crypt is a popular password hashing function designed to be computationally intensive to resist brute-force attacks.

It incorporates a salt to protect against rainbow table attacks and includes a work factor, which determines how slow the hashing process will be.

This work factor can be adjusted to make the hashing process more time-consuming, thereby increasing the security of the hashed passwords.

How to use the Bcrypt Library

Convert Password with Hashing

Step 1. First, download the Bcrypt library using the npm command shown below.

npm i bcrypt

Step 2. Next, you need to import bcrypt into your project.

Step 3. Then, convert the user's password using the hash function provided by the bcrypt library.

bcrypt.hash(myPlaintextPassword, saltRounds, function(err, hash) {
    // Store hash in your password DB.
});
///Example
const hashPassword = await bcrypt.hash(password, 8)

Step 4. Now, save the hashed password in the database.

Hash Password Verification with bcrypt

Once the user sends you the username and password to the signup route, you need to retrieve it from the request header and store it in a variable.

Next, you must check if the user's email is present in your database. For example:

app.post("/signin", async function (req, res) {
    const email = req.body.email;
    const password = req.body.password;

    const response = await UserModel.findOne({
        email: email,
    });

If the user's email is not in your database, you need to send a response indicating that the email is not found.

  if(!response){
        res.status(403)
        .json({
            Message:"User Not Found"
        })
    }

But if the user's email is present, you need to check if the password is correct. The question is, how do you check this since the password stored in the database is hashed, and the password the user sends is in plain text?

To do this, you use the compare function from the bcrypt library. It takes two arguments: the first is the password entered by the user, and the second is the hashed password stored in your database, which you can retrieve with a database call.

const passwordMatch= await bcrypt.compare(password,response.password)

The compare function will return true or false. If the password is correct, you can assign a JWT token. If the password doesn't match, you can return an error message.


    if (passwordMatch) {
        const token = jwt.sign({
            id: response._id.toString()
        }, JWT_SECRET);

        res.json({
            token
        })
    } else {
        res.status(403).json({
            message: "Incorrect creds"
        })
    }

Complete Code for hashing

const express = require("express");
const bcrypt = require("bcrypt");
const { UserModel, TodoModel } = require("./db");
const { auth, JWT_SECRET } = require("./auth");
const jwt = require("jsonwebtoken");
const mongoose = require("mongoose");

// Use environment variable for DB connection string
let dbConnection = mongoose.connect(process.env.MONGO_URI);

const app = express();
app.use(express.json());

app.post("/signup", async function (req, res) {
    const { email, password, name } = req.body;

    const hashPassword = await bcrypt.hash(password, 8);
    await UserModel.create({ email, password: hashPassword, name });

    res.json({ message: "You are signed up" });
});

app.post("/signin", async function (req, res) {
    const { email, password } = req.body;

    const response = await UserModel.findOne({ email });
    if (!response) {
        return res.status(403).json({ message: "User Not Found" });
    }

    const passwordMatch = await bcrypt.compare(password, response.password);
    if (passwordMatch) {
        const token = jwt.sign({ id: response._id.toString() }, JWT_SECRET);
        return res.json({ token });
    }

    res.status(403).json({ message: "Incorrect credentials" });
});

app.post("/todo", auth, async function (req, res) {
    const { userId } = req;
    const { title, done } = req.body;

    await TodoModel.create({ userId, title, done });
    res.json({ message: "Todo created" });
});

app.get("/todos", auth, async function (req, res) {
    const { userId } = req;

    const todos = await TodoModel.find({ userId });
    res.json({ todos });
});

app.listen(3000, () => console.log("Server running on port 3000"));

Conclusion

In conclusion, hashing is a fundamental technique in computer science and cryptography that enhances data security and integrity. Transforming data into a fixed-size hash code allows for efficient data retrieval and secure storage, particularly in the context of password management.

Techniques like salting and using robust hashing functions such as B-Crypt further strengthen security by protecting against common attacks like brute-force and rainbow table attacks.

Implementing these practices ensures that sensitive information, such as user passwords, is stored securely, reducing the risk of unauthorised access and data breaches.

0
Subscribe to my newsletter

Read articles from Aditya Kumar Gupta directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Aditya Kumar Gupta
Aditya Kumar Gupta

Hi there! I'm Aditya, a passionate Full-Stack Developer driven by a love for turning concepts into captivating digital experiences. With a blend of creativity and technical expertise, I specialize in crafting user-friendly websites and applications that leave a lasting impression. Let's connect and bring your digital vision to life!