Salt in security is a random data string added to a password before hashing to prevent attackers from using precomputed hash tables. It ensures each password hash is unique, even if passwords are identical. This protects stored credentials from being cracked via dictionary or rainbow table attacks.
When a user creates a password, the system generates a unique salt-typically 16 bytes or more-and combines it with the password. The resulting string is then passed through a cryptographic hash function like SHA-256 or bcrypt. The salt and the final hash are both stored in the database. During login, the system retrieves the salt, appends it to the entered password, hashes the result, and compares it to the stored hash.
This process prevents attackers from cracking multiple accounts simultaneously. Without salt, identical passwords produce identical hashes. With salt, even if two users choose "password123," their stored hashes differ due to different salts. This forces attackers to brute-force each account individually.
Consider a user who sets "sunshine" as their password. Without salt, the system computes a hash like:
SHA-256("sunshine") = 5d41402abc4b2a76b9719d91101e2e9e
If another user picks the same password, they get the same hash. An attacker can look up this hash in a rainbow table-a precomputed list of common passwords and their hashes-and instantly recover the password.
Now suppose the system adds a random salt. For the first user, the salt is "xk7mPq9zTn2vRw5y." The system computes:
SHA-256("sunshine" + "xk7mPq9zTn2vRw5y") = f3c8e1a2d4b6f9e0c1a3d5b7e9f2a4c8
For the second user, the salt is "rY4tNp8kMj3nQw7z." The hash becomes:
SHA-256("sunshine" + "rY4tNp8kMj3nQw7z") = 9d2a4f1c3e5b7a8d6f4e2c1b9a7d5f3e
Even though both passwords are "sunshine," the hashes differ. An attacker cannot use a single rainbow table entry to crack both accounts.
Salts are typically generated using cryptographically secure random number generators. They should be long enough to avoid collisions-16 bytes (128 bits) is standard. Some systems use longer salts, especially in high-security environments.
There are two main approaches to storing salt:
Modern password hashing algorithms like bcrypt, scrypt, and Argon2 include salt generation and storage automatically. These functions are designed to be slow and memory-intensive, making brute-force attacks impractical. For example, bcrypt uses a built-in salt field in the output format:
$2b$12$ZiK8gXuF2JGvW7kqZfVJUOqD3fZ6jY3qR6jA3d6lK3o3qR6jA3d6lK3o
The segment after $2b$12$ is the salt. The algorithm handles salt creation and verification internally.
Many developers assume that using a hash function like SHA-256 is sufficient for securing passwords. That's incorrect. SHA-256 is fast and deterministic-ideal for checksums, but poor for password storage. It lacks built-in salting and is vulnerable to GPU-based brute-force attacks.
A common mistake is reusing the same salt across all users. This defeats the purpose. If an attacker compromises the database and learns the salt, they can precompute a rainbow table for that salt and crack all passwords at once. The National Institute of Standards and Technology (NIST) explicitly warns against this in SP 800-63B, stating that salts must be unpredictable and unique per credential.
Another error is storing the salt alongside the hash in plaintext. While this is acceptable-because the salt is not secret-it must not be reused. Some legacy systems store the salt in a separate column, which increases complexity and risk of misconfiguration. Best practice is to embed the salt within the hash output, as in bcrypt.
In 2012, LinkedIn suffered a breach exposing 167 million user records. The company had stored passwords using SHA-1 without salt. Attackers used rainbow tables to crack 117 million passwords in hours.
Had LinkedIn used per-user salts, the attack would have required 117 million individual brute-force attempts-each taking minutes on consumer hardware. The computational cost would have been prohibitive. As it stood, attackers cracked passwords like "linkedin123" and "admin" in seconds.
After the breach, LinkedIn adopted bcrypt with random salts. This raised the bar for attackers. Even today, many companies still fail to implement proper salting. According to a 2023 report by the Open Web Application Security Project (OWASP), 34% of web applications still use unsalted or weakly salted password hashing.
Confusion often arises between salt, pepper, and hash. Here's how they differ:
| Term | Definition | Use Case |
|---|---|---|
| Salt | Random data added to a password before hashing. Stored with the hash. | Prevents rainbow table attacks. Ensures uniqueness. |
| Pepper | A secret value added to the password before hashing. Not stored with the hash. Must be kept secure. | Additional layer of defense. If breached, the pepper must be known to crack passwords. |
| Hash | One-way function that transforms input into a fixed-length output. | Used to store passwords securely. Should be slow and memory-hard. |
Pepper is not a substitute for salt. It's an extra layer. If you use both, the process becomes:
This makes cracking much harder-even if an attacker gets the database, they still need the pepper.
I once audited a small SaaS platform that used MD5 with a static salt. The salt was hardcoded in the source code. I found it in a GitHub repo. Within 10 minutes, I rebuilt a rainbow table for that salt and cracked 40% of the passwords. The team had no idea they were using a predictable salt. They later switched to bcrypt with per-user salts and disabled code-level salt storage.
Follow these guidelines to ensure proper use:
os.urandom() in Python or SecureRandom in Java).Understanding what is salt in security isn't just technical-it's foundational. Without it, even the strongest passwords are vulnerable. Salting turns a weak system into a resilient one. It's not a luxury. It's a necessity.