UserManager a Nette\security\Password

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Jarik
Člen | 9
+
0
-

Zdravím,

mohl by mi prosím někdo vysvětlit jak funguje funkce nette\security\password::hash() a následně nette\security\password::verify;

/*Výpis z Api knihovny, z třídy: Nette\Security\Password*/


public static function hash($password, array $options = NULL)
28:     {
29:         $cost = isset($options['cost']) ? (int) $options['cost'] : self::BCRYPT_COST;
30:         $salt = isset($options['salt']) ? (string) $options['salt'] : Nette\Utils\Random::generate(22, '0-9A-Za-z./');
31:
32:         if (PHP_VERSION_ID < 50307) {
33:             throw new Nette\NotSupportedException(__METHOD__ . ' requires PHP >= 5.3.7.');
34:         } elseif (($len = strlen($salt)) < 22) {
35:             throw new Nette\InvalidArgumentException("Salt must be 22 characters long, $len given.");
36:         } elseif ($cost < 4 || $cost > 31) {
37:             throw new Nette\InvalidArgumentException("Cost must be in range 4-31, $cost given.");
38:         }
39:
40:         $hash = crypt($password, '$2y$' . ($cost < 10 ? 0 : '') . $cost . '$' . $salt);
41:         if (strlen($hash) < 60) {
42:             throw new Nette\InvalidStateException('Hash returned by crypt is invalid.');
43:         }
44:         return $hash;
45:     }
46:
47:
48:     /**
49:      * Verifies that a password matches a hash.
50:      * @return bool
51:      */
52:     public static function verify($password, $hash)
53:     {
54:         return preg_match('#^\$2y\$(?P<cost>\d\d)\$(?P<salt>.{22})#', $hash, $m)
55:             && $m['cost'] >= 4 && $m['cost'] <= 31
56:             && self::hash($password, $m) === $hash;
57:     }

Nějak mi nedává smysl, že funkce hash(‚password‘) zahashuje zadaný řetězec spolu s náhodně generovaným saltem a vrátí samotný hash, bez saltu.
Jakým způsobem je pak funkce verify(‚password‘, hash) schopná zjistit správnost hesla, když nezná salt?

Jan Tvrdík
Nette guru | 2595
+
0
-

Trik je v tom, že to nevrátí samotný hash, ale hash se saltem. Viz dokumentace PHP funkce crypt.

Jarik
Člen | 9
+
0
-

Dokumentaci funkce crypt() jsem četl, ale bohužel mi asi stále něco uniká.

Funkce krypt vrátí hash(‚heslo‘.‚salt‘), tzn. výstupem je pouze string (hash), ze kterého není možné běžným způsobem dostat původní data.
Máme pouze zaručeno, že dva totožné řetězce mají stejný hash. Ale já nemohu vytvořit totožný řetězec, pokud neznám salt.

Smysl by dávalo, pokud by salt i hash byly následně zašifrovány pomocí některé symetrické substituční šifry, kde by heslo sloužilo jako klíč. A výstupem by byla tato šifra, pokud mi ale něco neuniklo, to se neděje.

Je mi jasné, že Vám tyto dotazy mohou znít hloupě, ale opravdu mi zatím něco uniká, a zajímá mě co..

Jan Tvrdík
Nette guru | 2595
+
0
-

výstupem je pouze string (hash)

Ne. Výstupem je string (hash + salt).

looky
Člen | 99
+
0
-

Z dokumentace funkce crypt:

Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z".