Porównywanie haseł z crypt () w PHP

Muszę poznać podstawy tej funkcji. Na php.net dokumentacja stwierdza, dla algorytmu blowfish, że:

Blowfish hashowanie z solą w następujący sposób: "$2A$", dwucyfrowy parametr kosztu,"$", i 22 podstawowe 64 cyfry z alfabetu"./ 0-9A-Za-z". Użycie znaków spoza tego zakresu w salt spowoduje, że crypt () zwróci łańcuch o zerowej długości

Więc to z definicji nie powinno działać:

echo crypt('rasmuslerdorf', '$2a$07$usesomadasdsadsadsadasdasdasdsadesillystringforsalt$');

Jednak pluje out:

$2a$07$usesomadasdsadsadsadaeMTUHlZEItvtV00u0.kb7qhDlC0Kou9e

Gdzie wydaje się, że crypt() przecięła samą sól do długości 22. Czy ktoś może to wyjaśnić?

Innym aspektem tej funkcji, którego nie mogę ogarnąć, jest użycie crypt () do porównywania haseł. http://php.net/manual/en/function.crypt.php (spójrz na ex. #1). Czy to oznacza, że jeśli używam tej samej soli do szyfrowania wszystkich moich haseł, muszę je najpierw zaszyfrować? ie:

$salt = "usesomadasdsadsadsadae";
$salt_crypt = crypt($salt);

if (crypt($user_input, $salt) == $password) {
   // FAIL WONT WORK
}

if (crypt($user_input, $salt_crypt) == $password) {
   // I HAVE TO DO THIS?
}    

Dziękujemy za poświęcony czas

Author: soren.qvist, 2010-06-28

6 answers

Poniższy przykład kodu może odpowiedzieć na twoje pytania.

Aby wygenerować hashowane hasło za pomocą Blowfish, musisz najpierw wygenerować salt, który zaczyna się od $2a$, a następnie licznik iteracji i 22 znaki łańcucha Base64.

$salt = '$2a$07$usesomadasdsadsadsadasdasdasdsadesillystringfors';
$digest = crypt('rasmuslerdorf', $salt);

Przechowuj cały $digest w bazie danych, ma zarówno sól, jak i digest.

Porównując hasło, po prostu zrób to,

  if (crypt($user_input, $digest) == $digest)
Używasz ponownie trawienia jako soli. crypt wie, jak długi jest salt z identyfikatora algorytmu.
 19
Author: ZZ Coder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-28 21:16:22

Cytowanie z podręcznika

CRYPT_BLOWFISH - Blowfish hashing with sól w następujący sposób: "$2A$", dwucyfrowa parametr kosztu,"$", oraz 22 base 64 cyfry z alfabetu

Uwaga: 22 baza 64 cyfry

 3
Author: Mark Baker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-28 19:44:39

BCrypt używa 128 bitów dla salt, więc 22 bajty Base64, przy czym używane są tylko dwa bity ostatniego bajtu.

Hash jest obliczany przy użyciu soli i hasła. Po przekazaniu hasła algorytm odczytuje siłę, sól (ignorując wszystko poza nią) i podane hasło, a następnie oblicza hash, dołączając je. Jeśli masz pod ręką PostgreSQL i pg_crypto, wybierz gen_salt ('bf'); pokaże ci co z $salt jest czytane.

Oto próbka kodu dla soli generacji, z mojej implementacji . Net ' s test-vector-gen.php, alternatywnie:

$salt = sprintf('$2a$%02d$%s', [strength goes here],
    strtr(str_replace(
    '=', '', base64_encode(openssl_random_pseudo_bytes(16))
    ),
    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
    './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'));

Nie ma powodu, aby używać tej samej soli dla wszystkich haseł. Sól i tak jest częścią produkcji, więc nic nie zyskujesz w wygody... chociaż przyznam, że PHP powinno mieć wbudowaną funkcję gen_salt.

 2
Author: Zer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-22 17:08:08

Nowa Sól na każde hasło

$password = 'p@ssw0rd';

$salt = uniqid('', true);
$algo = '6'; // CRYPT_SHA512
$rounds = '5042';
$cryptSalt = '$'.$algo.'$rounds='.$rounds.'$'.$salt;

$hashedPassword = crypt($password, $cryptSalt);
// Store complete $hashedPassword in DB

echo "<hr>$password<hr>$algo<hr>$rounds<hr>$cryptSalt<hr>$hashedPassword";

Uwierzytelnianie

if (crypt($passwordFromPost, $hashedPasswordInDb) == $hashedPasswordInDb) {
    // Authenticated
 2
Author: Brock Hensley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-27 13:07:11

Pierwsze pytanie:

Więc to z definicji nie powinno działać:

echo crypt('rasmuslerdorf', '$2a$07$usesomadasdsadsadsadasdasdasdsadesillystringforsalt$');

Gdzie wydaje się, że crypt () wyciął sama sól do długości 22. Czy ktoś może to wyjaśnić?

Nie ma problemu z posiadaniem zbyt wielu postaci... fraza użycie znaków spoza tego zakresu w salt spowoduje, że crypt() zwróci ciąg o zerowej długości odwołuje się do spoza zakresu base 64, a nie do zakresu 22 znaki. Spróbuj umieścić nielegalny znak w łańcuchu salt, a powinieneś zauważyć, że masz puste wyjście (lub jeśli umieścisz

Drugie pytanie:

Przekazujesz zaszyfrowane zapisane hasło jako salt, ponieważ łańcuch salt zawsze pojawia się (według projektu) w zaszyfrowanym łańcuchu, a tym samym zapewniasz, że masz ten sam salt zarówno dla szyfrowania zapisanego, jak i wprowadzonego przez użytkownika hasła.

 0
Author: G__,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-28 19:47:54

To pytanie jest związane z moją odpowiedzią na odpowiedź ZZ Coder. Zasadniczo moje pytanie dotyczy przechowywania wyniku crypt () w bazie danych. Czy mam przechowywać całe wyjście w bazie danych, aby moja baza wyglądała tak:

--------------------------------------------------------------------------------
| ID | Username |                          Password                            |
--------------------------------------------------------------------------------
| 32 | testuser | $2a$07$usesomadasdsadsadsadaeMTUHlZEItvtV00u0.kb7qhDlC0Kou9e |
--------------------------------------------------------------------------------

Jeśli tak, to czy ten rodzaj nie przeciwstawia się celowi użycia soli w pierwszej kolejności? Jeśli ktoś uzyska dostęp do db, może wyraźnie zobaczyć sól używaną do szyfrowania?

Pytanie dodatkowe: czy korzystanie z tego samego sól na każde hasło?
 0
Author: soren.qvist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-29 20:54:03