Jakiego typu danych użyć dla pola hashowanego i jakiej długości?


268

Nie jestem pewien, jak działa haszowanie haseł (zaimplementuję je później), ale muszę teraz utworzyć schemat bazy danych.

Mam na myśli ograniczenie haseł do 4–20 znaków, ale jak rozumiem, po zaszyfrowaniu ciąg skrótu będzie różnej długości.

Jak więc przechowywać te hasła w bazie danych?


Zobacz także strukturę hashowania haseł PHP Openwall (PHPass). Jest przenośny i odporny na wiele typowych ataków na hasła użytkowników. Facet, który napisał framework (SolarDesigner), to ten sam facet, który napisał John The Ripper i zasiada jako sędzia w konkursie Hashing Competition . Więc wie coś więcej o atakach na hasła.
jww

2
Nie nakładaj górnego limitu na hasła. Mieszasz je, nie ma powodu do przechowywania górnego limitu. Jeśli martwisz się atakami DoS przy użyciu skrótu hasła, 1000 lub 1024 to rozsądny górny limit.
Iiridayn

dlaczego ograniczać długość hasła? Przynajmniej pozwól użytkownikowi utworzyć 100-znakowe hasło :)
Andrew

4 znaki to dość niebezpieczna dolna granica dla haseł, ponieważ są one trywialne. Przynajmniej użyj 8, ale 14 lub 16 jest znacznie lepsze.
quikchange

To bardzo stare pytanie z nieaktualną odpowiedzią. Zobacz odpowiedź Gilles na aktualne.
kelalaka

Odpowiedzi:


448

Aktualizacja: samo użycie funkcji skrótu nie jest wystarczające do przechowywania haseł. Powinieneś przeczytać odpowiedź Gillesa w tym wątku, aby uzyskać bardziej szczegółowe wyjaśnienie.

W przypadku haseł użyj algorytmu skrótu wzmacniającego klucz, takiego jak Bcrypt lub Argon2i. Na przykład w PHP użyj funkcji password_hash () , która domyślnie używa Bcrypt.

$hash = password_hash("rasmuslerdorf", PASSWORD_DEFAULT);

Wynikiem jest ciąg 60 znaków podobny do następującego (ale cyfry będą się różnić, ponieważ generuje unikalną sól).

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

Użyj typu danych SQL CHAR(60)do przechowywania tego kodowania skrótu Bcrypt. Zauważ, że ta funkcja nie jest kodowana jako ciąg cyfr szesnastkowych, więc nie możemy tak łatwo odhaczyć jej do zapisania w formacie binarnym.

Inne funkcje skrótu nadal mają zastosowanie, ale nie do przechowywania haseł, więc zachowam oryginalną odpowiedź poniżej, napisaną w 2008 roku.


To zależy od używanego algorytmu mieszającego. Hashowanie zawsze daje wynik o tej samej długości, niezależnie od danych wejściowych. Reprezentacja wyniku mieszania binarnego w tekście jest typowa jako ciąg cyfr szesnastkowych. Możesz też użyć tej UNHEX()funkcji, aby zmniejszyć ciąg cyfr szesnastkowych o połowę.

  • MD5 generuje 128-bitową wartość skrótu. Możesz użyć CHAR (32) lub BINARY (16)
  • SHA-1 generuje 160-bitową wartość skrótu. Możesz użyć CHAR (40) lub BINARY (20)
  • SHA-224 generuje 224-bitową wartość skrótu. Możesz użyć CHAR (56) lub BINARY (28)
  • SHA-256 generuje 256-bitową wartość skrótu. Możesz użyć CHAR (64) lub BINARY (32)
  • SHA-384 generuje 384-bitową wartość skrótu. Możesz użyć CHAR (96) lub BINARY (48)
  • SHA-512 generuje 512-bitową wartość skrótu. Możesz użyć CHAR (128) lub BINARY (64)
  • BCrypt generuje zależną od implementacji wartość skrótu 448-bitowego. Możesz potrzebować CHAR (56), CHAR (60), CHAR (76), BINARY (56) lub BINARY (60)

Począwszy od 2015 r., NIST zaleca stosowanie SHA-256 lub wyższej do wszelkich zastosowań funkcji mieszających wymagających interoperacyjności. Ale NIST nie zaleca używania tych prostych funkcji skrótu do bezpiecznego przechowywania haseł.

Mniejsze algorytmy mieszające mają swoje zastosowania (takie jak wewnętrzne w aplikacji, a nie do wymiany), ale wiadomo, że można je wyłamać .


47
@Hippo: Proszę nie używać nazwy użytkownika jako soli. Wygeneruj losową sól na użytkownika.
Bill Karwin

11
Tak, nie ma powodu, aby nie przechowywać go w tym samym rzędzie. Nawet jeśli atakujący uzyska dostęp do Twojej bazy danych, będzie musiał zbudować tęczową tabelę na podstawie tej soli. A to tyle samo pracy, co odgadnięcie hasła.
Bill Karwin

