Czy bezpieczniejsze jest wielokrotne hashowanie hasła?

43

Przeczytałem kilka razy, że podczas przechowywania haseł, dobrą praktyką jest „podwójne hashowanie” ciągów (np. Z md5, a następnie sha1, oczywiście oba z solami).

Wydaje mi się, że pierwsze pytanie brzmi: „czy to rzeczywiście jest poprawne?” Jeśli nie, to proszę odrzucić resztę tego pytania :)

Pytam dlatego, że na pierwszy rzut oka powiedziałbym, że ma to sens. Jednak gdy o tym myślę, za każdym razem, gdy skrót jest zmieniany (być może z czymś dodanym), wszystko, co widzę, to zmniejszenie górnej granicy ostatecznej „wyjątkowości” ... związanej z tym początkowe wejście.

Powiem inaczej: mamy liczbę x łańcuchów, które po zszyciu są zredukowane do y możliwych łańcuchów. Oznacza to, że w pierwszym zestawie występują kolizje. Przechodząc teraz od drugiego zestawu do trzeciego, czy nie jest możliwe, aby wystąpiła ta sama rzecz (tj. Kolizje w zbiorze wszystkich możliwych ciągów „y”, które skutkują tym samym hashem w trzecim zbiorze)?

W mojej głowie wszystko, co widzę, to „lejek” dla każdego wywołania funkcji skrótu, „leje” nieskończony zestaw możliwości do zbioru skończonego i tak dalej, ale oczywiście każde wywołanie działa na skończonym zestawie przed nim ustaw nie większy niż wejście.

Może przykład wyjaśni moje wędrówki? Weźmy „hash_function_a”, która da „a” i „b” skrót „1”, a „c” i „d” skrót „2”. Używając tej funkcji do przechowywania haseł, nawet jeśli hasło to „a”, mógłbym użyć hasła „b”.

Weź „hash_function_b”, który da „1” i „2” skrót „3”. Gdybym użył go jako „hash wtórny” po „hash_function_a”, to nawet jeśli hasło to „a”, mógłbym użyć „b”, „c” lub „d”.

Co więcej, rozumiem, że sole powinny być używane, ale tak naprawdę nie zmieniają faktu, że za każdym razem mapujemy wejścia „x” na wyjścia „mniej niż x”. Nie sądzę

Czy ktoś może mi wyjaśnić, czego tu brakuje?

Dzięki!

EDYCJA: dla tego, co jest warte, nie robię tego sam, używam bcrypt. I tak naprawdę nie martwię się, czy jest to przydatne do „zużywania cykli” dla „hakera”. Naprawdę zastanawiam się tylko, czy ten proces zmniejsza „bezpieczeństwo” z punktu widzenia kolizji mieszania.

Narcyz
źródło
2
@ S.Lott: Naprawdę nie rozumiem, jak to odpowiada na rzeczywiste pytanie, ale ... wszystko to mówi albo „nie rób tego sam, użyj tego”, albo „dobrze jest poświęcić czas!”. .. żadna z tych odpowiedzi „czy to rzeczywiście jest bezpieczniejsze”. Znowu, chyba że coś mi umknie.
Narcyz
@MetalMikester: Tak, to był wczorajszy artykuł: thedailywtf.com/Articles/Bulletproof-Encryption.aspx
FrustratedWithFormsDesigner
Nie jest to temat bezpieczeństwa IT, ale wygląda na dobre dopasowanie do kryptografii. W rzeczywistości wygląda bardzo podobnie do tego pytania .
Znam firmę, która chciała używać niesolonej MD5(password). Powiedzieliśmy, że to nie jest bezpieczne, więc zasugerowali użycie MD5(MD5(password))zamiast tego ...
konfigurator
Przyjęta odpowiedź nie jest poprawna!
markus

Odpowiedzi:

27

Jest to bardziej odpowiednie dla security.stackexchange, ale ...

Problem z

