A Complete Guide - NodeJS bcrypt for Password Hashing
Explaining in Detail and Showing Important Information for NodeJS bcrypt for Password Hashing
Why Use bcrypt?
- Salting: Automatically generates a unique salt for each password hash, ensuring that even identical passwords will have different hashes.
- Cost Factor: Adjustable cost factor (work factor) allows balancing between performance and security. Increasing the cost factor exponentially increases the time required to compute a hash.
- Resilience: Built-in protection against rainbow table attacks due to its adaptive nature and unique salting mechanism.
Installation of bcrypt in NodeJS:
To integrate bcrypt
into your NodeJS project, use npm (Node Package Manager) to install it:
npm install bcrypt
Basic Usage Example:
Here’s how you can use bcrypt
to hash passwords and compare them with user input during login.
- Password Hashing:
const bcrypt = require('bcrypt');
async function hashPassword(password) {
const saltRounds = 10; // Cost factor - can be adjusted
try {
const hash = await bcrypt.hash(password, saltRounds);
console.log("Hashed Password:", hash);
return hash;
} catch (err) {
console.error("Error hashing password:", err);
}
}
// Example usage
hashPassword('mySuperSecretPassword');
- saltRounds: Represents the computational cost. A higher number means better security but slower hashing. Commonly used values range from 10 to 12.
- Password Comparison:
async function comparePassword(plainPassword, hashedPassword) {
try {
const match = await bcrypt.compare(plainPassword, hashedPassword);
console.log("Passwords match:", match);
return match;
} catch (err) {
console.error("Error comparing passwords:", err);
}
}
// Example usage
const storedHash = '$2b$10$KIXlB5Smoy5CDxroQPtSPAeTJbBPV5ZpmZSEBXTp0D8MoPCEdkiwi'; // Example hash
comparePassword('mySuperSecretPassword', storedHash);
Important Considerations:
- Cost Factor: Strike a balance between security and performance. A higher cost factor ensures better security but comes at the cost of slower hashing times.
- Salt Management:
bcrypt
automatically handles salt generation and storage within the hash. No need for manual salt management. - Future-Proofing: Regularly review and adjust your cost factor as hardware capabilities evolve. Keeping the cost factor updated ensures that your application remains secure against advances in computational power.
Best Practices:
- Always use a library like
bcrypt
for hashing passwords. - Avoid storing passwords in plaintext or using outdated hashing methods such as MD5.
- Regularly audit and update your dependencies for security patches.
- Use environment variables to manage sensitive data such as secret keys or configuration settings.
Online Code run
Step-by-Step Guide: How to Implement NodeJS bcrypt for Password Hashing
Step 1: Set Up Your Node.js Environment
First, create a new directory for your project and set up a new Node.js project using npm init -y
. This will create a package.json
file with default settings.
mkdir bcrypt-example
cd bcrypt-example
npm init -y
Step 2: Install Dependencies
Install the bcrypt
package which we'll use for hashing passwords:
npm install bcrypt
Step 3: Create a Simple Script to Hash Passwords
Create a JavaScript file named hashPassword.js
. This script will hash a given password.
// hashPassword.js
const bcrypt = require('bcrypt');
const saltRounds = 10;
const plainPassword = 'mySuperSecurePassword';
bcrypt.hash(plainPassword, saltRounds, (err, hash) => {
if (err) {
console.error('Error during hashing:', err);
return;
}
console.log('Hashed Password:', hash);
});
Explanation:
saltRounds
: This indicates the cost factor in bcrypt; it specifies the number of rounds the key derivation function is processed.bcrypt.hash()
: This is an asynchronous method that takes three parameters: the plaintext password, the salt rounds, and a callback to handle the result.
Step 4: Run the Hash Password Script
Run the script to see the hashed version of the password:
node hashPassword.js
You should see something like this:
Hashed Password: $2b$10$iJH6YpQFZV17GzN5Y8S1W.9jU6Xwv2J2GqZBfG6Xwv2J2GqZBfG6Xwv2
Note: The actual output will be different each time because the salt is different for each run.
Step 5: Create a Simple Script to Verify Hashed Passwords
Create another JavaScript file named verifyPassword.js
. This script will verify a hashed password against a plaintext password.
// verifyPassword.js
const bcrypt = require('bcrypt');
const plainPassword = 'mySuperSecurePassword';
// Use the hash generated from the previous step
const hashedPassword = '$2b$10$iJH6YpQFZV17GzN5Y8S1W.9jU6Xwv2J2GqZBfG6Xwv2J2GqZBfG6Xwv2';
bcrypt.compare(plainPassword, hashedPassword, (err, result) => {
if (err) {
console.error('Error during verification:', err);
return;
}
if (result) {
console.log('Password verified successfully!');
} else {
console.log('Invalid password.');
}
});
Explanation:
bcrypt.compare()
: This is an asynchronous method that checks if the given plaintext password matches the hashed password. It takes three parameters: the plain text password, the hashed password, and a callback that returns whether the passwords match.
Step 6: Run the Verify Password Script
Run the script to verify the password:
node verifyPassword.js
You should see something like this:
Password verified successfully!
If you try to verify with an incorrect password, you'll see:
Invalid password.
Example Using Promises
Since bcrypt
provides promise-based methods, let's rewrite the hashing and verifying scripts using promises.
Hash Password with Promise:
// hashPasswordWithPromise.js
const bcrypt = require('bcrypt');
const saltRounds = 10;
const plainPassword = 'mySuperSecurePassword';
async function hashPassword() {
try {
const hash = await bcrypt.hash(plainPassword, saltRounds);
console.log('Hashed Password:', hash);
} catch (err) {
console.error('Error during hashing:', err);
}
}
hashPassword();
Verify Password with Promise:
// verifyPasswordWithPromise.js
const bcrypt = require('bcrypt');
const plainPassword = 'mySuperSecurePassword';
// Use the hash generated from the previous step
const hashedPassword = '$2b$10$iJH6YpQFZV17GzN5Y8S1W.9jU6Xwv2J2GqZBfG6Xwv2J2GqZBfG6Xwv2';
async function verifyPassword() {
try {
const result = await bcrypt.compare(plainPassword, hashedPassword);
if (result) {
console.log('Password verified successfully!');
} else {
console.log('Invalid password.');
}
} catch (err) {
console.error('Error during verification:', err);
}
}
verifyPassword();
Running the Revised Scripts
Run the revised scripts using Node.js:
node hashPasswordWithPromise.js
node verifyPasswordWithPromise.js
The outputs should be the same as before but now using promise-based async/await syntax.
Summary
In this step-by-step example, you learned how to:
- Set up a Node.js environment.
- Install the
bcrypt
library. - Hash a password using
bcrypt.hash()
. - Verify a hashed password using
bcrypt.compare()
. - Use promise-based calls for hashing and verifying passwords.
This should provide a solid foundation to start using bcrypt in your Node.js applications for secure password storage.
Login to post a comment.