UserManager a Nette\security\Password
- Jarik
- Člen | 9
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
Trik je v tom, že to nevrátí samotný hash, ale hash se saltem. Viz dokumentace PHP funkce crypt.
- Jarik
- Člen | 9
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..