hash1(hash2(hash3(...hashn(pass+salt)+salt)+salt)...)+salt)

jest to, że jest on tak silny, jak najsłabsza funkcja skrótu w łańcuchu. Na przykład, jeśli hashn (najbardziej wewnętrzny skrót) powoduje kolizję, cały łańcuch skrótu spowoduje kolizję ( niezależnie od tego, jakie inne skróty są w łańcuchu ).

Byłby silniejszy łańcuch

hash1(hash2(hash3(...hashn(pass + salt) + pass + salt) + pass + salt)...) + pass + salt)

Tutaj unikamy problemu wczesnej kolizji i zasadniczo generujemy sól, która zależy od hasła do końcowego skrótu.

A jeśli jeden krok w łańcuchu koliduje, nie ma to znaczenia, ponieważ w następnym kroku hasło jest ponownie używane i powinno dać inny wynik dla różnych haseł.

maniak zapadkowy
źródło
Tak więc teraz widzę, że dodanie „hasła + soli” jako soli do następnej rundy mieszania może zwiększać ilość „rzeczy”, które mogłyby wejść do lejka, teraz muszę tylko zrozumieć „ile”. Dzięki.
Narcyz
Właściwie myślę, że teraz to rozumiem: poprzez wymuszenie hasła do każdej warstwy haszowania, czy faktycznie zmniejsza liczbę możliwych kolizji, wymagając zasadniczo „hasła kolidującego” i prawdziwego hasła, aby mieć pasujące hasze dla każdego „połączenia” , dobrze? Myślę, że brakowało mi części „wpisz hasło na każdej warstwie”! Dzięki jeszcze raz.
Narcyz
@Narcissus nie ma problemu, a to ma również tę zaletę, że pozwala na słabsze hashy wewnętrzne (o ile skróty zewnętrzne / końcowe są silne), ponieważ hashy wewnętrzne tylko generują sól do następnego przejścia
maniak zapadkowy
szum, myślę, że problem jest nieco większy (i głębszy). Dzięki atakom tęczy możesz po prostu generować tabele z uwzględnieniem wszystkich swoich skrótów, a problem pozostaje.
woliveirajr,
4
@Narcissus: w bardzo krótkiej odpowiedzi: Tak, to nie jest bardziej bezpieczne. Tak, prawdopodobnie jest to jeszcze mniej bezpieczne.
woliveirajr
54

Używanie różnych algorytmów mieszających jest złym pomysłem - raczej zmniejszy entropię niż ją zwiększy.

Jednak przy założeniu, że dysponujesz kryptograficznie silnym algorytmem mieszającym i dobrą solą, zastosowanie tej samej funkcji skrótu kilka razy sprawia, że ​​proces mieszania jest bardziej kosztowny obliczeniowo. Zaletą tego jest to, że gdy inne metody łamania skrótu hasła kończą się niepowodzeniem (zgadywanie, ataki słownikowe, tabele tęczy itp.), A atakujący jest zmuszany do stosowania technik brutalnej siły, potrzeba więcej czasu na wypróbowanie każdego hasła, po prostu dlatego, że muszą częściej stosować tę samą funkcję skrótu. Więc jeśli jedna runda haszowania wymagałaby jednego miesiąca brutalnego forsowania, zastosowanie jej dwanaście razy wydłużyłoby szacowany czas do roku.

Najnowsze algorytmy mieszające, takie jak bcrypt, bazują na tym pomyśle; zawierają parametr kontrolujący złożoność obliczeniową skrótu, dzięki czemu można go skalować wraz z postępem prędkości sprzętowej: gdy sprzęt staje się dwa razy szybszy, zwiększasz złożoność, aby to zrekompensować, a więc czas potrzebny na użycie siły skróty pozostają w przybliżeniu stałe.