5
@SgtPooki: Potrzebujesz innej kolumny do przechowywania soli w postaci zwykłego tekstu. Następnie możesz haszować hasło użytkownika przy użyciu tej samej soli, gdy je wpisuje, i porównać wynik z podsumowaniem skrótu zapisanym w tabeli.
Bill Karwin

12
Jeśli przechowujesz sól w tej samej tabeli (lub w innej lokalizacji z tymi samymi uprawnieniami dostępu), nie ma powodu, aby nie używać nazwy użytkownika jako soli, ponieważ będzie ona unikalna dla każdego użytkownika. Jednak każda znana sól sprawia, że ​​skrót jest kryptograficznie słabszy niż w przypadku braku znanej soli. Sól dodaje wartość tylko wtedy, gdy jest również nieznana.
fijiaaron

9
Nie rozumiem umowy ze znaną kontra nieznaną solą. Jeśli wdrażasz witrynę - sól musi być znana stronie logowania / skryptu / usłudze, która testuje hasło. Tak więc - „nieznani” zwolennicy soli - czy zakładacie, że kod procesu logowania jest nieznany atakującemu? W przeciwnym razie - czy atakujący nie zawsze zna sól, bez względu na to, czy jest losowa, unikalna, przechowywana razem z hasłem, czy osobno?
mattstuehler

13

Rzeczywiście możesz użyć CHAR(długości skrótu), aby zdefiniować typ danych dla MySQL, ponieważ każdy algorytm skrótu zawsze ocenia tę samą liczbę znaków. Na przykład SHA1zawsze zwraca 40-znakową liczbę szesnastkową.


1
SHA-1 nie nadaje się do mieszania haseł.
Gilles 'SO - przestań być zły'

10

Zawsze należy używać algorytmu mieszającego hasło: Argon2 , scrypt , bcrypt lub PBKDF2 .

Argon2 wygrał konkurs hashowania hasła 2015. Scrypt , bcrypt i PBKDF2 są starsze algorytmy, które są uważane za mniej korzystne teraz, ale nadal zasadniczo zdrowe, więc jeśli platforma nie obsługuje Argon2 jeszcze, to jest ok, aby użyć innego algorytmu do teraz.

Nigdy nie przechowuj hasła bezpośrednio w bazie danych. Nie szyfruj go też: w przeciwnym razie, jeśli Twoja witryna zostanie naruszona, atakujący otrzymuje klucz deszyfrujący, dzięki czemu może uzyskać wszystkie hasła. Hasła MUSZĄ zostać zakodowane .

Hash hasła ma różne właściwości z tabeli hash hash lub kryptograficzną hash. Nigdy nie używaj zwykłego skrótu kryptograficznego, takiego jak MD5, SHA-256 lub SHA-512 do hasła. Algorytm mieszania haseł wykorzystuje sól , która jest unikalna (nieużywana dla żadnego innego użytkownika ani w żadnej bazie danych). Sól jest niezbędna, aby atakujący nie mogli po prostu wstępnie obliczyć skrótów wspólnych haseł: przy użyciu soli muszą ponownie uruchomić obliczenia dla każdego konta. Algorytm mieszania hasła jest z natury powolny - tak wolny, jak tylko możesz sobie na to pozwolić. Powolność boli atakującego bardziej niż ciebie, ponieważ atakujący musi wypróbować wiele różnych haseł. Aby uzyskać więcej informacji, zobacz Jak bezpiecznie mieszać hasła .

Skrót hasła koduje cztery informacje:

  • Wskaźnik tego, który algorytm jest używany. Jest to konieczne dla zwinności : zalecenia kryptograficzne zmieniają się z czasem. Musisz być w stanie przejść do nowego algorytmu.
  • Wskaźnik trudności lub twardości. Im wyższa jest ta wartość, tym więcej obliczeń potrzeba do obliczenia wartości skrótu. Powinna to być stała lub globalna wartość konfiguracyjna w funkcji zmiany hasła, ale z czasem powinna rosnąć, ponieważ komputery stają się szybsze, dlatego należy pamiętać o wartości dla każdego konta. Niektóre algorytmy mają jedną wartość liczbową, inne mają więcej parametrów (na przykład do osobnego dostrajania zużycia procesora i pamięci RAM).
  • Sól. Ponieważ sól musi być unikalna na całym świecie, musi być przechowywana dla każdego konta. Sól powinna być generowana losowo przy każdej zmianie hasła.
  • Właściwy hash, tzn. Wynik obliczeń matematycznych w algorytmie haszującym.

Wiele bibliotek zawiera funkcje parowe, które wygodnie pakują te informacje jako pojedynczy ciąg znaków: taki, który pobiera wskaźnik algorytmu, wskaźnik twardości i hasło, generuje losową sól i zwraca pełny ciąg skrótu; oraz taki, który przyjmuje hasło i pełny ciąg hashowy jako dane wejściowe i zwraca wartość logiczną wskazującą, czy hasło było prawidłowe. Nie ma uniwersalnego standardu, ale powszechne jest kodowanie

$ Algorytm $ parametry $ sól $ wyjście

