Zwykle działa to tak:
Powiedz, że Twoje hasło to „baseball”. Mógłbym po prostu przechowywać to w stanie surowym, ale każdy, kto zdobędzie moją bazę danych, otrzyma hasło. Więc zamiast tego robię na nim hash SHA1 i otrzymuję to:
$ echo -n baseball | sha1suma2c901c8c6dea98958c219f6f2d038c44dc5d362
Teoretycznie niemożliwe jest odwrócenie skrótu SHA1. Ale idź wyszukaj w Google dokładnie ten ciąg, a nie będziesz mieć problemu z odzyskaniem oryginalnego hasła.
Ponadto, jeśli dwóch użytkowników w bazie danych ma to samo hasło, to będą mieć ten sam skrót SHA1. A jeśli jeden z nich ma wskazówkę do hasła, która mówi spróbuj „baseball”
- cóż, teraz wiem, czym są oba hasła użytkowników.
Więc zanim go zhaszujemy, dołączamy unikalny ciąg. To nie jest sekret , po prostu coś wyjątkowego. A co z WquZ012C
. Więc teraz haszujemy ciąg WquZ012Cbaseball
. To oznacza to:
c5e635ec235a51e89f6ed7d4857afe58663d54f5
Przeszukanie w Google tego ciągu nic nie daje (z wyjątkiem być może tego strona), więc teraz coś jest. A jeśli person2 również używa „baseball” jako swojego hasła, używamy innej soli i otrzymujemy inny hash.
Oczywiście, aby przetestować swoje hasło, musisz wiedzieć, co to za sól. Więc musimy to gdzieś przechowywać. Większość implementacji po prostu umieszcza to w tym miejscu za pomocą skrótu, zwykle z pewnym ogranicznikiem. Spróbuj tego, jeśli masz zainstalowane openssl
:
[tylerl ~] $ openssl passwd -1Password: baseballVerifying - Password: baseball $ 1 $ oaagVya9 $ NMvf1IyubxEYvrZTRSLgk0
To daje nam hash przy użyciu standardowej biblioteki crypt
. Więc nasz skrót to $ 1 $ oaagVya9 $ NMvf1IyubxEYvrZTRSLgk0
: to w rzeczywistości 3 sekcje oddzielone $
. Zastąpię separator spacją, aby był bardziej przejrzysty:
$ 1 $ oaagVya9 $ NMvf1IyubxEYvrZTRSLgk0 1 oaagVya9 NMvf1IyubxEYvrZTRSLgk0
Jeśli uruchomię proces znowu dostaję zupełnie inny haszysz z inną solą. W tym przykładzie istnieje około 10 14 sposobów przechowywania tego jednego hasła. Wszystkie z nich dotyczą hasła „baseball”:
$ 1 $ 9XsNo9.P $ kTPuyvrHqsJJuCci3zLwL. $ 1 $ nLEOCtx6 $ uSnz6PF8q3YuUhB3rLTC3 / $ 1 $ / jZJXTF3 $ WfDukpe. U $ KR0jkhpeb1sz.UIqvfYOR.
Ale jeśli celowo określę sól, którą chcę sprawdzić, odzyskam oczekiwany wynik:
[ tylerl ~] $ openssl passwd -1 -salt oaagVya9Hasło: baseballVerifying - Hasło: baseball $ 1 $ oaagVya9 $ NMvf1IyubxEYvrZTRSLgk0
I to jest test, który przeprowadzam, aby sprawdzić, czy hasło jest poprawne. Znajdź przechowywany hash dla użytkownika, znajdź zapisaną sól, ponownie uruchom ten sam hash używając zapisanej soli, sprawdź, czy wynik jest zgodny z oryginalnym hashem.
Implementing This Yourself
Żeby było jasne, ten post nie jest przewodnikiem po implementacji. Nie posolaj MD5 i nie nazywaj go dobrym. To za mało w dzisiejszym klimacie ryzyka. Zamiast tego będziesz chciał uruchomić iteracyjny proces, który uruchamia funkcję haszującą tysiące razy. Było to wyjaśniane w innym miejscu wiele razy, więc nie będę tutaj omawiać „dlaczego” .
Jest kilka dobrze ugruntowanych i zaufane możliwości zrobienia tego:
crypt : Funkcja, której użyłem powyżej, jest starszą wersją mechanizmu haszowania haseł unix crypt
wbudowanego we wszystkie Systemy operacyjne Unix / Linux. Oryginalna (oparta na DES) wersja jest strasznie niepewna; nawet o tym nie myśl. Ten, który pokazałem (oparty na MD5) jest lepszy, ale nadal nie powinien być używany. Późniejsze warianty, w tym warianty SHA-256 i SHA-512, powinny być rozsądne. Wszystkie najnowsze warianty implementują wiele rund haszów.
-
bcrypt : Wersja Blowfish crypt kod> wezwanie funkcjonalne wspomniane powyżej. Wykorzystuje fakt, że Blowfish ma bardzo kosztowny proces konfiguracji klucza i przyjmuje parametr „koszt”, który odpowiednio wydłuża czas konfiguracji klucza.
-
PBKDF2 : ("Funkcja wyprowadzania klucza opartego na haśle w wersji 2") Stworzona do tworzenia silnych kluczy kryptograficznych z prostych haseł, jest to jedyna wymieniona tutaj funkcja, która faktycznie ma RFC. Uruchamia konfigurowalną liczbę rund, a każda runda haszuje hasło i wynik poprzedniej rundy. Pierwsza runda używa soli. Warto zauważyć, że jego pierwotnym przeznaczeniem jest tworzenie silnych kluczy , a nie przechowywanie haseł , ale nakładanie się celów sprawia, że jest to również godne zaufania rozwiązanie. Jeśli nie miałeś dostępnych bibliotek i byłeś zmuszony do implementacji czegoś od zera, jest to najłatwiejsza i najlepiej udokumentowana opcja. Chociaż, oczywiście, korzystanie z dobrze sprawdzonej biblioteki jest zawsze najlepsze.
-
scrypt : niedawno wprowadzony system zaprojektowany szczególnie trudne do wdrożenia na dedykowanym sprzęcie. Oprócz wymagania wielu rund funkcji mieszającej, scrypt ma również bardzo duży stan pamięci roboczej, aby zwiększyć zapotrzebowanie na pamięć RAM dla implementacji. Chociaż jest bardzo nowy i w większości niesprawdzony, wygląda co najmniej tak samo bezpieczny jak inne i prawdopodobnie najbezpieczniejszy z nich wszystkich.