A rainbow table is a precomputed data structure that lets an attacker reverse unsalted password hashes back into plaintext by trading storage space for computation time, using chains of alternating hash and reduction operations. It is a classic attack against databases that store fast, unsalted hashes. The single most effective defense is simple: add a unique random salt to every password and use a slow hashing algorithm, which renders rainbow tables useless.
Key takeaways
- A rainbow table reverses unsalted hashes using precomputed chains, saving storage via a time-memory tradeoff.
- It relies on the target hashes being unsalted and computed with a fast algorithm.
- Reduction functions turn hashes back into candidate plaintexts, forming the chains that compress the data.
- A unique random salt per password completely defeats rainbow tables.
- Slow, memory-hard hashes like bcrypt and Argon2 make both precomputation and guessing impractical.
- Rainbow tables are largely historical against modern best-practice storage but still endanger legacy systems.
What is a rainbow table?
A rainbow table is a way for attackers to crack password hashes efficiently. Instead of guessing passwords one at a time when they steal a hash database, they do enormous computation in advance and store the results cleverly, so that later they can look up or quickly recover the plaintext behind a stolen hash.
The naive version of this idea is a plain lookup table that stores the hash of every possible password alongside the password. That works but requires astronomical storage for any realistic password space. The rainbow table is a refinement that dramatically reduces storage requirements at the cost of some extra computation during lookup, making precomputation feasible for larger password spaces.
How do rainbow tables work?
The clever part of a rainbow table is that it does not store every hash. Instead it stores chains. Building a chain alternates two operations:
- Start with a candidate password and compute its hash.
- Apply a reduction function that maps that hash to a new candidate password.
- Hash that new candidate, reduce again, and repeat many times.
The table stores only the first and last value of each chain, not the thousands of intermediate values. To crack a stolen hash, the attacker applies reductions and hashes to see if the value eventually matches a stored chain endpoint; if it does, they regenerate that chain to find the plaintext. Real rainbow tables use a sequence of different reduction functions across the chain, which reduces collisions and is the origin of the colorful name.
What is the time-memory tradeoff?
Rainbow tables sit between two extremes. At one end, pure brute force uses almost no storage but must compute every guess fresh each time. At the other, a complete lookup table uses no computation at lookup time but demands impossible amounts of storage.
| Approach | Storage | Lookup computation |
|---|---|---|
| Brute force | Minimal | Very high |
| Full lookup table | Enormous | Minimal |
| Rainbow table | Moderate | Moderate |
The rainbow table is the balanced middle: it accepts some computation during cracking in exchange for storing far less than a complete table. This tradeoff is what made precomputed attacks practical against larger password spaces.
Why do salts defeat rainbow tables?
A rainbow table is built for a specific hashing scheme with no salt. Every entry assumes that a given password always produces the same hash. A unique, random salt per password shatters that assumption.
With per-user salts, the same password produces a different hash for every user, because the salt is mixed in before hashing. To attack a salted database, an attacker would need a separate rainbow table precomputed for every distinct salt value. When salts are long and random, the number of possible salts is astronomically large, so building tables for all of them is infeasible. The precomputation advantage vanishes, and the attacker is forced back to attacking each password individually. This is precisely why salting is mandatory.
Are rainbow tables still a threat today?
Against systems following current best practices, rainbow tables are largely obsolete. Unique salts eliminate their precomputation advantage, and slow, memory-hard algorithms like bcrypt and Argon2 make even individual guessing expensive. A properly stored password is effectively immune to this class of attack.
However, the threat persists wherever legacy or careless storage remains. Databases that store unsalted hashes, or hashes made with fast general-purpose functions, are still vulnerable, and breaches of such systems continue to expose passwords. The lesson is that rainbow tables did not become irrelevant on their own; they were neutralized by defenses that developers must actually apply. Skip those defenses and the old attack works again.
How do you protect against rainbow tables?
Protection is well understood and straightforward:
- Always salt. Use a unique, cryptographically random salt for every password so no two hashes are precomputable together.
- Use a slow, purpose-built hash. Choose bcrypt, scrypt, or Argon2 rather than a fast general-purpose digest.
- Prefer memory-hard functions. Argon2id and scrypt raise the cost for parallel-hardware attackers.
- Let libraries manage salting. Modern password hashes generate and embed the salt automatically, reducing mistakes.
- Add defense in depth. Rate limiting, breach monitoring, and multi-factor authentication reduce the impact even if hashes leak.
Following these makes rainbow tables and their descendants ineffective against your stored credentials.
How do rainbow tables differ from plain hash lookups?
It helps to keep the terminology straight. A lookup table or dictionary attack stores precomputed hashes for a list of candidate passwords and matches stolen hashes directly against them; it is simple but storage-heavy. A rainbow table is a space-optimized version that stores chains rather than every hash, using reduction functions to compress the data at the cost of extra work during cracking.
Both attacks share the same fatal weakness: they assume unsalted hashes. Whether an attacker uses a giant lookup table or a compact rainbow table, a unique salt per password forces them to redo all their work for each individual account, which is exactly the outcome secure password storage is designed to guarantee.
Frequently asked questions
What is the difference between a rainbow table and a lookup table?
A plain lookup table stores every precomputed hash directly. A rainbow table uses chains and reduction functions to store far less data, trading some computation for much less storage.
Do rainbow tables work against salted hashes?
No. A unique random salt per password means an attacker would need a separate table for every salt, which is infeasible, so salting defeats rainbow tables.
Are rainbow tables still a threat?
They are largely obsolete against properly salted, slow-hashed passwords, but they remain effective against unsalted or fast-hashed password databases.
What is a reduction function?
It maps a hash back into a candidate plaintext so that alternating hashing and reduction builds a chain of values, which is what compresses the stored data.
How do I protect against rainbow tables?
Use a unique random salt per password and a slow, purpose-built hash like bcrypt or Argon2. That combination makes precomputation useless.
Why does hashing speed matter for rainbow tables?
Fast hashes let attackers build and traverse tables cheaply. Slow, salted algorithms make both precomputation and per-guess attacks prohibitively expensive.
Can rainbow tables crack any hash?
Only within a defined character set and length that was precomputed. Passwords outside that space, or protected by unique salts, are not covered by a given table.