Security•12 min read
Password Security and Generation: Developer Best Practices
Learn secure password generation, hashing algorithms, entropy calculation, and modern security standards for protecting user credentials.
By Andy Pham
Password Security and Generation: Developer Best Practices
Password security is fundamental to application security. This guide covers password generation, hashing, and modern security practices.
Password Entropy
Entropy measures password strength in bits:
Entropy = log2(C^L)
Where:
C = number of possible characters
L = password length
Entropy Examples
| Password Type | Character Set | Length | Entropy |
|---|---|---|---|
| Numeric PIN | 10 | 4 | 13 bits |
| Lowercase | 26 | 8 | 38 bits |
| Mixed case | 52 | 8 | 46 bits |
| All printable | 95 | 12 | 79 bits |
Recommended minimum: 60+ bits of entropy
Secure Password Generation
JavaScript Implementation
function generatePassword(length = 16, options = {}) {
const {
lowercase = true,
uppercase = true,
numbers = true,
symbols = true
} = options;
let charset = '';
if (lowercase) charset += 'abcdefghijklmnopqrstuvwxyz';
if (uppercase) charset += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if (numbers) charset += '0123456789';
if (symbols) charset += '!@#$%^&*()_+-=[]{}|;:,.<>?';
const array = new Uint32Array(length);
crypto.getRandomValues(array);
return Array.from(array, x => charset[x % charset.length]).join('');
}
// Generate strong password
const password = generatePassword(20, {
lowercase: true,
uppercase: true,
numbers: true,
symbols: true
});
Python Implementation
import secrets
import string
def generate_password(length=16, use_symbols=True):
charset = string.ascii_letters + string.digits
if use_symbols:
charset += string.punctuation
return ''.join(secrets.choice(charset) for _ in range(length))
# Generate password
password = generate_password(20)
Password Hashing
Never store passwords in plain text!
Recommended Algorithms
| Algorithm | Work Factor | Memory | Recommended |
|---|---|---|---|
| bcrypt | Cost factor | Low | Yes |
| Argon2id | Time/Memory | High | Best |
| scrypt | N/r/p | High | Yes |
| PBKDF2 | Iterations | Low | Acceptable |
bcrypt Example
const bcrypt = require('bcrypt');
// Hash password
async function hashPassword(password) {
const saltRounds = 12; // Adjust based on security needs
return await bcrypt.hash(password, saltRounds);
}
// Verify password
async function verifyPassword(password, hash) {
return await bcrypt.compare(password, hash);
}
// Usage
const hash = await hashPassword('mySecurePassword');
const isValid = await verifyPassword('mySecurePassword', hash);
Argon2 Example
const argon2 = require('argon2');
// Hash with Argon2id (recommended)
async function hashPassword(password) {
return await argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 65536, // 64 MB
timeCost: 3,
parallelism: 4
});
}
// Verify
async function verifyPassword(password, hash) {
return await argon2.verify(hash, password);
}
Password Policies
Modern Recommendations (NIST 800-63B)
- Minimum length: 8 characters (12+ recommended)
- Maximum length: At least 64 characters
- No composition rules: Don't force special characters
- Check against breached passwords
- No periodic rotation unless compromised
- Allow paste in password fields
Breach Detection
const crypto = require('crypto');
async function isPasswordBreached(password) {
// Use Have I Been Pwned API (k-anonymity)
const hash = crypto.createHash('sha1')
.update(password)
.digest('hex')
.toUpperCase();
const prefix = hash.slice(0, 5);
const suffix = hash.slice(5);
const response = await fetch(
`https://api.pwnedpasswords.com/range/${prefix}`
);
const text = await response.text();
return text.includes(suffix);
}
Client-Side Security
Password Strength Meter
function calculateStrength(password) {
let score = 0;
// Length
if (password.length >= 8) score += 1;
if (password.length >= 12) score += 1;
if (password.length >= 16) score += 1;
// Character variety
if (/[a-z]/.test(password)) score += 1;
if (/[A-Z]/.test(password)) score += 1;
if (/[0-9]/.test(password)) score += 1;
if (/[^a-zA-Z0-9]/.test(password)) score += 1;
// Patterns (reduce score)
if (/(.)\1{2,}/.test(password)) score -= 1; // Repeated chars
if (/^[a-zA-Z]+$/.test(password)) score -= 1; // Letters only
return Math.max(0, Math.min(5, score));
}
Common Mistakes
- Using MD5/SHA1 for password hashing
- Not using salt (bcrypt/argon2 handle this)
- Storing passwords in logs
- Sending passwords via email
- Using predictable reset tokens
Security Checklist
- Use Argon2id or bcrypt for hashing
- Minimum 12 character passwords
- Check against breached password databases
- Implement rate limiting on login
- Use HTTPS for all auth endpoints
- Implement account lockout after failed attempts
- Log authentication events (without passwords)
Try Our Tools
- Password Generator - Generate secure passwords
- Random String Generator - Create random strings
- UUID Generator - Generate unique identifiers
Conclusion
Password security requires proper generation, secure hashing, and following modern standards. Always use established libraries and stay updated on security best practices.