This repository demonstrates my understanding of proper password storage and authentication using industry-standard cybersecurity practices. The focus is on password hashing, salting, and secure storage mechanisms.
When users create accounts, they provide passwords that must be stored for later authentication. The critical security challenge is: How do you store passwords securely so that even if your database is compromised, user accounts remain protected?
The answer lies in cryptographic hashing with salt - a one-way transformation that makes it computationally infeasible to recover the original password from what's stored.
A salt is a random, unique value that is combined with a password before hashing. Each password gets its own unique salt, which is then stored alongside (or within) the hash.
Without Salt:
- If two users have the same password, they'll have identical hashes
- Attackers can use rainbow tables (pre-computed hash tables) to quickly reverse common passwords
- A single compromised password hash can reveal multiple user accounts
With Salt:
- Even identical passwords produce different hashes
- Rainbow table attacks become impossible (each hash is unique)
- Attackers must brute-force each password individually
- The computational cost of attacks increases exponentially
- Cryptographically Secure Randomness: Salts must be generated using cryptographically secure random number generators (CSPRNG), not predictable sequences
- Sufficient Length: Modern standards recommend at least 16 bytes (128 bits) of random data
- Uniqueness: Every password must have a unique salt - never reuse salts
- Storage: The salt must be stored with the hash (often embedded in the hash string itself)
Password hashing is a one-way cryptographic function that transforms a password into a fixed-length string of characters. The key property is that it's computationally infeasible to reverse the process - you cannot derive the original password from the hash.
MD5, SHA1, SHA256 are cryptographic hash functions, but they're designed for speed, not security:
- Too Fast: Modern hardware can compute billions of hashes per second
- Vulnerable to Brute-Force: Attackers can quickly test millions of password combinations
- No Built-in Salt: Requires manual salt management
- No Cost Factor: Cannot be made slower as computers get faster
Example Attack Scenario:
- Attacker steals a database with SHA256 password hashes
- With modern GPUs, they can test 1+ billion password combinations per second
- Common passwords can be cracked in seconds or minutes
bcrypt, Argon2, and scrypt are specifically designed for password hashing:
- Slow by Design: Intentionally computationally expensive to make brute-force attacks impractical
- Adaptive Cost Factor: Can be made slower as computing power increases
- Built-in Salt Management: Automatically handles salt generation and storage
- Time-Tested: Widely audited and used in production systems
- Cost Factor: A configurable parameter that determines how many iterations the algorithm performs
- Increasing Cost: As computers get faster, you can increase the cost factor to maintain security
- Future-Proof: The same algorithm remains secure over time by adjusting the cost factor
Example:
- Cost factor 10: ~100ms per hash (acceptable for login)
- Cost factor 12: ~400ms per hash (recommended default)
- Cost factor 14: ~1.6s per hash (high security)
This means an attacker trying to brute-force a password would need:
- Cost factor 12: ~400ms Γ millions of attempts = years or decades
- Compare to SHA256: ~0.0001ms Γ millions of attempts = minutes or hours
When storing password hashes, you must store:
- The Hash: The result of the hashing function
- The Salt: The unique random value used (often embedded in the hash)
- Metadata: Algorithm identifier, cost factor, etc. (often in the hash string format)
Modern password hashing libraries (like bcrypt) store everything in a single string:
$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYqBWVHxkd0
β β β β β
β β β β ββ Hash (31 chars)
β β β ββββββββββββββββββββββββ Salt (22 chars)
β β ββββββββββββββββββββββββββββ Cost factor (12)
β βββββββββββββββββββββββββββββββ Algorithm version (2b)
βββββββββββββββββββββββββββββββββββ Format identifier ($)
This format ensures:
- All necessary information is stored together
- The algorithm and parameters are preserved
- Verification can be performed correctly
Database Security:
- Use parameterized queries to prevent SQL injection
- Encrypt database connections (TLS/SSL)
- Implement proper access controls
- Regular security audits
File-Based Storage:
- Secure file permissions (restrict read access)
- Consider encryption at rest for sensitive files
- Regular backups with secure storage
General Principles:
- Never store plaintext passwords
- Never store passwords in logs or error messages
- Use environment variables for database credentials
- Implement proper access controls and monitoring
- User Input: User provides a password
- Salt Generation: System generates a unique, random salt
- Hashing: Password + salt are hashed using bcrypt (or similar)
- Storage: Only the hash (containing salt) is stored
- Discard: Original password is immediately discarded from memory
- User Input: User provides username and password
- Retrieve Hash: System retrieves the stored hash for that username
- Extract Salt: System extracts the salt from the stored hash
- Re-hash: System hashes the provided password with the extracted salt
- Compare: System compares the newly generated hash with the stored hash
- Constant-Time Comparison: Comparison is done in constant time to prevent timing attacks
- Result: Authentication succeeds or fails
- One-Way Function: Even with the hash and salt, you cannot reverse-engineer the password
- Unique Salts: Each password requires individual brute-force attempts
- Slow Hashing: Makes brute-force attacks computationally infeasible
- Constant-Time Comparison: Prevents timing attacks that could reveal information
- Use bcrypt, Argon2, or scrypt for password hashing
- Generate unique salts for every password using cryptographically secure randomness
- Use appropriate cost factors (12+ for bcrypt is recommended)
- Store only hashes - never plaintext passwords
- Use constant-time comparison functions for password verification
- Implement proper error handling that doesn't reveal information
- Secure your storage (encrypted connections, proper access controls)
- Never store passwords in plaintext
- Don't use MD5, SHA1, or SHA256 for password hashing (they're too fast)
- Don't reuse salts across different passwords
- Don't use weak random number generators for salt generation
- Don't reveal whether usernames exist in error messages
- Don't log passwords in any form (plaintext or hash)
- Don't hardcode credentials in source code
What they are: Pre-computed tables of common passwords and their hashes
Why salts prevent them: Each password has a unique salt, making pre-computed tables useless
Protection: Unique salts for every password
What they are: Systematically trying every possible password combination
Why adaptive hashing prevents them: Slow hashing makes brute-force computationally infeasible
Protection: bcrypt/Argon2 with appropriate cost factors
What they are: Measuring response times to infer information about password correctness
Why constant-time comparison prevents them: Response time doesn't reveal information
Protection: Use constant-time comparison functions
What they are: Using leaked credentials from other breaches
Why proper hashing helps: Even if your database is compromised, passwords can't be easily recovered
Additional protection: Rate limiting, account lockout, 2FA
This project demonstrates understanding of:
- Cryptographic Hashing: One-way functions for password transformation
- Salt Generation: Unique random values for password protection
- Adaptive Hashing: Algorithms designed to resist brute-force attacks
- Secure Storage: Proper handling of sensitive authentication data
- Attack Mitigation: Understanding and preventing common attack vectors
- Security by Design: Building security into the system from the ground up
This implementation follows:
- OWASP Password Storage Cheat Sheet: Industry-standard guidelines for password security
- NIST Guidelines: Recommendations for password handling and storage
- bcrypt Specification: Widely-used adaptive hashing algorithm
- Security Best Practices: Defense-in-depth approach to authentication security
This repository is for educational and demonstration purposes to showcase understanding of password security concepts. While it implements security best practices, production systems require additional considerations such as:
- Rate limiting and brute-force protection
- Two-factor authentication (2FA)
- Account lockout mechanisms
- Security monitoring and logging
- Regular security audits
- HTTPS/TLS encryption
- Comprehensive input validation
Purpose: Demonstrate understanding of proper password hashing, salting, and secure storage practices in cybersecurity.