Załóżmy, że mamy przechować jakiś sekret. Nie do końca chodzi nam o to, by był on przechowywany w sposób nieodwracalny, natomiast zdecydowanie chcemy mieć możliwość sprawdzenia, czy określona osoba ten sekret zna.
Tak, dokładnie o to chodzi również przy przechowywaniu haseł. Tu absolutnym standardem jest przechowywanie sekretów (haseł) w formie skrótu (hasha), który powinien być nie tylko nieodwracalny, ale również kosztowny do wyliczenia. Wszystko po to, by atak brute force był jak najbardziej kosztowny (obliczeniowo). Są jednak takie przypadki, w których przestrzeń możliwych wartości sekretu jest na tyle niewielka, że podejście oparte na wykorzystaniu hasha po prostu się nie sprawdza.
W takich przypadkach lepszym podejściem jest zaszyfrowanie sekretu i przechowywanie go w takiej postaci. Oczywiście szyfrowanie musi być wykonane z głową, bo inaczej skutki są takie: Anatomy of a password disaster - Adobe's giant-sized cryptographic blunder.
Jeśli szyfrowanie zostanie zrealizowane poprawnie, to atak na hasła sprowadzi się do ataku na wykorzystany szyfr. W praktyce oznacza to konieczność odgadnięcia klucza, który ma co najmniej 128 bitów. Powodzenia.
Ale jednocześnie właśnie tu jest problem - system by działać, musi mieć dostęp do tego klucza. Z pewnym prawdopodobieństwem należy więc założyć, że również atakujący będzie miał do niego dostęp (choć w przypadku wspomnianej już wpadki Adobe - klucza najwyraźniej nie udało się zdobyć).
Jaki stąd morał? Warto zastanowić się co chcemy chronić i jaka jest możliwa przestrzeń wartości tego sekretu. W pewnych sytuacjach bardziej bezpiecznym rozwiązaniem będzie wybranie szyfrowania i próba utrudnienia dostępu do klucza.
P.S. W zasadzie dokładnie to samo można osiągnąć przy pomocy tajnego pepper (uzupełniając jawny salt). Oczywiście tutaj należy z kolei zadbać o to, by pepper nie był łatwo dostępny dla atakującego.
P.S2. A przypomniało mi się to w związku z tym: Can hackers decrypt Target's PIN data? Przy okazji - warto zwrócić uwagę na sztuczki zastosowane po to, by uniknąć sytuacji, w której dwa różne PIN szyfrują się do tej samej wartości (wykorzystany jest 3DES w trybie ECB).
Myślę, że w takim wypadku problem jest znacznie większy, niż zły algorytm szyfrowania/hashowania. Wystarczy szybki brute force[1]... Który ciężko sensownie zlimitować, bez narażania użytkowników na proste odcięcie od serwisu.
Szczytem był chyba serwis, w którym podpowiedzią do hasła był dzień tygodnia, w którym się właściciel urodził. W ramach ułatwienia odpowiedź wybierało się z listy rozwijanej. Myślę, że jakbyś się przyjrzał dokładniej serwisom oferującym podpowiedzi, a często wręcz wymagającym ich ustawienia, to znajdziesz tego typu dziur znacznie więcej.
Co do Adobe, to - dopóki klucza nie wykradziono - nie zrobili IMO wielkiego błędu. Po prostu mieli pecha, że baza była ogromna, a wtedy hasła zaczynają się powtarzać. Zrobili po prostu (znacznie) lepszy odpowiednik hashowania bez soli. Jaki procent haseł, i jak słabych, można w ten sposób uzyskać? Jakim nakładem pracy? Myślisz, że będzie wśród nich choć jedno hasło >10 znaków, losowe?
Ale tak, hashowanie w wersji wspomnianej z PS jest znacznie lepsze.
[1] Kiedyś były takie walizki na zamek szyfrowy, zamiast kluczyka (z możliwością ustawienia własnego kodu). Jedną z nich miał mój ojciec. For fun przeleciałem bruteforcem poniżej 30 minut (dwa zamki po 3 pokrętła, więc nawet jedno sprawdzenie/sekundę spokojnie wystarcza).
Podejrzewam, że "dobrych" haseł się nie da odgadnąć. No, chyba, że ktoś się bardzo wykazał w podpowiedzi.