Merge pull request #2135 from MPOS/hashing-improvements
Hashing improvements
This commit is contained in:
commit
d84e54983a
@ -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');
|
||||||
@ -28,6 +35,12 @@ class User extends Base {
|
|||||||
public function getUserEmailById($id) {
|
public function getUserEmailById($id) {
|
||||||
return $this->getSingle($id, 'email', 'id', 'i');
|
return $this->getSingle($id, 'email', 'id', 'i');
|
||||||
}
|
}
|
||||||
|
public function getUserPasswordHashById($id) {
|
||||||
|
return $this->getSingle($id, 'pass', 'id', 'i');
|
||||||
|
}
|
||||||
|
public function getUserPinHashById($id) {
|
||||||
|
return $this->getSingle($id, 'pin', 'id', 'i');
|
||||||
|
}
|
||||||
public function getUserNoFee($id) {
|
public function getUserNoFee($id) {
|
||||||
return $this->getSingle($id, 'no_fees', 'id');
|
return $this->getSingle($id, 'no_fees', 'id');
|
||||||
}
|
}
|
||||||
@ -257,11 +270,13 @@ class User extends Base {
|
|||||||
* @param pin int PIN to check
|
* @param pin int PIN to check
|
||||||
* @return bool
|
* @return bool
|
||||||
**/
|
**/
|
||||||
public function checkPin($userId, $pin=false) {
|
public function checkPin($userId, $pin='') {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
$this->debug->append("Confirming PIN for $userId and pin $pin", 2);
|
$this->debug->append("Confirming PIN for $userId and pin $pin", 2);
|
||||||
$stmt = $this->mysqli->prepare("SELECT pin FROM $this->table WHERE id=? AND pin=? LIMIT 1");
|
$strPinHash = $this->getUserPinHashById($userId);
|
||||||
$pin_hash = $this->getHash($pin);
|
$aPin = explode('$', $strPinHash);
|
||||||
|
count($aPin) == 1 ? $pin_hash = $this->getHash($pin, 0) : $pin_hash = $this->getHash($pin, $aPin[1], $aPin[2]);
|
||||||
|
$stmt = $this->mysqli->prepare("SELECT pin FROM $this->table WHERE id = ? AND pin = ? LIMIT 1");
|
||||||
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()) {
|
||||||
$this->setUserPinFailed($userId, 0);
|
$this->setUserPinFailed($userId, 0);
|
||||||
return ($pin_hash === $row_pin);
|
return ($pin_hash === $row_pin);
|
||||||
@ -289,15 +304,17 @@ class User extends Base {
|
|||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
$username = $this->getUserName($userID);
|
$username = $this->getUserName($userID);
|
||||||
$email = $this->getUserEmail($username);
|
$email = $this->getUserEmail($username);
|
||||||
$current = $this->getHash($current);
|
$strPasswordHash = $this->getUserPasswordHashById($userID);
|
||||||
|
$aPassword = explode('$', $strPasswordHash);
|
||||||
|
count($aPassword) == 1 ? $password_hash = $this->getHash($current, 0) : $password_hash = $this->getHash($current, $aPassword[1], $aPassword[2]);
|
||||||
$newpin = intval( '0' . rand(1,9) . rand(0,9) . rand(0,9) . rand(0,9) );
|
$newpin = intval( '0' . rand(1,9) . rand(0,9) . rand(0,9) . rand(0,9) );
|
||||||
$aData['username'] = $username;
|
$aData['username'] = $username;
|
||||||
$aData['email'] = $email;
|
$aData['email'] = $email;
|
||||||
$aData['pin'] = $newpin;
|
$aData['pin'] = $newpin;
|
||||||
$newpin = $this->getHash($newpin);
|
$newpin = $this->getHash($newpin, HASH_VERSION, bin2hex(openssl_random_pseudo_bytes(32)));
|
||||||
$aData['subject'] = 'PIN Reset Request';
|
$aData['subject'] = 'PIN Reset Request';
|
||||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET pin = ? WHERE ( id = ? AND pass = ? )");
|
$stmt = $this->mysqli->prepare("UPDATE $this->table SET pin = ? WHERE ( id = ? AND pass = ? )");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('sis', $newpin, $userID, $current) && $stmt->execute()) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param('sis', $newpin, $userID, $password_hash) && $stmt->execute()) {
|
||||||
if ($stmt->errno == 0 && $stmt->affected_rows === 1) {
|
if ($stmt->errno == 0 && $stmt->affected_rows === 1) {
|
||||||
if ($this->mail->sendMail('pin/reset', $aData)) {
|
if ($this->mail->sendMail('pin/reset', $aData)) {
|
||||||
$this->log->log("info", "$username was sent a pin reset e-mail");
|
$this->log->log("info", "$username was sent a pin reset e-mail");
|
||||||
@ -407,7 +424,7 @@ class User extends Base {
|
|||||||
$this->setErrorMessage('A request has already been sent to your e-mail address. Please wait an hour for it to expire.');
|
$this->setErrorMessage('A request has already been sent to your e-mail address. Please wait an hour for it to expire.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the accounts password
|
* Update the accounts password
|
||||||
* @param userID int User ID
|
* @param userID int User ID
|
||||||
@ -427,8 +444,10 @@ class User extends Base {
|
|||||||
$this->setErrorMessage( 'New password is too short, please use more than 8 chars' );
|
$this->setErrorMessage( 'New password is too short, please use more than 8 chars' );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$current = $this->getHash($current);
|
$strPasswordHash = $this->getUserPasswordHashById($userID);
|
||||||
$new = $this->getHash($new1);
|
$aPassword = explode('$', $strPasswordHash);
|
||||||
|
count($aPassword) == 1 ? $password_hash = $this->getHash($current, 0) : $password_hash = $this->getHash($current, $aPassword[1], $aPassword[2]);
|
||||||
|
$new = $this->getHash($new1, HASH_VERSION, bin2hex(openssl_random_pseudo_bytes(32)));
|
||||||
if ($this->config['twofactor']['enabled'] && $this->config['twofactor']['options']['changepw']) {
|
if ($this->config['twofactor']['enabled'] && $this->config['twofactor']['options']['changepw']) {
|
||||||
$tValid = $this->token->isTokenValid($userID, $strToken, 6);
|
$tValid = $this->token->isTokenValid($userID, $strToken, 6);
|
||||||
if ($tValid) {
|
if ($tValid) {
|
||||||
@ -448,7 +467,7 @@ class User extends Base {
|
|||||||
}
|
}
|
||||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET pass = ? WHERE ( id = ? AND pass = ? )");
|
$stmt = $this->mysqli->prepare("UPDATE $this->table SET pass = ? WHERE ( id = ? AND pass = ? )");
|
||||||
if ($this->checkStmt($stmt)) {
|
if ($this->checkStmt($stmt)) {
|
||||||
$stmt->bind_param('sis', $new, $userID, $current);
|
$stmt->bind_param('sis', $new, $userID, $password_hash);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
if ($stmt->errno == 0 && $stmt->affected_rows === 1) {
|
if ($stmt->errno == 0 && $stmt->affected_rows === 1) {
|
||||||
$this->log->log("info", $this->getUserName($userID)." updated password");
|
$this->log->log("info", $this->getUserName($userID)." updated password");
|
||||||
@ -460,7 +479,7 @@ class User extends Base {
|
|||||||
$this->setErrorMessage( 'Unable to update password, current password wrong?' );
|
$this->setErrorMessage( 'Unable to update password, current password wrong?' );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update account information from the edit account page
|
* Update account information from the edit account page
|
||||||
* @param userID int User ID
|
* @param userID int User ID
|
||||||
@ -538,7 +557,7 @@ class User extends Base {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We passed all validation checks so update the account
|
// We passed all validation checks so update the account
|
||||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET coin_address = ?, ap_threshold = ?, donate_percent = ?, email = ?, is_anonymous = ? WHERE id = ?");
|
$stmt = $this->mysqli->prepare("UPDATE $this->table SET coin_address = ?, ap_threshold = ?, donate_percent = ?, email = ?, is_anonymous = ? WHERE id = ?");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('sddsii', $address, $threshold, $donate, $email, $is_anonymous, $userID) && $stmt->execute()) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param('sddsii', $address, $threshold, $donate, $email, $is_anonymous, $userID) && $stmt->execute()) {
|
||||||
@ -577,14 +596,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 +808,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, HASH_VERSION, bin2hex(openssl_random_pseudo_bytes(32)));
|
||||||
$pin_hash = $this->getHash($pin);
|
$pin_hash = $this->getHash($pin, HASH_VERSION, 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();
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@ $defflip = (!cfip()) ? exit(header('HTTP/1.1 401 Unauthorized')) : 1;
|
|||||||
define('MPOS_VERSION', '0.0.4');
|
define('MPOS_VERSION', '0.0.4');
|
||||||
define('DB_VERSION', '0.0.8');
|
define('DB_VERSION', '0.0.8');
|
||||||
define('CONFIG_VERSION', '0.0.8');
|
define('CONFIG_VERSION', '0.0.8');
|
||||||
|
define('HASH_VERSION', 1);
|
||||||
|
|
||||||
// Fetch installed database version
|
// Fetch installed database version
|
||||||
$db_version = $setting->getValue('DB_VERSION');
|
$db_version = $setting->getValue('DB_VERSION');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user