Utility Coder
← Back to Blog
Security12 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)

  1. Minimum length: 8 characters (12+ recommended)
  2. Maximum length: At least 64 characters
  3. No composition rules: Don't force special characters
  4. Check against breached passwords
  5. No periodic rotation unless compromised
  6. 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

  1. Using MD5/SHA1 for password hashing
  2. Not using salt (bcrypt/argon2 handle this)
  3. Storing passwords in logs
  4. Sending passwords via email
  5. 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

Conclusion

Password security requires proper generation, secure hashing, and following modern standards. Always use established libraries and stay updated on security best practices.

Share this article