Optimized bcrypt in plain JavaScript with zero dependencies, with TypeScript support.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Password verification functionality for comparing plain text passwords against bcrypt hashes. Provides both synchronous and asynchronous APIs with optional progress tracking for time-intensive operations.
Synchronously tests a password against a bcrypt hash.
/**
* Synchronously tests a password against a hash.
* @param password Password to test
* @param hash Hash to test against
* @returns true if matching, otherwise false
*/
function compareSync(password: string, hash: string): boolean;Usage Examples:
import { compareSync } from "bcryptjs";
// Basic password verification
const hash = "$2b$10$N9qo8uLOickgx2ZMRZoMye2Z8WSdtXvKLhXfV.O/JZ4MYxvmq4dS6";
const isValid = compareSync("myPassword", hash);
console.log(isValid); // true or false
// Login verification function
function verifyLogin(username, password, storedHash) {
try {
const isValid = compareSync(password, storedHash);
if (isValid) {
console.log(`Login successful for ${username}`);
return true;
} else {
console.log(`Invalid password for ${username}`);
return false;
}
} catch (error) {
console.error("Password verification failed:", error);
return false;
}
}Asynchronously tests a password against a hash using Promises.
/**
* Asynchronously tests a password against a hash.
* @param password Password to test
* @param hash Hash to test against
* @returns Promise resolving to boolean result
*/
function compare(password: string, hash: string): Promise<boolean>;Usage Examples:
import { compare } from "bcryptjs";
// Basic async verification
const hash = "$2b$10$N9qo8uLOickgx2ZMRZoMye2Z8WSdtXvKLhXfV.O/JZ4MYxvmq4dS6";
const isValid = await compare("myPassword", hash);
console.log(isValid); // true or false
// Async login verification
async function verifyLoginAsync(username, password, storedHash) {
try {
const isValid = await compare(password, storedHash);
if (isValid) {
console.log(`Login successful for ${username}`);
return { success: true, user: username };
} else {
console.log(`Invalid password for ${username}`);
return { success: false, error: "Invalid credentials" };
}
} catch (error) {
console.error("Password verification failed:", error);
return { success: false, error: "Verification failed" };
}
}
// Express.js middleware example
app.post('/login', async (req, res) => {
const { username, password } = req.body;
const user = await getUserByUsername(username);
if (!user) {
return res.status(401).json({ error: "Invalid credentials" });
}
const isValid = await compare(password, user.hashedPassword);
if (isValid) {
// Generate JWT token or session
res.json({ success: true, token: generateToken(user) });
} else {
res.status(401).json({ error: "Invalid credentials" });
}
});Asynchronously tests a password against a hash using callback-based API with optional progress tracking.
/**
* Asynchronously tests a password against a hash.
* @param password Password to test
* @param hash Hash to test against
* @param callback Callback receiving the error, if any, and the result
* @param progressCallback Optional callback for progress updates (0.0 - 1.0)
*/
function compare(
password: string,
hash: string,
callback?: Callback<boolean>,
progressCallback?: ProgressCallback
): void;Usage Examples:
import { compare } from "bcryptjs";
// Basic callback usage
const hash = "$2b$10$N9qo8uLOickgx2ZMRZoMye2Z8WSdtXvKLhXfV.O/JZ4MYxvmq4dS6";
compare("myPassword", hash, (err, result) => {
if (err) {
console.error("Comparison failed:", err);
return;
}
console.log("Password is valid:", result);
});
// With progress callback for high-round hashes
compare("myPassword", highRoundHash,
(err, result) => {
if (err) {
console.error("Comparison failed:", err);
return;
}
console.log("Verification completed:", result);
},
(progress) => {
console.log(`Verification progress: ${Math.round(progress * 100)}%`);
}
);
// Node.js callback-style authentication
function authenticateUser(username, password, callback) {
getUserHash(username, (err, storedHash) => {
if (err) {
return callback(err);
}
compare(password, storedHash, (err, isValid) => {
if (err) {
return callback(err);
}
callback(null, isValid);
});
});
}bcryptjs implements constant-time comparison to prevent timing attacks. The verification time remains consistent regardless of whether the password matches or not.
The comparison functions validate the hash format before processing:
// Valid bcrypt hash format
const validHash = "$2b$10$N9qo8uLOickgx2ZMRZoMye2Z8WSdtXvKLhXfV.O/JZ4MYxvmq4dS6";
// Invalid formats will cause comparison to return false
const invalidHash1 = "plaintext"; // Not a hash
const invalidHash2 = "$2a$10$invalid"; // Malformed hash
const invalidHash3 = ""; // Empty string
// All these will return false safely
console.log(compareSync("password", invalidHash1)); // false
console.log(compareSync("password", invalidHash2)); // false
console.log(compareSync("password", invalidHash3)); // false// Synchronous error handling
function safeCompareSync(password, hash) {
try {
return compareSync(password, hash);
} catch (error) {
console.error("Password comparison failed:", error);
return false; // Fail securely
}
}
// Asynchronous error handling
async function safeCompareAsync(password, hash) {
try {
return await compare(password, hash);
} catch (error) {
console.error("Password comparison failed:", error);
return false; // Fail securely
}
}
// Callback error handling
function safeCompareCallback(password, hash, done) {
compare(password, hash, (err, result) => {
if (err) {
console.error("Password comparison failed:", err);
return done(null, false); // Fail securely
}
done(null, result);
});
}// Express.js authentication middleware
const authenticateToken = async (req, res, next) => {
const { password } = req.body;
const user = req.user; // From previous middleware
try {
const isValid = await compare(password, user.hashedPassword);
if (!isValid) {
return res.status(401).json({ error: "Invalid password" });
}
next();
} catch (error) {
res.status(500).json({ error: "Authentication failed" });
}
};
// React login form handler
const handleLogin = async (username, password) => {
try {
const response = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password })
});
if (response.ok) {
const data = await response.json();
localStorage.setItem('token', data.token);
return { success: true };
} else {
return { success: false, error: 'Invalid credentials' };
}
} catch (error) {
return { success: false, error: 'Login failed' };
}
};