"Tomu se dá snadno zabránit takzvaným solením, při němž se otisky počítají z hesel doplněných o nějakou další hodnotu (sůl), takže i když dva uživatelé budou mít stejné heslo, odpovídající otisky budou odlišné."
Ano, ale jen v případě nekonstantní soli, jinak samozřejmě heslo1 == heslo2 => hash(heslo1.salt) == hash(heslo2.salt).
"Zbývá ještě zmínit bezkoliznost, která zajišťuje, že pro různé vstupy budou vypočítány různé otisky (i drobné změně vstupu by měly odpovídat velké změny výsledného otisku)."
A tady jste smíchal bezkoliznost s jednosměrností.
Nechci být drzý, ale od odborníka na počítačovou bezpečnost bych čekal přesnější vyjadřování.
Třeba v případě přihlašování HTTP DIGEST je sůl konstantní, protože je jí identifikace serveru.
Výhoda rainbow tables je v tom, že už jsou předpočítané. Když je bude muset útočník počítat znova i pro konstantní sůl, reálně je může spočítat jen pro malou množinu hesel, tedy pro slabá a často se opakující hesla.
Ale to je přeci známý fakt, že každý uživatel má jinou sůl, takže to ani není nutné zmiňovat ;) Nebo když už se tedy vůbec solí že by se to fakt implementovalo tak že sůl je konstantní a nejlépe v databázi aby si to útočník mohl předpočítat rainbow tables? No minimálně ho to o nějakou dobu pozdrží. A nezapomínejme že žijeme v době SSD a GPU, a taky pozor na SQL injection a některá exotičtější kódování UTF...