All your favorite passwords are already known to hackers. Even if a website hashes them, tools like hashcat can process leaked data to reveal the password or find an alternative one. See Hash collision and Rainbow table for more details
Think this happens rarely? Check yourself and find out how much of your data is already in the hands of attackers at haveibeenpwned.com and how many of your passwords are compromised
Suppose the application has to use passwords. As a result, it is necessary to store the password hash for comparison. The key point here is to do it correctly
Hash function
Below is an example of almost reliable password processing logic
string = Application Secret + password + User ID
iterations = 1_000_000
additional iterations = Int(string) % iterations
Hash (string, 1_000_000 + additional iterations)
Application Secret – is an additional secret (peppering) used alongside a password at the application level. If password hashes are leaked, attackers will need not only the list of passwords but also the specific secret used by each user. Requirements: UUID v4 minimum, the secret is stored exclusively in the application configuration, not in the database (good example – HashiCorp Vault)
There are two types of data leaks: external and internal. External leaks include SQL injection, database backup leaks, and insecure design. Internal leaks occur when an employee falls victim to phishing attacks or deliberately shares sensitive information
Password – refers to the user's access code, which is straightforward. You may require a minimum of 12 characters
User ID – is a unique identifier that ensures different users, even with identical passwords, generate distinct hashes regardless of the hashing function used.
If an attacker gains access to the database and avoids guessing secrets or iteration counts, they can exploit common passwords by registering new users or changing their own password, then comparing their hashes with those of real users.
To prevent this, it is crucial that the User ID is also a UUID v4
Iterations – If you use the SHA-256 hashing function, it works quickly and efficiently not only for you but also for attackers. To make password hashing more secure, good algorithms perform multiple iterations of hashing, sometimes up to a million times, depending on the chosen method
Keep in mind that your site uses only a CPU for processing, while attackers often use GPUs 😉 (of cause if the attacker has your hashes on its device!)
Additional iterations – mean the number of hashing rounds should be high and tied to the specific string being hashed. This forces attackers to calculate the iterations separately for each user
In the example above, the range is from one to two million iterations
Although this is a small range, it adds complexity for enumerate attempts
Hash – is the most important aspect. Choose carefully.
A good starting point for research is the Password Storage Cheat Sheet.
For example, PBKDF2 already suggests using a unique salt for each password, that is why I didn’t mention additionally the salt here (anyway - user id looks like as a salt)
However, I would not disregard the previous points, as an additional inexpensive layer of protection is always beneficial. But anything that can be delegated to the hashing function – should be delegated
Modern algorithms like Argon2 and scrypt use not only iterations (computational complexity) but also memory hardness
This makes them much more resistant to GPU-based brute force attacks compared to algorithms like PBKDF2 or especially SHA-256 (which is not designed for direct password hashing)
Password hash storage
Have you often seen databases storing both user profile data and password hashes together? I've always wondered why. User data is accessed much more frequently than password hashes. Since hashes are long, this could slightly slow down read operations
It seems more logical to store password hashes in a separate storage system from user data. This approach enhances security in case of a data breach, as password hashes are safer when separated from the main database