summaryrefslogtreecommitdiffstats
path: root/lib/private/Security
diff options
context:
space:
mode:
authorRoeland Jago Douma <roeland@famdouma.nl>2018-04-04 15:40:28 +0200
committerRoeland Jago Douma <roeland@famdouma.nl>2018-04-04 15:43:50 +0200
commit84316aec6665eb553e4bda5336913f27cf32f232 (patch)
treeb95f2490db0bfe0ab4a8ed2b507c45a7029fdc33 /lib/private/Security
parent18676a8ee2c72a0239305e135dd04099280e3e43 (diff)
downloadnextcloud-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.php45
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);
}