Skip to content
Snippets Groups Projects
Commit 3c3341c1 authored by Tim van Dijen's avatar Tim van Dijen
Browse files

Provide proper password hashing & deprecate old unsafe code

parent f2ad81a2
No related branches found
No related tags found
No related merge requests found
...@@ -21,27 +21,4 @@ if (empty($password)) { ...@@ -21,27 +21,4 @@ if (empty($password)) {
exit(1); exit(1);
} }
$table = ''; echo "\n ".SimpleSAML\Utils\Crypto::pwHash($password)."\n\n";
foreach (array_chunk(hash_algos(), 6) as $chunk) {
foreach ($chunk as $algo) {
$table .= sprintf('%-13s', $algo);
}
$table .= "\n";
}
echo "The following hashing algorithms are available:\n".$table."\n";
echo "Which one do you want? [sha256] ";
$algo = trim(fgets(STDIN));
if (empty($algo)) {
$algo = 'sha256';
}
if (!in_array(strtolower($algo), hash_algos(), true)) {
echo "Hashing algorithm '$algo' is not supported\n";
exit(1);
}
echo "Do you want to use a salt? (yes/no) [yes] ";
$s = (trim(fgets(STDIN)) == 'no') ? '' : 'S';
echo "\n ".SimpleSAML\Utils\Crypto::pwHash($password, strtoupper($s.$algo))."\n\n";
...@@ -352,12 +352,12 @@ class Crypto ...@@ -352,12 +352,12 @@ class Crypto
* This function hashes a password with a given algorithm. * This function hashes a password with a given algorithm.
* *
* @param string $password The password to hash. * @param string $password The password to hash.
* @param string $algorithm The hashing algorithm, uppercase, optionally prepended with 'S' (salted). See * @param string|null $algorithm @deprecated The hashing algorithm, uppercase, optionally prepended with 'S' (salted). See
* hash_algos() for a complete list of hashing algorithms. * hash_algos() for a complete list of hashing algorithms.
* @param string $salt An optional salt to use. * @param string|null $salt @deprecated An optional salt to use.
* *
* @return string The hashed password. * @return string The hashed password.
* @throws \InvalidArgumentException If the input parameters are not strings. * @throws \InvalidArgumentException If the input parameter is not a string.
* @throws Error\Exception If the algorithm specified is not supported. * @throws Error\Exception If the algorithm specified is not supported.
* *
* @see hash_algos() * @see hash_algos()
...@@ -365,35 +365,41 @@ class Crypto ...@@ -365,35 +365,41 @@ class Crypto
* @author Dyonisius Visser, TERENA <visser@terena.org> * @author Dyonisius Visser, TERENA <visser@terena.org>
* @author Jaime Perez, UNINETT AS <jaime.perez@uninett.no> * @author Jaime Perez, UNINETT AS <jaime.perez@uninett.no>
*/ */
public static function pwHash($password, $algorithm, $salt = null) public static function pwHash($password, $algorithm = null, $salt = null)
{ {
if (!is_string($algorithm) || !is_string($password)) { if (!is_null($algorithm)) {
throw new \InvalidArgumentException('Invalid input parameters.'); // @deprecated Old-style
} if (!is_string($algorithm) || !is_string($password)) {
throw new \InvalidArgumentException('Invalid input parameters.');
// hash w/o salt }
if (in_array(strtolower($algorithm), hash_algos(), true)) { // hash w/o salt
$alg_str = '{'.str_replace('SHA1', 'SHA', $algorithm).'}'; // LDAP compatibility if (in_array(strtolower($algorithm), hash_algos(), true)) {
$hash = hash(strtolower($algorithm), $password, true); $alg_str = '{'.str_replace('SHA1', 'SHA', $algorithm).'}'; // LDAP compatibility
return $alg_str.base64_encode($hash); $hash = hash(strtolower($algorithm), $password, true);
} return $alg_str.base64_encode($hash);
}
// hash w/ salt
if ($salt === null) {
// no salt provided, generate one
// default 8 byte salt, but 4 byte for LDAP SHA1 hashes
$bytes = ($algorithm == 'SSHA1') ? 4 : 8;
$salt = openssl_random_pseudo_bytes($bytes);
}
// hash w/ salt if ($algorithm[0] == 'S' && in_array(substr(strtolower($algorithm), 1), hash_algos(), true)) {
if ($salt === null) { $alg = substr(strtolower($algorithm), 1); // 'sha256' etc
// no salt provided, generate one $alg_str = '{'.str_replace('SSHA1', 'SSHA', $algorithm).'}'; // LDAP compatibility
// default 8 byte salt, but 4 byte for LDAP SHA1 hashes $hash = hash($alg, $password.$salt, true);
$bytes = ($algorithm == 'SSHA1') ? 4 : 8; return $alg_str.base64_encode($hash.$salt);
$salt = openssl_random_pseudo_bytes($bytes); }
} throw new Error\Exception('Hashing algorithm \''.strtolower($algorithm).'\' is not supported');
} else {
if (!is_string($password)) {
throw new \InvalidArgumentException('Invalid input parameter.');
}
if ($algorithm[0] == 'S' && in_array(substr(strtolower($algorithm), 1), hash_algos(), true)) { return password_hash($password, PASSWORD_BCRYPT);
$alg = substr(strtolower($algorithm), 1); // 'sha256' etc
$alg_str = '{'.str_replace('SSHA1', 'SSHA', $algorithm).'}'; // LDAP compatibility
$hash = hash($alg, $password.$salt, true);
return $alg_str.base64_encode($hash.$salt);
} }
throw new Error\Exception('Hashing algorithm \''.strtolower($algorithm).'\' is not supported');
} }
...@@ -447,6 +453,12 @@ class Crypto ...@@ -447,6 +453,12 @@ class Crypto
throw new \InvalidArgumentException('Invalid input parameters.'); throw new \InvalidArgumentException('Invalid input parameters.');
} }
if (password_verify($password, $hash)) {
return true;
}
// return $hash === $password
// @deprecated remove everything below this line for 2.0
// match algorithm string (e.g. '{SSHA256}', '{MD5}') // match algorithm string (e.g. '{SSHA256}', '{MD5}')
if (preg_match('/^{(.*?)}(.*)$/', $hash, $matches)) { if (preg_match('/^{(.*?)}(.*)$/', $hash, $matches)) {
// LDAP compatibility // LDAP compatibility
...@@ -466,10 +478,9 @@ class Crypto ...@@ -466,10 +478,9 @@ class Crypto
$salt = substr(base64_decode($matches[2]), $hash_length); $salt = substr(base64_decode($matches[2]), $hash_length);
return self::secureCompare($hash, self::pwHash($password, $alg, $salt)); return self::secureCompare($hash, self::pwHash($password, $alg, $salt));
} }
throw new Error\Exception('Hashing algorithm \''.strtolower($alg).'\' is not supported');
} else { } else {
return $hash === $password; return $hash === $password;
} }
throw new Error\Exception('Hashing algorithm \''.strtolower($alg).'\' is not supported');
} }
} }
...@@ -105,12 +105,9 @@ class Htpasswd extends \SimpleSAML\Module\core\Auth\UserPassBase ...@@ -105,12 +105,9 @@ class Htpasswd extends \SimpleSAML\Module\core\Auth\UserPassBase
return $attributes; return $attributes;
} }
// SHA1 or plain-text // PASSWORD_BCRYPT
if (\SimpleSAML\Utils\Crypto::pwValid($crypted, $password)) { if (\SimpleSAML\Utils\Crypto::pwValid($crypted, $password)) {
\SimpleSAML\Logger::debug('User '.$username.' authenticated successfully'); \SimpleSAML\Logger::debug('User '.$username.' authenticated successfully');
\SimpleSAML\Logger::warning(
'SHA1 and PLAIN TEXT authentication are insecure. Please consider using something else.'
);
return $attributes; return $attributes;
} }
throw new \SimpleSAML\Error\Error('WRONGUSERPASS'); throw new \SimpleSAML\Error\Error('WRONGUSERPASS');
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment