Cryptographically secure salt generation functionality with configurable rounds for controlling computation cost. Provides both synchronous and asynchronous APIs with callback and Promise support.
Synchronously generates a cryptographically secure salt with configurable rounds.
/**
* Synchronously generates a salt.
* @param rounds Number of rounds to use, defaults to 10 if omitted (range: 4-31)
* @returns Resulting salt string in bcrypt format
* @throws Error if a random fallback is required but not set
*/
function genSaltSync(rounds?: number): string;Usage Examples:
import { genSaltSync } from "bcryptjs";
// Generate salt with default rounds (10)
const salt1 = genSaltSync();
console.log(salt1); // "$2b$10$N9qo8uLOickgx2ZMRZoMye"
// Generate salt with custom rounds
const salt2 = genSaltSync(12);
console.log(salt2); // "$2b$12$X8qo9uLOickgx2ZMRZoMye"
// Use in password hashing
const salt = genSaltSync(10);
const hash = hashSync("myPassword", salt);Asynchronously generates a cryptographically secure salt using Promises.
/**
* Asynchronously generates a salt.
* @param rounds Number of rounds to use, defaults to 10 if omitted
* @returns Promise with resulting salt
*/
function genSalt(rounds?: number): Promise<string>;Usage Examples:
import { genSalt, hash } from "bcryptjs";
// Generate salt with default rounds
const salt1 = await genSalt();
console.log(salt1); // "$2b$10$N9qo8uLOickgx2ZMRZoMye"
// Generate salt with custom rounds
const salt2 = await genSalt(12);
console.log(salt2); // "$2b$12$X8qo9uLOickgx2ZMRZoMye"
// Complete async password hashing workflow
async function hashPassword(password, rounds = 10) {
try {
const salt = await genSalt(rounds);
const hash = await hash(password, salt);
return hash;
} catch (error) {
console.error("Password hashing failed:", error);
throw error;
}
}
// Usage in Express.js route
app.post('/register', async (req, res) => {
const { username, password } = req.body;
try {
const salt = await genSalt(12);
const hashedPassword = await hash(password, salt);
const user = await createUser({
username,
hashedPassword
});
res.json({ success: true, userId: user.id });
} catch (error) {
res.status(500).json({ error: "Registration failed" });
}
});Asynchronously generates a salt with default rounds using callback API.
/**
* Asynchronously generates a salt.
* @param callback Callback receiving the error, if any, and the resulting salt
*/
function genSalt(callback: Callback<string>): void;Usage Examples:
import { genSalt } from "bcryptjs";
// Basic callback usage with default rounds
genSalt((err, salt) => {
if (err) {
console.error("Salt generation failed:", err);
return;
}
console.log("Salt generated:", salt);
// Continue with password hashing...
});Asynchronously generates a salt with specified rounds using callback API.
/**
* Asynchronously generates a salt.
* @param rounds Number of rounds to use, defaults to 10 if omitted
* @param callback Callback receiving the error, if any, and the resulting salt
*/
function genSalt(rounds: number, callback: Callback<string>): void;Usage Examples:
import { genSalt, hash } from "bcryptjs";
// Callback with custom rounds
genSalt(12, (err, salt) => {
if (err) {
console.error("Salt generation failed:", err);
return;
}
console.log("Salt generated:", salt);
// Continue with password hashing
hash("myPassword", salt, (err, hash) => {
if (err) {
console.error("Hashing failed:", err);
return;
}
console.log("Password hashed:", hash);
});
});
// Node.js callback-style user registration
function registerUser(username, password, callback) {
genSalt(10, (err, salt) => {
if (err) {
return callback(err);
}
hash(password, salt, (err, hash) => {
if (err) {
return callback(err);
}
saveUser({ username, hash }, callback);
});
});
}bcryptjs generates salts in the standard bcrypt format:
$2b$[rounds]$[salt]$2b$: bcrypt algorithm identifier (version 2b)[rounds]: Number of iterations, zero-padded (04-31)[salt]: 22-character base64-encoded random saltExamples:
$2b$10$N9qo8uLOickgx2ZMRZoMye (10 rounds)
$2b$12$X8qo9uLOickgx2ZMRZoMye (12 rounds)
$2b$04$A1qo8uLOickgx2ZMRZoMye (4 rounds - minimum)
$2b$31$Z9qo8uLOickgx2ZMRZoMye (31 rounds - maximum)// These are automatically corrected
genSaltSync(2); // Becomes 4 rounds
genSaltSync(50); // Becomes 31 rounds| Rounds | Approximate Time | Security Level | Use Case |
|---|---|---|---|
| 4 | ~1ms | Minimal | Testing only |
| 8 | ~16ms | Low | Low-security applications |
| 10 | ~100ms | Good | Standard web applications |
| 12 | ~400ms | High | Sensitive applications |
| 15 | ~3-4s | Very High | High-value targets |
| 20 | ~100s | Extreme | Long-term storage |
// Development/testing environment
const devSalt = await genSalt(4);
// Production web application
const prodSalt = await genSalt(10);
// High-security financial application
const secureSalt = await genSalt(12);
// Long-term password storage
const archivalSalt = await genSalt(15);bcryptjs uses the following sources for cryptographically secure randomness:
setRandomFallback)// If neither Web Crypto nor Node.js crypto is available
import { setRandomFallback } from "bcryptjs";
// Set a cryptographically secure fallback
setRandomFallback((length) => {
// Return array of `length` cryptographically secure random bytes
// This is critical for security - must use secure random source!
return secureRandomBytes(length);
});// Good: Generate new salt for each password
async function hashMultiplePasswords(passwords) {
const hashes = [];
for (const password of passwords) {
const salt = await genSalt(10); // New salt each time
const hash = await hash(password, salt);
hashes.push(hash);
}
return hashes;
}
// Bad: Reusing the same salt (vulnerable to rainbow tables)
async function hashMultiplePasswordsBad(passwords) {
const salt = await genSalt(10); // Same salt for all
const hashes = [];
for (const password of passwords) {
const hash = await hash(password, salt); // DON'T DO THIS
hashes.push(hash);
}
return hashes;
}// Synchronous error handling
try {
const salt = genSaltSync(10);
console.log("Salt generated:", salt);
} catch (error) {
if (error.message.includes("random fallback")) {
console.error("No secure random source available");
// Set up fallback or use different environment
} else {
console.error("Salt generation failed:", error);
}
}
// Asynchronous Promise error handling
try {
const salt = await genSalt(10);
console.log("Salt generated:", salt);
} catch (error) {
console.error("Salt generation failed:", error);
}
// Callback error handling
genSalt(10, (err, salt) => {
if (err) {
console.error("Salt generation failed:", err);
return;
}
console.log("Salt generated:", salt);
});// Pre-generate salts for batch operations
async function preGenerateSalts(count, rounds = 10) {
const salts = [];
const promises = [];
for (let i = 0; i < count; i++) {
promises.push(genSalt(rounds));
}
return Promise.all(promises);
}
// Use appropriate rounds for your use case
const rounds = process.env.NODE_ENV === 'production' ? 12 : 8;
const salt = await genSalt(rounds);