gdzie algorithmjest liczbą lub krótkim łańcuchem alfanumerycznym kodującym wybór algorytmu, parametersjest łańcuchem do wydruku salti outputjest kodowany w Base64 bez zakończenia =.

16 bajtów wystarcza na sól i wynik. (Zobacz np. Rekomendacje dla Argon2 .) Zakodowane w Base64, każdy ma 21 znaków. Pozostałe dwie części zależą od algorytmu i parametrów, ale typowe są 20–40 znaków. To w sumie około 82 znaków ASCII ( CHAR(82)i nie ma potrzeby Unicode), do których powinieneś dodać margines bezpieczeństwa, jeśli uważasz, że później trudno będzie powiększyć pole.

Jeśli kodujesz skrót w formacie binarnym, możesz sprowadzić go do 1 bajtu dla algorytmu, 1–4 bajtów dla twardości (jeśli kodujesz niektóre parametry) i 16 bajtów dla soli i danych wyjściowych , w sumie 37 bajtów. Powiedz 40 bajtów ( BINARY(40)), aby mieć przynajmniej kilka wolnych bajtów. Zauważ, że są to 8-bitowe bajty, znaki niedrukowalne, w szczególności pole może zawierać bajty zerowe.

Pamiętaj, że długość skrótu jest całkowicie niezwiązana z długością hasła.


9

Można znaleźć ten artykuł na solenie opłaca . Pomysł polega na dodaniu zestawu bitów danych w celu zrandomizowania wartości skrótu; to ochroni twoje hasła przed atakami słownikowymi, jeśli ktoś uzyska nieautoryzowany dostęp do skrótów haseł.


2
To jest rzeczywiście bardzo opłacalne (+1), ale nie odpowiada na pytanie! (-1)
Bill Karwin,

3
Tak, ale zdecydowanie istotne w tym kontekście (+1)
Treb

7

Jako ciąg o stałej długości (VARCHAR (n) lub jak to nazywa MySQL). Skrót ma zawsze stałą długość, na przykład 12 znaków (w zależności od używanego algorytmu skrótu). Tak więc hasło 20 znaków zostanie zredukowane do 12-znakowego skrótu, a hasło 4 znaków również da skrót 12 znaków.


3
„lub jak MySQL to nazywa” - MYSQL nazywa to CHAR. Ten typ dotyczy stałej długości. Myślę więc, że CHAR jest lepszym typem niż VARCHAR.
t298712383,

4

Powinieneś używać TEXT(przechowując nieograniczoną liczbę znaków) ze względu na kompatybilność do przodu. Algorytmy mieszania (muszą) z czasem stają się silniejsze, dlatego pole bazy danych będzie musiało obsługiwać więcej znaków z czasem. Ponadto w zależności od strategii migracji może być konieczne przechowywanie nowych i starych skrótów w tym samym polu, dlatego nie zaleca się ustawiania długości jednego typu skrótu.


3

To zależy od używanego algorytmu mieszającego. Długość hasła ma niewiele wspólnego z długością skrótu, jeśli dobrze pamiętam. Sprawdź specyfikację używanego algorytmu skrótu, uruchom kilka testów i obetnij tuż powyżej.


3

Hashe to sekwencja bitów (128 bitów, 160 bitów, 256 bitów itp., W zależności od algorytmu). Twoja kolumna powinna być typu binarnego, a nie tekstu / znaku, jeśli MySQL na to pozwala (typ danych SQL Server to binary(n)lub varbinary(n)). Powinieneś także posolić skróty. Sole mogą być tekstowe lub binarne i potrzebujesz odpowiedniej kolumny.


Sprawiedliwość jest tutaj całkowicie poprawna - MySQL będzie przechowywać te wartości liczbowe i sprawi, że wyszukiwanie w tej kolumnie będzie znacznie wydajniejsze niż dopasowanie ciągów, jednak sole nie powinny być przechowywane w bazie danych obok solonych danych - co eliminuje bezpieczeństwo zapewniane przez sole .
Tony Maro,

6
Sole nie są tajne. Tylko sekret to hasło. Upewnij się tylko, że każde nowe hasło otrzymuje nową sól. Za każdym razem, gdy użytkownik zmienia swoje hasło, system powinien wygenerować nową sól dla tego hasła. Sole powinny być długie i losowe, takie jak 16 bajtów wygenerowanych z kryptograficznie bezpiecznego PRNG.
yfeldblum,

1
@TonyMaro Nie jestem pewien, czy ciąg hasła pasuje do poziomu SQL jest dobrą strategią. Innymi słowy, nie należy przeszukiwać bazy danych w poszukiwaniu hasła, zamiast tego pobrać użytkownika na podstawie jego nazwy użytkownika i porównać hasła w kodzie zamiast w SQL.
bart,

1

Zawsze testowałem, aby znaleźć MAKSYMALNĄ długość ciągu zaszyfrowanego i ustawić go jako długość znaku typu VARCHAR. W zależności od liczby rekordów, które będziesz mieć, może to naprawdę pomóc w wielkości bazy danych.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.