Pomyślałem o tym by napisać o szyfrowaniu haseł w php, gdyż dużo osób myśli że jak sobie utworzy sumę md5 z hasła to jest bezpieczny. Otóż nie. Jest prawdopodobieństwo wygenerowania dwóch jednakowych sum md5 dla dwóch różnych stringów (nie majtki :) ).

Dlaczego nie używać md5?

W internecie możemy przeczytać nt używania sumy md5 w certyfikatach SSL przy połączeniach w np. systemach bankowych. Wg NIST (National Institute of Standards and Technology [ang. Narodowy Instytut Standaryzacji i Technologii]), powinno się wycofać używanie jej już w 1999r. I co Wy na to? Zdziwieni zapewne? A proszę bardzo, a to dlaczego? Jest za duża możliwość wygenerowania kolizji sumy, czyli to co pisałem wyżej wygenerowania dwóch identycznych sum.

Co zamiast md5?

Jest dużo algorytmów oferujących sumę kontrolną z stringu, lecz nie wszystkie są zalecane. W kolejności od najsłabszego:

  • SHA1
  • SHA-224
  • SHA-256
  • SHA-384
  • SHA-512

Wszystko wiąże się z przyrostem miejsca w bazie danych, więc i z czasem dostępu, porównaniem stringu. Szybciej jest pobrać 32 znaki alfanumeryczne z bazy danych niż 512 i je z sobą porównać. Ale na pewno nie jest bezpieczniej.

crypt() dobra alternatywa

Pewnie nie jeden z Was zastanawiał się jak w linuxie hasła są zabezpieczane. Otóż linux i unixowe systemy wykorzystują sól do zapisywania haseł. Tylko to nie polega na tym że wydzielimy sobie string, dorzucimy sól, połączymy ponownie i zrobimy z tego sumę md5 gdyż to nie zwiększy bezpieczeństwa.
W php od wersji > 4 istnieje taka funkcja jak crypt(), link-manual. Funkcja ta ma zaimplementowany algorytm taki jak linuks do zapisywania hasła.

function genSalt($len = 64) {
    $safeChars = '0123456789abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $shuffle = str_shuffle($safeChars); // mieszamy stringami ;)
    $n = strlen($safeChars);
	$p = ''; // na wszelki wypadek
	for ($i = 0; $i < $len; $i++) {
		$p .= $shuffle[rand(0, $n - 1)];
	} 
	return $p;
}
 
$password = $_POST['password'];
$salt = genSalt();
$pwdEncrypted = crypt($password, '$2a$07$'.$salt.'$');
echo $pwdEncrypted;

Problem z crypt()

Jest jeden mały problem z tą funkcją, po przeniesieniu strony wraz z bazą danych na inny hosting, istnieje prawdopodobieństwo iż hasła mimo że są poprawne nie będą pasować. Dlaczego? Nie mam pojęcia, przeczytałem to w jednej z książek ale autor nie wytłumaczył. Możliwe że zauważył ten problem, a mi się szukać nie chce ;] Ale who care? Jak można zawsze sobie hasło zmienić. Nie jestem do końca przekonany co do tej własności z tym że może być wygenerowany różnych suma dla teg samego stringa i soli.

A co z SHA-N?

Tak więc wg NIST do 2010r. SHA1 też ma zostać wycofane z użytku przy certyfikatach ssl. Tak więc pozostało nam parę funkcji.
Nie wszystkie z tych funkcji są “jawnie” dostępne w php, w sensie że są w postaci funkcji tak jak np md5, aby móc użyć np algorytmu SHA-512 musimy wykonać taką operację:

hash('sha512','Jakiś tekst do zsumowania ;)');

W funkcji hash możemy również wywoływać inne algorytmy tworzące sumę kontrolną. link-manual

Ale to nie wszystko, zapewne ktoś z Was słyszał o tęczowych tablicach, a jak nie to zapraszam link-wikipedia. Po przeczytaniu sami dojdziecie do wniosku że używanie sum kontrolnych jest po prostu mało bezpieczne.

Słów kilka na zakończenie

Co byśmy nie zrobili, to i tak się znajdzie ktoś kto nam złamie hasło, to tylko kwestia czasu.