password_hash în PHP

Creează un hash sigur pentru o parolă, gata de salvat în baza de date. Este modul corect de a stoca parole.

Sintaxă
password_hash(string $password, string|int|null $algo, array $options = []): string

Ce face password_hash

Parolele nu se salvează niciodată ca text simplu și nici cu md5 sau sha1. password_hash folosește un algoritm lent intenționat (implicit bcrypt) și adaugă automat o „sare” aleatorie, așa că aceeași parolă dă de fiecare dată alt hash.

Rezultatul conține tot ce trebuie pentru verificare: algoritmul, costul și sarea. Îl salvezi într-o coloană de tip VARCHAR(255) și îl verifici mai târziu cu password_verify.

Folosește PASSWORD_DEFAULT: PHP îl actualizează la algoritmi mai buni în versiunile noi. Din PHP 8.4 costul implicit pentru bcrypt este 12 (înainte era 10). Alternativa PASSWORD_ARGON2ID este disponibilă dacă PHP a fost compilat cu suport Argon2.

Parametri

Parametru Descriere
$password Parola introdusă de utilizator.
$algo Algoritmul: PASSWORD_DEFAULT (recomandat), PASSWORD_BCRYPT, PASSWORD_ARGON2ID.
$options Opțional. Pentru bcrypt, ["cost" => 12]: cu cât costul este mai mare, cu atât calculul este mai lent și mai greu de spart.

Ce returnează

Hash-ul parolei, ca text (60 de caractere pentru bcrypt).

Exemple

Exemplul 1: Hash pentru o parolă nouă

Partea de după $2y$12$ diferă la fiecare rulare, din cauza sării aleatorii.

<?php
$hash = password_hash("Ana#2026!", PASSWORD_DEFAULT);

echo $hash;

Rezultat posibil (diferă la fiecare rulare)

$2y$12$X35HWT06YaSd2qh/QDppX.HQN3oQTSn.Fo..H1lAh7oee6/O0Gl2y

Exemplul 2: Aceeași parolă, hash-uri diferite

<?php
$a = password_hash("parola", PASSWORD_DEFAULT);
$b = password_hash("parola", PASSWORD_DEFAULT);

var_dump($a === $b);
var_dump(password_verify("parola", $a), password_verify("parola", $b));
echo substr($a, 0, 7) . " ... " . strlen($a) . " caractere";

Rezultat

bool(false)
bool(true)
bool(true)
$2y$12$ ... 60 caractere

Exemplul 3: La înregistrarea unui utilizator

<?php
$parola = "Ana#2026!";

if (strlen($parola) < 8) {
    exit("Parola este prea scurtă.");
}

$hash = password_hash($parola, PASSWORD_DEFAULT);
// INSERT INTO utilizatori (email, parola) VALUES (?, ?)
// cu valorile "ana@exemplu.ro" și $hash
echo "Salvat: " . substr($hash, 0, 7) . "...";

Rezultat

Salvat: $2y$12$...

Greșeli frecvente

  • Coloana din baza de date are VARCHAR(32) sau VARCHAR(60). Hash-ul este tăiat sau nu încape când algoritmul implicit se schimbă. Folosește VARCHAR(255).
  • Compari hash-urile direct: password_hash($parola) === $hashSalvat. Nu va fi niciodată adevărat, pentru că sarea diferă. Folosește password_verify.
  • Cu bcrypt, doar primii 72 de octeți din parolă contează. Parolele mai lungi sunt tăiate, fără nicio eroare.

Comenzi înrudite

  • password_verify: Verifică dacă o parolă introdusă se potrivește cu hash-ul creat de password_hash.
  • password_needs_rehash: Verifică dacă un hash de parolă a fost creat cu alt algoritm sau alt cost decât cele actuale și trebuie refăcut.
  • hash: Calculează amprenta unui text cu algoritmul ales: sha256, sha512, sha3-256, xxh3 și multe altele.