diff options
author | Roeland Jago Douma <roeland@famdouma.nl> | 2018-04-04 15:40:28 +0200 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2018-04-04 15:43:50 +0200 |
commit | 84316aec6665eb553e4bda5336913f27cf32f232 (patch) | |
tree | b95f2490db0bfe0ab4a8ed2b507c45a7029fdc33 /lib/private/Security | |
parent | 18676a8ee2c72a0239305e135dd04099280e3e43 (diff) | |
download | nextcloud-server-84316aec6665eb553e4bda5336913f27cf32f232.tar.gz nextcloud-server-84316aec6665eb553e4bda5336913f27cf32f232.zip |
Add ARGON2I support to the hasher
When on php7.2 we can use the new and improved ARGON2I hashing.
This adds support for that to the hasher. When verifying an old hash
we'll update rehash to move all hashes eventually to the new hash
function.
Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
Diffstat (limited to 'lib/private/Security')
-rw-r--r-- | lib/private/Security/Hasher.php | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/lib/private/Security/Hasher.php b/lib/private/Security/Hasher.php index c6c9109b336..e20de729f4f 100644 --- a/lib/private/Security/Hasher.php +++ b/lib/private/Security/Hasher.php @@ -51,11 +51,9 @@ class Hasher implements IHasher { /** @var IConfig */ private $config; /** @var array Options passed to password_hash and password_needs_rehash */ - private $options = array(); + private $options = []; /** @var string Salt used for legacy passwords */ private $legacySalt = null; - /** @var int Current version of the generated hash */ - private $currentVersion = 1; /** * @param IConfig $config @@ -78,7 +76,11 @@ class Hasher implements IHasher { * @return string Hash of the message with appended version parameter */ public function hash(string $message): string { - return $this->currentVersion . '|' . password_hash($message, PASSWORD_DEFAULT, $this->options); + if (\defined('PASSWORD_ARGON2I')) { + return 2 . '|' . password_hash($message, PASSWORD_ARGON2I, $this->options); + } else { + return 1 . '|' . password_hash($message, PASSWORD_BCRYPT, $this->options); + } } /** @@ -90,7 +92,7 @@ class Hasher implements IHasher { $explodedString = explode('|', $prefixedHash, 2); if(\count($explodedString) === 2) { if((int)$explodedString[0] > 0) { - return array('version' => (int)$explodedString[0], 'hash' => $explodedString[1]); + return ['version' => (int)$explodedString[0], 'hash' => $explodedString[1]]; } } @@ -111,8 +113,8 @@ class Hasher implements IHasher { // Verify whether it matches a legacy PHPass or SHA1 string $hashLength = \strlen($hash); - if($hashLength === 60 && password_verify($message.$this->legacySalt, $hash) || - $hashLength === 40 && hash_equals($hash, sha1($message))) { + if(($hashLength === 60 && password_verify($message.$this->legacySalt, $hash)) || + ($hashLength === 40 && hash_equals($hash, sha1($message)))) { $newHash = $this->hash($message); return true; } @@ -121,7 +123,7 @@ class Hasher implements IHasher { } /** - * Verify V1 hashes + * Verify V1 (blowfish) hashes * @param string $message Message to verify * @param string $hash Assumed hash of the message * @param null|string &$newHash Reference will contain the updated hash if necessary. Update the existing hash with this one. @@ -129,7 +131,30 @@ class Hasher implements IHasher { */ protected function verifyHashV1(string $message, string $hash, &$newHash = null): bool { if(password_verify($message, $hash)) { - if(password_needs_rehash($hash, PASSWORD_DEFAULT, $this->options)) { + $algo = PASSWORD_BCRYPT; + if (\defined('PASSWORD_ARGON2I')) { + $algo = PASSWORD_ARGON2I; + } + + if(password_needs_rehash($hash, $algo, $this->options)) { + $newHash = $this->hash($message); + } + return true; + } + + return false; + } + + /** + * Verify V2 (argon2i) hashes + * @param string $message Message to verify + * @param string $hash Assumed hash of the message + * @param null|string &$newHash Reference will contain the updated hash if necessary. Update the existing hash with this one. + * @return bool Whether $hash is a valid hash of $message + */ + protected function verifyHashV2(string $message, string $hash, &$newHash = null) : bool { + if(password_verify($message, $hash)) { + if(password_needs_rehash($hash, PASSWORD_ARGON2I, $this->options)) { $newHash = $this->hash($message); } return true; @@ -149,6 +174,8 @@ class Hasher implements IHasher { if(isset($splittedHash['version'])) { switch ($splittedHash['version']) { + case 2: + return $this->verifyHashV2($message, $splittedHash['hash'], $newHash); case 1: return $this->verifyHashV1($message, $splittedHash['hash'], $newHash); } |