tdammers
źródło
2
To poprawna odpowiedź!
markus
@markus: zgodnie z przeczytaną przeze mnie dyskusją jest to poprawne tylko z powodu dodania „i dobrej soli”, do którego odnosi się zaakceptowana odpowiedź, prawda? Dlaczego ta odpowiedź jest poprawna, a odpowiedź zaakceptowana nie?
Narcyz
To poprawna odpowiedź, ponieważ jedynym powodem wielokrotnego zastosowania tej samej funkcji skrótu (sparametryzowanej) jest to, że można użyć tej iteracji, aby dostosować się do szybszego sprzętu. W przeciwnym razie haszowanie nie przyniesie wiele korzyści.
markus
@Narcissus Kluczem jest tutaj entropia. Istnieje różnica między haszowaniem wiele razy przy użyciu tej samej metody a haszowaniem wiele razy przy użyciu różnych metod.
sakisk
3

Nie próbuj pisać własnego schematu mieszania haseł, chyba że jesteś gotów podjąć kurs kryptografii i / lub inżynierii bezpieczeństwa.

Powinieneś użyć dobrze ustalonej implementacji haszowania haseł, która z kolei powinna używać funkcji wyprowadzania klucza ( KDF ), takiej jak PBKDF2, bcrypt, scrypt lub nowszy Argon2.

Dobre KDF obejmują czynnik roboczy, zwykle szereg iteracji, w celu zwiększenia kosztów ataków offline. Można powiedzieć, że te KDF hashują hasło wiele razy, za każdym razem używając tego samego algorytmu. Jak wskazują inni, nie ma sensu stosowanie algorytmu wielokrotnego podsumowania wiadomości.

Erwan Legrand
źródło
1
link https://crackstation.net/hashing-security.htm jest zablokowany przez firewall
gnat
1
@gnat Z jakiegoś powodu brakowało mi komentarza dotyczącego zablokowanego adresu URL. Zamieniłem go na link do wikipedii.
Erwan Legrand
2

Zasadniczo nie trzeba używać więcej niż jednego algorytmu mieszającego.

Co musisz zrobić, to:

Używaj soli: sól nie jest używana tylko po to, aby twoje hasło było bardziej bezpieczne , służy do powstrzymania ataku tęczowego stołu. W ten sposób ktoś będzie miał cięższą pracę, próbując wstępnie obliczyć skrót dla haseł przechowywanych w systemie.

Używaj wielu interakcji: zamiast wykonywać tylko SHA (hasło + sól), wykonaj SHA (SHA (SHA (SHA (SHA (... SHA (hasło + sól)))))). Lub reprezentować w inny sposób:

hash = sha(password + salt)
for i=1 , i=5000, i++ {
    hash = sha(hash + salt);
}

I wreszcie wybierz dobrą funkcję haszującą. SHA, MD5 itp. Nie są dobre, ponieważ są zbyt szybkie . Ponieważ chcesz używać skrótu do ochrony, lepiej użyj wolniejszych skrótów. Spójrz na Bcrypt , PBKDF2 lub Scrypt , na przykład.

edytuj : po spostrzeżeniach spróbujmy zobaczyć kilka punktów (przepraszam, długie wyjaśnienie, aby dojść do końca, ponieważ może to pomóc innym w poszukiwaniu podobnych odpowiedzi):

Jeśli twój system jest bezpieczny, tak jakby nikt nigdy nie uzyskał dostępu do przechowywanego hasła, nie potrzebujesz hasha. Hasło byłoby tajne, nikt go nie dostanie.

Ale nikt nie może zagwarantować, że baza danych z hasłami zostanie skradziona. Kradnij bazę danych, mam wszystkie hasła. Ok, twój system i Twoja firma poniosą wszystkie tego konsekwencje. Możemy więc spróbować uniknąć wycieku tego hasła.

UWAGA, że w tym momencie nie martwimy się atakami online. W przypadku jednego ataku online najlepszym rozwiązaniem jest spowolnienie po złych hasłach, zablokowanie konta po kilku próbach itp. W tym przypadku nie ma znaczenia, w jaki sposób szyfrujesz, hash, przechowujesz itp. Hasło. Atak online polega na spowolnieniu wprowadzania hasła .

Wróćmy do don't let them take my plain passwordsproblemu. Odpowiedź jest prosta: nie przechowuj ich jako zwykłego tekstu. Ok, rozumiem.

Jak tego uniknąć?

Zaszyfruj hasło (?). Ale, jak wiesz, jeśli go zaszyfrujesz, możesz go odszyfrować z powrotem, jeśli masz odpowiedni klucz. I skończysz z problemem „gdzie ukryć” klucz. Hum, nic dobrego, skoro dostali twoją bazę danych, mogą zdobyć twój klucz. Ok, nie używajmy tego.

Kolejne podejście: przekształćmy hasło w coś innego, czego nie można cofnąć, i zapisz je. Aby sprawdzić, czy podane hasło jest prawidłowe, ponownie wykonujemy ten sam proces i sprawdzamy, czy dwie transformowane wartości są zgodne. Jeśli się zgadzają = podano dobre hasło.

Ok, jak dotąd tak dobrze. Użyjmy skrótu MD5 w haśle. Ale ... jeśli ktoś ma naszą zapisaną wartość skrótu hasła, może mieć dużą moc komputera, aby obliczyć skrót MD5 każdego możliwego hasła (brutalna siła), aby mógł znaleźć oryginalne hasło. Lub, co najgorsze, może przechowywać wszystkie MD5 ze wszystkich kombinacji znaków i łatwo znaleźć hasło. Więc wykonaj wiele iteracji, HASH (HASH (HASH ())), aby było trudniej, ponieważ zajmie to więcej czasu.

Ale nawet to można obejść, tęczowy stół został stworzony właśnie w celu przyspieszenia tego rodzaju ochrony.

Użyjmy więc soli. W ten sposób przy każdej interakcji sól jest ponownie używana. Osoba próbująca zaatakować twoje hasła będzie musiała wygenerować tęczową tabelę, biorąc pod uwagę, że sól jest dodawana za każdym razem. A kiedy wygeneruje tęczową tabelę, ponieważ została wygenerowana z jedną solą, będzie musiał ponownie obliczyć dla drugiej soli, więc będzie musiał poświęcić trochę czasu na każde hasło (= każda sól). Sól nie doda „więcej złożoności” do hasła, po prostu sprawi, że atakujący będzie tracił czas na generowanie tęczowej tabeli, jeśli użyjesz jednej soli dla każdego hasła, tabela od jednej soli jest bezużyteczna do innego hasła.

A użycie więcej niż jednego skrótu pomoże tutaj? Nie. Osoba generująca konkretny atak tęczy będzie w stanie go wygenerować za pomocą jednego lub więcej skrótów.

A użycie więcej niż jednego skrótu może doprowadzić do jednego problemu: jest tak bezpieczny, jak najsłabszy skrót, którego używasz. Jeśli ktoś znajdzie kolizje w jednym algorytmie mieszającym, to ten skrót zostanie wykorzystany w dowolnym momencie procesu iteracji do złamania hasła. Tak więc nic nie zyskujesz, stosując więcej algorytmów mieszających, lepiej wybrać tylko jeden dobry algo. i użyj go. A jeśli kiedykolwiek usłyszysz, że został uszkodzony, zastanów się, jak to zmienisz w swojej aplikacji.

I po co używać bcrypt lub czegoś podobnego (mówisz, że go używasz): ponieważ atakujący będzie musiał spędzić więcej czasu na generowaniu tabel. Dlatego użycie MD5 + czekać (3 sekundy) nie pomaga: atak i tak będzie offline, więc osoba atakująca może wygenerować tabele bez (3 sekund opóźnienia).

