Szukaj…


Wprowadzenie

Ponieważ bezpieczniejsze usługi sieciowe unikają przechowywania haseł w formacie zwykłego tekstu, języki takie jak PHP zapewniają różne (nieszyfrowalne) funkcje skrótu w celu obsługi bardziej bezpiecznego standardu branżowego. Ten temat zawiera dokumentację do poprawnego mieszania z PHP.

Składnia

  • string password_hash ( string $password , integer $algo [, array $options ] )
  • boolean password_verify ( string $password , string $hash )
  • boolean password_needs_rehash ( string $hash , integer $algo [, array $options ] )
  • array password_get_info ( string $hash )

Uwagi

W wersjach wcześniejszych niż PHP 5.5 można użyć pakietu zgodności w celu zapewnienia funkcji password_* . Zdecydowanie zaleca się korzystanie z pakietu zgodności, jeśli jest to możliwe.

Z pakietem kompatybilności lub bez niego, poprawna funkcjonalność Bcrypt poprzez crypt() opiera się na PHP 5.3.7+, w przeciwnym razie musisz ograniczyć hasła do zestawów znaków tylko ASCII.

Uwaga: jeśli używasz PHP 5.5 lub niższej, korzystasz z nieobsługiwanej wersji PHP, która nie otrzymuje już żadnych aktualizacji zabezpieczeń. Zaktualizuj tak szybko, jak to możliwe, a następnie zaktualizuj skróty hasła.

Wybór algorytmu

Bezpieczne algorytmy

Niepewne algorytmy

Poniższe algorytmy mieszające są niepewne lub nieodpowiednie do określonego celu i dlatego nie należy ich używać . Nigdy nie nadawały się do mieszania haseł, ponieważ zostały zaprojektowane do szybkich skrótów zamiast powolnych i trudnych do brutalnego skrótu hasła.

Jeśli użyjesz któregokolwiek z nich , nawet soli, powinieneś jak najszybciej przełączyć się na jeden z zalecanych bezpiecznych algorytmów.

Algorytmy uważane za niepewne:

Niektóre algorytmy mogą być bezpiecznie używane jako algorytm podsumowania wiadomości w celu potwierdzenia autentyczności, ale nigdy jako algorytm mieszania hasła :

  • SHA-2
  • SHA-3

Uwaga, silne skróty takie jak SHA256 i SHA512 są nienaruszone i wytrzymałe, jednakże jest generalnie bardziej bezpieczne do użytku bcrypt lub argon2 funkcji mieszających jak ataki brute force wobec tych algorytmów są znacznie trudniejsze dla komputerów klasycznych.

Sprawdź, czy istniejący skrót hasła można zaktualizować do silniejszego algorytmu

Jeśli używasz metody PASSWORD_DEFAULT , aby system mógł wybrać najlepszy algorytm do mieszania haseł, ponieważ domyślna wartość zwiększa siłę, możesz chcieć zmienić stare hasła podczas logowania użytkowników

<?php
// first determine if a supplied password is valid
if (password_verify($plaintextPassword, $hashedPassword)) {

    // now determine if the existing hash was created with an algorithm that is
    // no longer the default
    if (password_needs_rehash($hashedPassword, PASSWORD_DEFAULT)) {

        // create a new hash with the new default
        $newHashedPassword = password_hash($plaintextPassword, PASSWORD_DEFAULT);

        // and then save it to your data store
        //$db->update(...);
    }
}
?>

Jeśli funkcje hasła_ * nie są dostępne w twoim systemie (i nie możesz użyć pakietu kompatybilności podanego w uwagach poniżej), możesz określić algorytm i użyć go do utworzenia oryginalnego skrótu w metodzie podobnej do następującej:

<?php
if (substr($hashedPassword, 0, 4) == '$2y$' && strlen($hashedPassword) == 60) {
    echo 'Algorithm is Bcrypt';
    // the "cost" determines how strong this version of Bcrypt is
    preg_match('/\$2y\$(\d+)\$/', $hashedPassword, $matches);
    $cost = $matches[1];
    echo 'Bcrypt cost is '.$cost;
}
?>

Tworzenie skrótu hasła

Twórz skróty haseł za pomocą password_hash() aby użyć obecnego standardowego skrótu lub pochodnej klucza najlepszej w branży. W momencie pisania standardem jest bcrypt , co oznacza, że PASSWORD_DEFAULT zawiera tę samą wartość, co PASSWORD_BCRYPT .

$options = [
    'cost' => 12,
];

$hashedPassword = password_hash($plaintextPassword, PASSWORD_DEFAULT, $options);

Trzeci parametr nie jest obowiązkowy .

Wartość 'cost' należy wybrać na podstawie sprzętu serwera produkcyjnego. Zwiększenie go spowoduje, że wygenerowanie hasła będzie bardziej kosztowne. Im droższe jest generowanie, tym dłużej zajmuje próba złamania go, aby go wygenerować. Koszt powinien być możliwie jak najwyższy, ale w praktyce powinien być ustawiony tak, aby nie spowalniał wszystkiego zbyt mocno. Gdzieś pomiędzy 0,1 a 0,4 sekundy byłoby w porządku. W razie wątpliwości użyj wartości domyślnej.

