Home/Blog/What are rainbow tables and how do salts protect against them?
Cybersecurity

What are rainbow tables and how do salts protect against them?

Learn about rainbow tables used in password attacks, how they work, and how cryptographic salts provide protection against this common attack method.

By Inventive HQ Team
What are rainbow tables and how do salts protect against them?

Understanding Rainbow Tables

A rainbow table is a massive precomputed lookup table used in password cracking attacks. Instead of attempting to crack passwords through brute force (trying combinations of letters, numbers, and symbols until one works), attackers use rainbow tables to instantly look up the hash value and retrieve the corresponding password. Rainbow tables represent one of the most efficient password cracking techniques available—but cryptographic salts provide a robust defense.

Understanding rainbow tables and salts is essential for anyone involved in cybersecurity, system administration, or software development. Properly salting passwords is fundamental to modern password security and a critical component of protecting against the most efficient password attacks.

How Hashing Works

Before understanding rainbow tables, it's essential to understand hashing—the cryptographic function that stores passwords securely.

The Hashing Process

When users register or change passwords, systems don't store the actual password. Instead, they:

  1. Take the password: User enters "MyPassword123"
  2. Apply hash function: System runs password through SHA-256 or similar hashing algorithm
  3. Store the hash: System stores the resulting hash (e.g., "5a7f6b8d9c2e1f4a7b8c9d0e1f2a3b4c5d6e7f8")
  4. Discard password: Original password is never stored

Benefits of hashing:

  • If database is stolen, attackers get hashes, not passwords
  • Hash is one-directional (can't reverse to get original password)
  • Even tiny password changes produce completely different hashes

Authentication Process

When users log in:

  1. User enters password
  2. System hashes the entered password using the same algorithm
  3. System compares the generated hash to the stored hash
  4. If they match, authentication succeeds

This approach means the system never actually "knows" the password—it only verifies that what the user entered produces the same hash.

Rainbow Tables: How They Work

The Attack Concept

While hashing is secure for protecting stored passwords, it has a vulnerability: the same password always produces the same hash. This means attackers can precompute hashes.

Traditional brute force attack:

  1. Stolen hash value: "5a7f6b8d9c2e1f4a7b8c9d0e1f2a3b4c5d6e7f8"
  2. Try password: "password1" → Hash: "3a9d7b2c..." → Doesn't match
  3. Try password: "password2" → Hash: "8c2e1f4a..." → Doesn't match
  4. Repeat thousands of times until a match is found
  5. Time-consuming process, especially for strong passwords

Rainbow table attack:

  1. Stolen hash value: "5a7f6b8d9c2e1f4a7b8c9d0e1f2a3b4c5d6e7f8"
  2. Look up hash in precomputed table
  3. Instantly get: "MyPassword123"
  4. Attack succeeds in milliseconds

Building Rainbow Tables

Creating a rainbow table involves:

  1. Generate candidate passwords: All possible passwords up to certain length

    • All lowercase letters: "a" through "zzz..."
    • With numbers: "0" through "999..."
    • With symbols: "!#$%..." combinations
    • Dictionary words and variations
  2. Compute hashes: Run each candidate through hashing function

    • Hash("password1") = "a1b2c3d4e5f6..."
    • Hash("password2") = "f6e5d4c3b2a1..."
    • Billions of hashes computed and stored
  3. Store in table: Create massive lookup table

    • Key: Hash value
    • Value: Original password
    • Organized for fast lookup
  4. Use for attacks: When stolen hashes obtained, look up instantly

    • Find hash "a1b2c3d4..." in table
    • Instantly retrieve "password1"

Rainbow Table Scale

The computational effort is extraordinary:

MD5 Hashes:

  • Table size: ~160 GB for all 6-8 character passwords
  • Coverage: ~99.9% success rate on 6-character passwords
  • Lookup time: ~1-2 seconds per password

SHA-1 Hashes:

  • More computational effort than MD5
  • Table size: ~1 TB+ for comprehensive coverage
  • Still effective for shorter passwords

Available resources:

  • Free: Online rainbow table services (RainbowCrack, tables available for download)
  • Commercial: Precomputed tables for various algorithms and password lengths
  • Custom: Organizations build custom tables for their specific targets

Real-World Attack Scenario

Scenario: Social media breach

  1. Hackers break into social media company database
  2. Steal password hashes (10 million users)
  3. Download publicly available rainbow table (MD5 hashes)
  4. Feed stolen hashes through table lookup
  5. Within hours, recover passwords for millions of users
  6. Use compromised credentials to access email, banking, other services

This happened in real breaches—LinkedIn (2012), Adobe (2013), Yahoo (2014)—where weak hashing allowed rainbow table attacks on stolen password databases.

Why Rainbow Tables Are So Effective

Speed: Looking up a hash in a precomputed table takes microseconds, compared to seconds or minutes for brute force.

Offline attack: Attackers don't need to attack live systems. They can use rainbow tables on a stolen database offline.

Reusability: The same table works against any password that was originally used to create the hashes.

Universal: If multiple users have the same password, they'll have the same hash. One lookup reveals all matching accounts.

Cryptographic Salts: The Defense

A salt is random data added to passwords before hashing. This simple but brilliant technique completely defeats rainbow tables.

How Salts Work

Without salt:

Password: "MyPassword123"
Hash function: SHA-256
Result: "5a7f6b8d9c2e1f4a7b8c9d0e1f2a3b4c5d6e7f8"

Same password always produces same hash

With salt:

Password: "MyPassword123"
Salt: "j7k3m9p2" (random)
Hash function: SHA-256("MyPassword123j7k3m9p2")
Result: "9c2e1f4a7b8c5d6e7f8a9b0c1d2e3f4a5b6c7d8e"

Different salt produces different hash

Key Properties of Salts

Randomness: Each password gets a unique, random salt

  • User 1: salt = "a1b2c3d4"
  • User 2: salt = "x9y8z7w6" (different, even same password)
  • Same password with different salts = different hashes

Storage: Salt is stored with the hash

  • Stored format: salt:hash
  • Example: j7k3m9p2:5a7f6b8d9c2e1f4a7b8c9d0e1f2a3b4c5d6e7f8
  • Salt doesn't need to be secret (it's stored alongside hash)

Length: Longer salts are stronger

  • Minimum: 8-12 bytes (64-96 bits)
  • Recommended: 16+ bytes (128+ bits)
  • Longer salts make rainbow tables exponentially larger

Uniqueness: Each password should have its own salt

  • Prevents two users with same password having same hash
  • Prevents recognizing when multiple users have same password

Why Salts Defeat Rainbow Tables

The multiplication problem:

Without salt:

  • One rainbow table covers all users
  • Hash "5a7f6b8d..." could be "password123"
  • All instances of "password123" produce same hash
  • One table lookup breaks all matching passwords

With salt (8-byte salt):

  • For each possible hash value, there are 2^64 possible salts
  • Would need 2^64 times more storage
  • Instead of 160 GB table, need exabytes (not feasible)
  • Cannot precompute all possibilities

Practical effect:

  • Rainbow tables become useless
  • Attackers must use brute force instead (slow)
  • Even brute force requires trying salt combinations
  • A strong salt makes password cracking impractical

Implementation Best Practices

Proper Salting

Generate unique random salt:

import os
import hashlib

# Generate random salt (16 bytes = 128 bits)
salt = os.urandom(16)

# Hash password with salt
password = "MyPassword123"
salted_hash = hashlib.sha256(password.encode() + salt).digest()

# Store both salt and hash
stored = salt + salted_hash

Verify password:

# Extract salt from storage
stored_data = retrieve_from_database()
salt = stored_data[:16]  # First 16 bytes are salt
stored_hash = stored_data[16:]  # Rest is hash

# Hash entered password with extracted salt
entered_password = "MyPassword123"
entered_hash = hashlib.sha256(entered_password.encode() + salt).digest()

# Compare hashes
if entered_hash == stored_hash:
    print("Password correct!")

Recommended Hashing Algorithms

Not recommended (no salt support):

  • MD5: Too fast, allows rainbow tables
  • SHA-1: Too fast, weak collision resistance
  • SHA-256: Fast (bad for passwords), no salt support in standard form

