Dev.to Security πŸ” Cybersecurity πŸ‘ 0 πŸ“– 4 min read

Argon2 vs bcrypt vs PBKDF2 in Node.js: Which Password Hashing Algorithm Should You Use in 2026?

Introduction Password storage is one of the most important security decisions when building a backend application. A common mistake developers make is storing passwords using fast hashing algorithms like: SHA256(pa

Argon2 vs bcrypt vs PBKDF2 in Node.js: Which Password Hashing Algorithm Should You Use in 2026?

Introduction

Password storage is one of the most important security decisions when building a backend application.

A common mistake developers make is storing passwords using fast hashing algorithms like:

SHA256(password)
MD5(password)

These algorithms are designed to be fast, which makes them perfect for data integrity checks but terrible for password storage.

If your database is leaked, attackers can use GPUs and password-cracking tools to test billions of passwords.

attackflow
Modern password hashing algorithms solve this problem by intentionally making password cracking expensive.

The three most common choices in Node.js applications are:

  • Argon2id
  • bcrypt
  • PBKDF2

This article explains how each works and how to implement them correctly in Node.js applications.

1. Password Hashing Flow in a Node.js Application

A secure authentication system follows this flow:

User Registration
        |
        |
        v
User enters password
        |
        |
        v
Generate random salt
        |
        |
        v
Password Hashing Algorithm
        |
        |
        v
Store Hash in Database

hashing

Example database:

{
    "email": "[email protected]",
    "password": "$argon2id$v=19$m=65536,t=3,p=4$..."
}

During login:

User Login
     |
     |
     v
Enter Password
     |
     |
     v
Retrieve Stored Hash
     |
     |
     v
Verify Password
     |
     |
     v
Allow / Reject Login

2. Argon2id Implementation in Node.js

What is Argon2id?

Argon2id is currently the recommended password hashing algorithm for new applications.

It was designed to resist:

  • GPU cracking attacks
  • Password dictionary attacks
  • Large-scale offline attacks

Unlike bcrypt and PBKDF2, Argon2id is memory-hard.

That means an attacker cannot simply add more GPUs to increase cracking speed.

argon2

Installing Argon2

Install the package:

npm install argon2

Basic Argon2id Password Hashing

Example:

const argon2 = require("argon2");


async function hashPassword(password){

    const hash = await argon2.hash(password,{
        type: argon2.argon2id
    });

    return hash;
}


async function verifyPassword(password,hash){

    return await argon2.verify(
        hash,
        password
    );
}

Argon2id Configuration

Production systems should configure the cost parameters.

Example:

const hash = await argon2.hash(password,{

    type: argon2.argon2id,

    memoryCost: 65536,

    timeCost: 3,

    parallelism: 4

});

argon2conf

Understanding Argon2 Settings

memoryCost

Controls RAM usage.

Example:

memoryCost: 65536

means:

65536 KB

β‰ˆ

64 MB RAM

Higher value:

More security
+
More server memory usage

timeCost

Number of iterations.

Example:

timeCost:3

means:

Password processing happens 3 times

parallelism

Number of CPU threads.

Example:

parallelism:4

means:

Use 4 parallel lanes

Recommended Node.js Production Config

const ARGON_CONFIG = {

    type: argon2.argon2id,

    memoryCost: 65536,

    timeCost: 3,

    parallelism: 4

};

Complete User Registration Example

const argon2 = require("argon2");


async function registerUser(password){

    const passwordHash =
        await argon2.hash(
            password,
            ARGON_CONFIG
        );


    await User.create({

        password: passwordHash

    });

}

Database stores:

$argon2id$v=19$m=65536,t=3,p=4$...

The configuration is stored inside the hash.

You do not need to save:

memoryCost
timeCost
parallelism

separately.

Login Verification

async function login(password,storedHash){

    const valid =
        await argon2.verify(
            storedHash,
            password
        );


    if(valid){

        return "Login success";

    }


    throw Error("Invalid password");

}

3. bcrypt Implementation in Node.js

What is bcrypt?

bcrypt is one of the oldest and most widely used password hashing algorithms.

It is still secure when configured correctly.

Many existing Node.js applications use bcrypt.

Installing bcrypt

npm install bcrypt

Basic bcrypt Example

const bcrypt = require("bcrypt");


async function hashPassword(password){

    const saltRounds = 12;


    return await bcrypt.hash(
        password,
        saltRounds
    );

}

Understanding bcrypt Cost Factor

Example:

bcrypt.hash(password,12)

The number:

12

is the cost factor.

Calculation:

2^cost

Example:

cost 10

=
1024 rounds


cost 12

=
4096 rounds

Higher cost:

More secure
+
Slower login

costfactor

Recommended bcrypt Configuration

const BCRYPT_ROUNDS = 12;

For high-security applications:

const BCRYPT_ROUNDS = 14;

bcrypt Verification

const match =
await bcrypt.compare(
    userPassword,
    databaseHash
);


if(match){

    console.log("Authenticated");

}

bcrypt Limitations

bcrypt has one major limitation:

Maximum password length:

72 bytes

Example:

VeryLongPassword....................

Only first 72 bytes processed

For new systems, Argon2id is usually preferred.

4. PBKDF2 Implementation in Node.js

What is PBKDF2?

PBKDF2 is a password-based key derivation algorithm.

It is commonly used in:

  • Enterprise systems
  • Banking systems
  • Compliance environments

Node.js already includes PBKDF2 through the built-in crypto module.

No package installation required.

PBKDF2

PBKDF2 Example

const crypto = require("crypto");


function hashPassword(password){

    const salt =
    crypto.randomBytes(16)
    .toString("hex");


    const hash =
    crypto.pbkdf2Sync(

        password,

        salt,

        600000,

        64,

        "sha256"

    );


    return {

        salt,

        hash:
        hash.toString("hex")

    };

}

PBKDF2 Configuration

crypto.pbkdf2Sync(

password,

salt,

iterations,

keyLength,

digest

)

Example:

600000

means:

600,000 iterations

Recommended PBKDF2 Settings

{

iterations:600000,

keyLength:64,

algorithm:"sha256"

}

PBKDF2 Verification

function verifyPassword(
password,
salt,
storedHash
){

const hash =
crypto.pbkdf2Sync(

password,

salt,

600000,

64,

"sha256"

);


return (
hash.toString("hex")
===
storedHash
);

}

5. Node.js Configuration Comparison

Algorithm Package Configuration
Argon2id argon2 memory, iterations, parallelism
bcrypt bcrypt salt rounds
PBKDF2 crypto iterations, key length

compare

6. Environment-Based Configuration

Do not hardcode security settings.

Example:

.env

PASSWORD_ALGORITHM=argon2id

ARGON_MEMORY=65536
ARGON_TIME=3
ARGON_PARALLELISM=4

BCRYPT_ROUNDS=12

PBKDF2_ITERATIONS=600000

Configuration file:

module.exports={

argon2:{
memoryCost:
Number(process.env.ARGON_MEMORY),

timeCost:
Number(process.env.ARGON_TIME),

parallelism:
Number(process.env.ARGON_PARALLELISM)

},


bcrypt:{
rounds:
Number(process.env.BCRYPT_ROUNDS)
}

};

7. Migrating bcrypt Users to Argon2id

You don't need to reset every password.

Migration flow:

User Login

      |

Check bcrypt hash

      |

Password correct?

      |

Generate Argon2id hash

      |

Replace old hash

Example:

if(await bcrypt.compare(password,user.password)){


const newHash =
await argon2.hash(
password,
ARGON_CONFIG
);


user.password=newHash;

await user.save();

}

Migration happens automatically.

migration

8. Final Recommendation for Node.js Developers in 2026

New Projects

Use:

Argon2id

Example stack:

Node.js
+
Express
+
PostgreSQL/MongoDB
+
Argon2id
+
JWT/Session
+
MFA

Existing Applications

If you already use bcrypt:

Keep bcrypt

+

Increase cost factor

+

Gradually migrate to Argon2id

Enterprise Applications

If compliance requires it:

PBKDF2-HMAC-SHA256

Final Security Checklist

A production authentication system should have:

βœ… Argon2id/bcrypt/PBKDF2
βœ… Unique salt per password
βœ… Rate limiting
βœ… Account lockout protection
βœ… MFA support
βœ… Password breach detection
βœ… Secure session management
βœ… HTTPS everywhere

final

Conclusion

For Node.js applications in 2026:

Argon2id is the default choice for new systems.

bcrypt remains reliable for existing applications, while PBKDF2 continues to be useful where compliance standards require it.

The best implementation is not only choosing a strong hashing algorithm but also correctly configuring it, monitoring performance, and combining it with other authentication security layers.

πŸ“° Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.