Last updated
NIST-Aligned Modern Password Policy
Following current NIST SP 800-63B guidelines:
PASSWORD POLICY — Modern (NIST-Aligned)
Effective: March 2024 | Version: 2.0
REQUIREMENTS:
Minimum length: 15 characters
Maximum length: 128 characters (do not truncate)
Character types: No complexity requirements
Spaces: Allowed
Unicode: Allowed
PROHIBITED:
✗ Passwords found in breach databases (checked via Have I Been Pwned)
✗ Dictionary words as the entire password
✗ Repetitive patterns (aaaa, 1234, abcd)
✗ Context-specific words (company name, username, service name)
NOT REQUIRED:
✗ Mandatory periodic changes (unless breach is suspected)
✗ Complexity rules (uppercase, numbers, special chars)
✗ Password hints
Traditional Enterprise Password Policy
Complexity-based policy for organizations with legacy compliance requirements:
PASSWORD POLICY — Enterprise Standard
Effective: March 2024 | Version: 3.1
REQUIREMENTS:
Minimum length: 12 characters
Maximum length: 64 characters
Must contain at least:
✓ 1 uppercase letter (A-Z)
✓ 1 lowercase letter (a-z)
✓ 1 digit (0-9)
✓ 1 special character (!@#$%^&*()_+-=[]{}|;:,.<>?)
HISTORY: Cannot reuse last 12 passwords
EXPIRATION: Change every 90 days
LOCKOUT: 5 failed attempts → 15-minute lockout
EXAMPLES:
Compliant: MyP@ssw0rd2024!
Non-compliant: password123 (no uppercase, no special char)
Non-compliant: ALLCAPS123! (no lowercase)
PCI DSS Password Requirements
Payment Card Industry Data Security Standard requirements:
PCI DSS v4.0 Password Requirements (Requirement 8.3):
Minimum length: 12 characters (or 8 if MFA is required)
Complexity: Must contain both numeric and alphabetic characters
History: Cannot reuse last 4 passwords
Expiration: Change every 90 days (or use MFA)
Lockout: Lock after 10 failed attempts
Lockout duration: Minimum 30 minutes or until admin unlocks
Additional requirements:
- Unique passwords for each user
- No group/shared accounts for system access
- First-use and reset passwords must be changed immediately
- Passwords must be protected with strong cryptography (bcrypt, Argon2)
HIPAA Password Policy
Healthcare organizations must protect ePHI with appropriate access controls:
HIPAA Technical Safeguard — Password Policy
Minimum length: 8 characters (12+ recommended)
Complexity: Uppercase, lowercase, digit, special character
Expiration: 90 days maximum
History: Cannot reuse last 6 passwords
Lockout: 3-5 failed attempts → account lockout
Inactivity: Auto-logout after 15 minutes of inactivity
Audit requirements:
- Log all login attempts (success and failure)
- Log password changes
- Review access logs quarterly
- Terminate access within 24 hours of employee departure
Account Lockout Policy Options
Balancing security against denial-of-service risk:
Option 1: Hard lockout (high security, DoS risk)
After 5 failed attempts: Account locked
Unlock: Admin action required or 30-minute timeout
Risk: Attacker can lock out legitimate users
Option 2: Progressive delay (recommended for most apps)
Attempt 1-3: No delay
Attempt 4: 5-second delay
Attempt 5: 30-second delay
Attempt 6+: 5-minute delay (doubles each attempt)
Benefit: Slows brute force without enabling DoS
Option 3: CAPTCHA after failures
After 3 failed attempts: Require CAPTCHA
No lockout — CAPTCHA prevents automated attacks
Best for: Public-facing login forms
Breach Database Check Implementation
Using Have I Been Pwned API with k-anonymity (privacy-preserving):
// Check if password appears in breach database
async function isPasswordBreached(password) {
// Hash the password with SHA-1
const hash = await sha1(password);
const prefix = hash.substring(0, 5);
const suffix = hash.substring(5).toUpperCase();
// Send only first 5 chars of hash (k-anonymity)
const response = await fetch(
`https://api.pwnedpasswords.com/range/${prefix}`
);
const hashes = await response.text();
// Check if our hash suffix appears in the results
return hashes.includes(suffix);
}
// Usage in registration
if (await isPasswordBreached(newPassword)) {
return error('This password has appeared in a data breach. Please choose a different password.');
}
Password Policy for Different User Types
Different roles may have different requirements:
Standard Users:
Minimum length: 12 characters
MFA: Optional (encouraged)
Expiration: None (unless breach detected)
Privileged Users (admins, developers):
Minimum length: 16 characters
MFA: Required
Expiration: 90 days
Separate admin account required (no shared credentials)
Service Accounts:
Minimum length: 32 characters (randomly generated)
MFA: N/A (use API keys or certificates instead)
Rotation: Every 90 days or on personnel change
Storage: Secrets manager (never in code or config files)
Multi-Factor Authentication Impact on Policy
MFA allows relaxing some password requirements:
Without MFA:
Minimum length: 15 characters
Expiration: 90 days
Lockout: 5 attempts
With MFA required:
Minimum length: 8 characters (PCI DSS allows this)
Expiration: Not required
Lockout: 10 attempts (attacker needs both factors)
Rationale: With MFA, a compromised password alone is insufficient
for unauthorized access. The second factor provides the critical
additional protection that allows relaxing password requirements.
Password Storage Requirements
The policy should specify how passwords are stored:
REQUIRED: Use adaptive hashing algorithms
✓ Argon2id (recommended — winner of Password Hashing Competition)
✓ bcrypt (widely supported, proven)
✓ scrypt (memory-hard, good alternative)
PROHIBITED:
✗ MD5 (broken)
✗ SHA-1 (broken for passwords)
✗ SHA-256 without salt (vulnerable to rainbow tables)
✗ Reversible encryption (passwords must not be recoverable)
✗ Plaintext storage
Recommended bcrypt settings:
Cost factor: 12 (adjust to keep hashing time ~100-300ms)
Salt: Automatically generated per password by bcrypt