5.5

W PHP mniejszym niż 5.5.0 funkcje password_* nie są dostępne. Należy użyć pakietu kompatybilności, aby zastąpić te funkcje. Zauważ, że pakiet kompatybilności wymaga PHP 5.3.7 lub nowszej wersji lub wersji, która ma z $2y poprawkę $2y (taką jak RedHat).

Jeśli nie możesz ich użyć, możesz zaimplementować haszowanie haseł za pomocą crypt() Ponieważ password_hash() jest zaimplementowane jako opakowanie wokół funkcji crypt() , nie musisz tracić żadnej funkcjonalności.

// this is a simple implementation of a bcrypt hash otherwise compatible
// with `password_hash()`
// not guaranteed to maintain the same cryptographic strength of the full `password_hash()`
// implementation

// if `CRYPT_BLOWFISH` is 1, that means bcrypt (which uses blowfish) is available
// on your system
if (CRYPT_BLOWFISH == 1) {
    $salt = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
    $salt = base64_encode($salt);
    // crypt uses a modified base64 variant
    $source = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    $dest = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $salt = strtr(rtrim($salt, '='), $source, $dest);
    $salt = substr($salt, 0, 22);
    // `crypt()` determines which hashing algorithm to use by the form of the salt string
    // that is passed in
    $hashedPassword = crypt($plaintextPassword, '$2y$10$'.$salt.'$');
}

Sól do mieszania hasła

Pomimo niezawodności algorytmu kryptowego nadal istnieje podatność na tęczowe tabele . To jest powód, dla którego zaleca się stosowanie soli .

Sól to coś, co jest dodawane do hasła przed haszowaniem, aby unikalny był ciąg źródłowy. Biorąc pod uwagę dwa identyczne hasła, wynikowe skróty będą również unikalne, ponieważ ich sole są unikalne.

Losowa sól jest jednym z najważniejszych elementów bezpieczeństwa hasła. Oznacza to, że nawet przy tabeli przeglądowej skrótów znanych haseł atakujący nie może dopasować skrótu hasła użytkownika do skrótów hasła bazy danych, ponieważ użyto losowej soli. Powinieneś używać zawsze losowych i kryptograficznie bezpiecznych soli. Czytaj więcej

Dzięki algorytmowi bcrypt password_hash() sól tekstowa jest przechowywana wraz z wynikowym hashem, co oznacza, że hash można przenosić między różnymi systemami i platformami i nadal dopasowywać do oryginalnego hasła.

7.0

Nawet jeśli jest to odradzane, możesz użyć opcji salt , aby zdefiniować własną losową sól.

 $options = [
        'salt' => $salt, //see example below
 ];

Ważne Jeśli pominiesz tę opcję, losowa sól będzie generowana przez hasło_hash () dla każdego haszowanego hasła. To jest zamierzony tryb działania.

7.0

Opcja soli jest przestarzała od PHP 7.0.0. Teraz najlepiej jest po prostu użyć soli, która jest generowana domyślnie.

Weryfikacja hasła względem skrótu

password_verify() to wbudowana funkcja (od PHP 5.5) służąca do weryfikacji ważności hasła względem znanego skrótu.

<?php
if (password_verify($plaintextPassword, $hashedPassword)) {
    echo 'Valid Password';
}
else {
    echo 'Invalid Password.';
}
?>

Wszystkie obsługiwane algorytmy mieszające przechowują informacje identyfikujące, który skrót został użyty w samym skrócie, więc nie trzeba wskazywać, którego algorytmu używasz do kodowania hasła w postaci zwykłego tekstu.

Jeśli funkcje hasła_ * nie są dostępne w twoim systemie (i nie możesz użyć pakietu kompatybilności podanego w uwagach poniżej), możesz zaimplementować weryfikację hasła za pomocą funkcji crypt() . Należy pamiętać, że należy podjąć szczególne środki ostrożności, aby uniknąć ataków na czas .

<?php
// not guaranteed to maintain the same cryptographic strength of the full `password_hash()`
// implementation
if (CRYPT_BLOWFISH == 1) {
    // `crypt()` discards all characters beyond the salt length, so we can pass in
    // the full hashed password
    $hashedCheck = crypt($plaintextPassword, $hashedPassword);

    // this a basic constant-time comparison based on the full implementation used
    // in `password_hash()`
    $status = 0;
    for ($i=0; $i<strlen($hashedCheck); $i++) {
        $status |= (ord($hashedCheck[$i]) ^ ord($hashedPassword[$i]));
    }

    if ($status === 0) {
        echo 'Valid Password';
    }
    else {
        echo 'Invalid Password';
    }
}
?>


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow