[IMPROVED] Versioned password hashing support

Addresses #2047
This commit is contained in:
Sebastian Grewe 2014-04-20 17:07:31 +02:00
parent 540a99abc5
commit 4cac2ce3b4

View File

@ -7,8 +7,15 @@ class User extends Base {
private $user = array(); private $user = array();
// get and set methods // get and set methods
private function getHash($string) { private function getHash($string, $version=0, $pepper='') {
return hash('sha256', $string.$this->salt); switch($version) {
case 0:
return hash('sha256', $string.$this->salt);
break;
case 1:
return '$' . $version . '$' . $pepper . '$' . hash('sha256', $string.$this->salt.$pepper);
break;
}
} }
public function getUserName($id) { public function getUserName($id) {
return $this->getSingle($id, 'username', 'id'); return $this->getSingle($id, 'username', 'id');
@ -263,6 +270,8 @@ class User extends Base {
$stmt = $this->mysqli->prepare("SELECT pin FROM $this->table WHERE id=? AND pin=? LIMIT 1"); $stmt = $this->mysqli->prepare("SELECT pin FROM $this->table WHERE id=? AND pin=? LIMIT 1");
$pin_hash = $this->getHash($pin); $pin_hash = $this->getHash($pin);
if ($stmt->bind_param('is', $userId, $pin_hash) && $stmt->execute() && $stmt->bind_result($row_pin) && $stmt->fetch()) { if ($stmt->bind_param('is', $userId, $pin_hash) && $stmt->execute() && $stmt->bind_result($row_pin) && $stmt->fetch()) {
$aPin = explode('$', $row_pin);
count($aPin) == 1 ? $pin_hash = $this->getHash($pin, 0) : $pin_hash = $this->getHash($pin, $aPin[1], $aPin[2]);
$this->setUserPinFailed($userId, 0); $this->setUserPinFailed($userId, 0);
return ($pin_hash === $row_pin); return ($pin_hash === $row_pin);
} }
@ -577,14 +586,15 @@ class User extends Base {
private function checkUserPassword($username, $password) { private function checkUserPassword($username, $password) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
$user = array(); $user = array();
$password_hash = $this->getHash($password); $stmt = $this->mysqli->prepare("SELECT username, pass, id, is_admin FROM $this->table WHERE LOWER(username) = LOWER(?) LIMIT 1");
$stmt = $this->mysqli->prepare("SELECT username, id, is_admin FROM $this->table WHERE LOWER(username) = LOWER(?) AND pass = ? LIMIT 1"); if ($this->checkStmt($stmt) && $stmt->bind_param('s', $username) && $stmt->execute() && $stmt->bind_result($row_username, $row_password, $row_id, $row_admin)) {
if ($this->checkStmt($stmt) && $stmt->bind_param('ss', $username, $password_hash) && $stmt->execute() && $stmt->bind_result($row_username, $row_id, $row_admin)) {
$stmt->fetch(); $stmt->fetch();
$stmt->close(); $stmt->close();
$aPassword = explode('$', $row_password);
count($aPassword) == 1 ? $password_hash = $this->getHash($password, 0) : $password_hash = $this->getHash($password, $aPassword[1], $aPassword[2]);
// Store the basic login information // Store the basic login information
$this->user = array('username' => $row_username, 'id' => $row_id, 'is_admin' => $row_admin); $this->user = array('username' => $row_username, 'id' => $row_id, 'is_admin' => $row_admin);
return strtolower($username) === strtolower($row_username); return $password_hash === $row_password && strtolower($username) === strtolower($row_username);
} }
return $this->sqlError(); return $this->sqlError();
} }
@ -788,9 +798,9 @@ class User extends Base {
} }
// Create hashed strings using original string and salt // Create hashed strings using original string and salt
$password_hash = $this->getHash($password1); $password_hash = $this->getHash($password1, 1, bin2hex(openssl_random_pseudo_bytes(32)));
$pin_hash = $this->getHash($pin); $pin_hash = $this->getHash($pin, 1, bin2hex(openssl_random_pseudo_bytes(32)));
$apikey_hash = $this->getHash($username); $apikey_hash = $this->getHash($username, 0);
$username_clean = strip_tags($username); $username_clean = strip_tags($username);
$signup_time = time(); $signup_time = time();