public static function deriveKeys($password, $salt) { $seed = hex2bin(scrypt($password, $salt, 2048, 1, 1, 32)); $keypair = Sodium::crypto_sign_seed_keypair($seed); $keys = array('public' => bin2hex(Sodium::crypto_sign_publickey($keypair)), 'private' => bin2hex(Sodium::crypto_sign_secretkey($keypair))); return $keys; }
public function test_vector4() { $expected = "2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4"; $this->assertEquals(strlen($expected), 128); $actual = scrypt("pleaseletmein", "SodiumChloride", 1048576, 8, 1, 64); $this->assertEquals(bin2hex($actual), $expected); }
public function pass_verify($hash, $password) { global $conf; if (extension_loaded("scrypt")) { if (strlen($hash) <= 16) { return false; } $salt = substr($hash, 0, 16); $crypt = substr($hash, 16); return scrypt($password, $salt, $conf->hash_cost ^ 2, 8, 1, 64) == $crypt ? true : false; } else { return password_verify($password, $hash); } }
/** * Execute the scrypt algorithm * * @param string $password * @param string $salt * @param int $n CPU cost * @param int $r Memory cost * @param int $p parallelization cost * @param int $length size of the output key * @return string */ public static function calc($password, $salt, $n, $r, $p, $length) { if ($n == 0 || ($n & $n - 1) != 0) { throw new Exception\InvalidArgumentException("N must be > 0 and a power of 2"); } if ($n > PHP_INT_MAX / 128 / $r) { throw new Exception\InvalidArgumentException("Parameter n is too large"); } if ($r > PHP_INT_MAX / 128 / $p) { throw new Exception\InvalidArgumentException("Parameter r is too large"); } if (extension_loaded('Scrypt')) { if ($length < 16) { throw new Exception\InvalidArgumentException("Key length is too low, must be greater or equal to 16"); } return self::hex2bin(scrypt($password, $salt, $n, $r, $p, $length)); } $b = Pbkdf2::calc('sha256', $password, $salt, 1, $p * 128 * $r); $s = ''; for ($i = 0; $i < $p; $i++) { $s .= self::scryptROMix(substr($b, $i * 128 * $r, 128 * $r), $n, $r); } return Pbkdf2::calc('sha256', $password, $s, 1, $length); }
/** * Check a clear text password against a hash * * @src https://github.com/DomBlack/php-scrypt/blob/master/scrypt.php * @param string $password The clear text password * @param string $hash The hashed password * @param string $pepper A little extra to be added to the salt * @param string $key_length Length of the scrypt key * * @return boolean If the clear text matches */ private static function scrypt_check($password, $hash, $pepper = '', $key_length = 32) { list($N, $r, $p, $salt, $hash) = explode('$', $hash); return scrypt($password, $pepper . $salt, $N, $r, $p, self::$key_length) == $hash; }
/** * Check a clear text password against a hash * * @param string $password The clear text password * @param string $hash The hashed password * * @return boolean If the clear text matches */ public static function check($password, $hash) { // Is there actually a hash? if (!$hash) { return false; } list($N, $r, $p, $salt, $hash) = explode('$', $hash); // No empty fields? if (empty($N) or empty($r) or empty($p) or empty($salt) or empty($hash)) { return false; } // Are numeric values numeric? if (!is_numeric($N) or !is_numeric($r) or !is_numeric($p)) { return false; } $calculated = scrypt($password, $salt, $N, $r, $p, self::$_keyLength); // Use compareStrings to avoid timeing attacks return self::compareStrings($hash, $calculated); }
/** * Check a clear text password against a hash * * @param string $password The clear text password * @param string $hash The hashed password * * @throws \Exception * * @return boolean If the clear text matches */ public static function scryptcheck($password, $hash) { // Check if scrypt extension is available if (!extension_loaded('scrypt')) { throw new \Exception('Missing scrypt extension'); } // Is there actually a hash? if (!$hash) { return false; } list($N, $r, $p, $salt, $hash) = explode('$', $hash); // No empty fields? if (empty($N) or empty($r) or empty($p) or empty($salt) or empty($hash)) { return false; } // Are numeric values numeric? if (!is_numeric($N) or !is_numeric($r) or !is_numeric($p)) { return false; } $calculated = scrypt($password, $salt, $N, $r, $p, self::$_keyLength); // Use compareStrings to avoid timeing attacks return self::compareStrings($hash, $calculated); }
blkcpy($V, $i * 128 * $r, $X, 0, 128 * $r); blockmix_salsa8($X, $Y, $r); } for ($i = 0; $i < $N; $i++) { $j = integerify($X, $r) & $N - 1; blkxor($X, 0, $V, $j * 128 * $r, 128 * $r); blockmix_salsa8($X, $Y, $r); } blkcpy($B, $offset, $X, 0, 128 * $r); $XY = $X . $Y; } function scrypt($passwd, $salt, $N, $r, $p, $dklen) { echo "{$passwd} {$salt} : N = {$N}, r= {$r}, p = {$p}\n"; echo "best memory usage: " . (256 * $r + 256 * $r * $N + $p + 128 * $r) . "\n"; $XY = str_repeat("", 256 * $r); $V = str_repeat("", 256 * $r * $N); $B = pbkdf2_sha256($passwd, $salt, 1, $p * 128 * $r); for ($i = 0; $i < $p; $i++) { $t0 = microtime(true); echo "{$i} of {$p}\n"; smix($B, $i * 128 * $r, $r, $N, $V, $XY); $t1 = microtime(true); printf(" Took %.1f\n", $t1 - $t0); } return pbkdf2_sha256($passwd, $B, 1, $dklen); } //scrypt("password", "NaCl", 1024, 8, 16, 64); //scrypt("password", "NaCl", 1024, 8, 16, 64); scrypt("pleaseletmein", "SodiumChloride", 16384, 8, 1, 64);