Recommended:

  • bcrypt: Includes salt generation, built-in iteration

    import bcrypt
    hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
    # Automatically handles salt
    
  • Argon2: Modern, memory-hard, resistant to GPU attacks

    from argon2 import PasswordHasher
    ph = PasswordHasher()
    hashed = ph.hash(password)
    
  • PBKDF2: Industry standard, simple, configurable

    from passlib.hash import pbkdf2_sha256
    hashed = pbkdf2_sha256.encrypt(password)
    

Key difference: These algorithms:

  1. Automatically generate and handle salts
  2. Use key stretching (iterations) to slow hashing
  3. Resist GPU and ASIC acceleration
  4. Are specifically designed for password hashing

Salt Length and Strength

Salt size guidelines:

  • Minimum: 8 bytes (64 bits)
  • Recommended: 16 bytes (128 bits)
  • Modern best practice: 16+ bytes

Why longer is better:

  • 8-byte salt: 2^64 = 18 billion combinations (feasible for attackers with resources)
  • 16-byte salt: 2^128 = 340 undecillion combinations (infeasible to precompute)

Randomness requirements:

  • Salt must be cryptographically random, not predictable
  • Use secure random generators:
    • Python: os.urandom()
    • Java: SecureRandom
    • C#: RNGCryptoServiceProvider
    • JavaScript: crypto.getRandomValues()

Historical Salt Mistakes

The Problem with Weak Hashing

LinkedIn Breach (2012):

  • Used unsalted SHA-1 hashing
  • 6.5 million password hashes stolen
  • Rainbow tables used to recover 90% of passwords within hours
  • Lesson: Salts are mandatory

Adobe Breach (2013):

  • Used unsalted MD5 hashing
  • 150 million password hashes compromised
  • Rainbow tables recovered millions of passwords
  • Lesson: Even adding salts requires strong algorithms

Yahoo Breach (2014):

  • Used weak hashing algorithms
  • 3 billion account hashes compromised
  • Many passwords recovered through rainbow tables
  • Lesson: Weak algorithms defeat even salt protection

Modern Approach

Today's best practices:

  1. Use modern hashing algorithm (Argon2 preferred)
  2. Include random salt for each password
  3. Use key stretching (iterations) to slow hashing
  4. Use memory-hard algorithms resistant to GPU/ASIC attacks
  5. Regularly audit password storage practices

Testing Your Defenses

Organizations should:

  1. Audit password hashing: Review what algorithm is used

    • Check: "What hashing algorithm are we using for passwords?"
    • Good: Bcrypt, Argon2, PBKDF2
    • Bad: MD5, SHA-1, unsalted algorithms
  2. Verify salt implementation: Confirm salts are used properly

    • Check: "Does each password have a unique salt?"
    • Verify: "Are salts at least 16 bytes?"
    • Confirm: "Are salts cryptographically random?"
  3. Test password validation: Verify same password produces different hashes

    • Create two accounts with same password
    • Extract hashes from database
    • Confirm hashes are different (indicates unique salts)
  4. Check iteration counts: Verify key stretching is configured

    • Bcrypt: Default factor 12 (2^12 = 4096 iterations)
    • PBKDF2: Minimum 100,000 iterations (preferably 600,000+)
    • Argon2: Verify memory cost and time cost configured

Conclusion

Rainbow tables are a powerful password cracking technique that would render passwords insecure if salts weren't used. Salts solve this problem by adding randomness to each password before hashing, making precomputed attacks infeasible. Combined with strong hashing algorithms like bcrypt and Argon2, proper salting ensures that even if attackers steal password hashes, they cannot efficiently recover the original passwords.

For developers, system administrators, and security professionals, implementing proper password salting is non-negotiable. It's one of the most effective and well-understood defenses in cryptography, and the cost of implementation is minimal compared to the security benefit. Organizations that fail to properly salt passwords leave themselves vulnerable to rainbow table attacks—a lesson learned through countless high-profile breaches.

Need Expert Cybersecurity Guidance?

Our team of security experts is ready to help protect your business from evolving threats.