woliveirajr
źródło
2
Ups! Niestety, mój komentarz (dotyczący celowego spowolnienia skrótu za pomocą parametru limitu czasu) nie powinien być traktowany poważnie ... Myślę, że ostatnio czytałem zbyt dużo Dilberta.
FrustratedWithFormsDesigner
2
sha (sha (sha (...))) nie jest bezpieczniejszy niż sha. Jeśli entropia funkcji sha nie jest maksymalna, jest to w rzeczywistości mniej bezpieczne.
deadalnix,
1
@deadalnix: ważne jest, aby wspomnieć, że nie ułatwia odzyskania oryginalnego hasła, ale ułatwia wygenerowanie kolidującego hasła, które jest wszystkim, czego potrzeba.
Bryan Boettcher
1
@deadalnix, przeczytałem ten komentarz w głosie Dale Gribble .
jiggy
1
@deadalnix: celem sha (sha (sha ())) nie jest i nigdy nie było, aby dodać więcej entropii. Entropia jest dokonywana przez początkowego użytkownika wybierającego hasło, a wszystko inne (skrót, sól itp.) Służy jedynie spowolnieniu ataku brutalnej siły. Jeśli ktoś jest w stanie uzyskać bazę danych zawierającą hasła, prawdopodobnie dostanie również kod używany do skrótu hasła, więc znana jest również każda zakodowana sól
woliveirajr
-1

Rozumiem, że używanie wielu algorytmów mieszających polega na pokonaniu tabel tęczy . Używanie dobrej soli również działa, ale myślę, że to drugi poziom ochrony.

nerwowy
źródło
4
Cóż, to się tak bardzo nie zmienia. Funkcja „wielokrotnego mieszania” może być postrzegana jako jedna i traktowana jako taka.
deadalnix,
2
Korzystanie z wielu technik mieszania lub iteracji nie ma wpływu na tabele tęczy. Jeśli osoba atakująca ma bazę danych i stosuje metodę generowania skrótów, osoba atakująca może następnie wygenerować tęczową tabelę, aby zaatakować wszystkie hasła w bazie danych. SALTS zapobiega atakom na tęczową tablicę, ponieważ uniemożliwiają atakującemu wygenerowanie pojedynczego słownika wyszukiwania, aby zaatakować, powiedzmy, wszystkie hasła o długości 8 znaków lub mniej.
Erik
-1

To nie jest bardziej bezpieczne. Masz jednak protokół identyfikacji oparty na haszowaniu wiele razy z tą samą funkcją.

Tak to wygląda. Zapisana wartość to hash ^ n (pass) na komputerze A. Zapytaj B o uwierzytelnienie i poda B liczbę całkowitą n. B wykonuje skrót obliczeniowy ^ (n-1) (pass) i odsyła go z powrotem do A.

Sprawdzenie, że hash (hash ^ (n-1) (pass)) == hash ^ n (pass). Jeśli to prawda, uwierzytelnianie jest wykonywane. Ale następnie skrót H ^ (n-1) (pass) i następne uwierzytelnienie da B n-1 zamiast n.

Zapewnia to, że hasło nigdy nie jest wymieniane w sposób wyraźny, że A nigdy nie wie, jakie jest hasło, a uwierzytelnienie jest chronione przez powtórkę. Ma to jednak tę wadę, że wymaga hasła o skończonym okresie użytkowania. Kiedy n osiągnie wartość 2, po uwierzytelnieniu należy wybrać nowe hasło.

Innym zastosowaniem wielu skrótów jest narzędzie HMAC, które zapewnia uwierzytelnianie i integralność żądania. Więcej informacji na temat HMAC można znaleźć na stronie http://en.wikipedia.org/wiki/HMAC .

Większość użycia wielu skrótów w prawdziwym świecie to przesada. W twoim przypadku wydaje się, że tak. Zauważ, że jeśli użyjesz kilku funkcji skrótu, nie wszystkie będą miały tę samą entropię, co zmniejszy siłę skrótu. Na przykład md5 ma mniejszą entropię niż sha1, więc użycie sha1 na md5 nie poprawi siły skrótu. Siła będzie na ogół równa sile słabszej funkcji skrótu.

deadalnix
źródło