I used this hash function for a while (got it from the internet). The thing is it used to work immediately but now it is complaining about a paramter. The following is the code:
function generateHash($plainText, $salt = null)
{
if ($salt === null)
{
$salt = substr(md5(uniqid(rand(), true)), 0, SALT_LENGTH);
}
else
{
$salt = substr($salt, 0, SALT_LENGTH);
}
return $salt . sha1($salt . $plainText);
}
So I would use this code in the method call:
validateUserInput($userid, $pass);
and validateUserInput is:
function validateUserInput($username, $password)
{
//$username = mysql_real_escape_string($username);
//$password = mysql_real_escape_string($password);
if(!$username || !$password)
{
//$errors['credentials'] = 'Missing Credentials!';
//$_SESSION['errors_array'] = $errors;
//echo $errors['credentials'];
header("LOCATION:XXXXXXX.php");
}
$local_salt = generateHash($password);
//echo $local_salt;
$groupid;
if($username != null && $password !=null)
{
connectToServer();
$result = mysql_query("SELECT * FROM users WHERE hashkey = '{$local_salt}'");
while($row_access = mysql_fetch_array($result))
{
$groupid = $row_access['groupid'];
}
if(!isset($result))
{
$errors['not_found_user'] = 'No Users Found with Provided Credentials!';
//$_SESSION['errors_array'] = $errors;
$userfound = 0;
$_SESSION['user_available'] = $userfound;
}elseif(isset($result)){
$_SESSION['user_logged'] = array('username' => $username, 'password' => $password, 'salt' => $local_salt, 'groupid' => $groupid);
$userfound = 1;
//echo "stored";
$_SESSION['user_available'] = $userfound;
}
}
}
finally the error is:
Warning: substr() expects parameter 3 to be long, string given in /home/XXXX.php on line 64
This is pointing to the function generateHash()
The error itself tells you everything. The constant SALT_LENGTH is not a long. I suspect it's not defined at all, so PHP converts the bare string to a string ("SALT_LENGTH") and passes that to substr(), which complains.
That being said... This code is dangerously wrong:
if(!isset($result)): Really? This condition will always be false because $result will always be set (unless you run into a problem with mysql_query(), but that doesn't tell you anything about the valididty of the login). And since mysql_query() never returns null, no logins will ever be rejected.
This query:
SELECT * FROM users WHERE hashkey = '{$local_salt}'
Is invalid. $local_salt = generateHash($password);. From the generateHash function, if a salt is not given, one will be randomly created for you. Thus, every call to generateHash will generate a new hash, which means it can't be compared to anything in the database.
On the basis of the two (very) egregious mistakes above, I would throw away this piece of code for good.
The correct way to check for a valid hash when a salt is used is something like:
$_SESSION['user_logged'] = null;
// fetch hashed pw from db, where username is the submitted username
$result = mysqli_query("SELECT hash FROM users WHERE username = '{$username}'");
if ($result->num_rows != 0)
{
$row = $result->fetch_assoc();
$hash = $row['hash'];
$salt = substr($hash, 0, SALT_LENGTH); // extract salt
if (generateHash($password, $salt) == $hash)
{
// login successful.
$_SESSION['user_logged'] = $username; // don't store passwords here
}
}
// if $_SESSION['user_logged'] is not set, the login failed
if (!isset($_SESSION['user_logged']))
{
// you *don't* want to tell people which one (login or pw) is invalid
echo 'Invalid login or password';
}
Note: It's very important that the SALT_LENGTH is at most 32, or this won't work because of the way generateHash() is implemented.
Clearly SALT_LENGTH is not an integer. Find where it's defined and correct this.
Instead of making a new hashing function each time you write an application , you should utilize the one provided to you by php: crypt() ( i would recommend to go with any blowfish or sha256+ hash ).
And when selecting information from database, you should select it by username and then, with php, check if hash fits the password.
Related
I want use password_verify to login, and this is my code
$DB1->select('Idx,Email,Password');
$DB1->from('User');
$DB1->where('Email',$Email);
$result = $DB1->get()->result();
// get_where('4SUser',array('Email' => $Email))->result();
if(password_verify($this->input->post('Password'), $result[0]->Password)) {
$this->response("Login Success");
} else {
$this->response("Login Failed");
}
And then, this is when I join the member use password_hash
---update change
$hash = password_hash($this->input->post('Password'), PASSWORD_DEFAULT);
I don't know why it returns error;
use password tester1234 and in DB, $2y$10$FZ7WV5cn5OL58t5hgM3cBeb2NRfXk7IrxNzyBiBMYZA.HYtXSSDjS
this is DB value.
But when I test hash_password when I input the password,
"$2y$10$KP1MG1abyMBD/gR82WmKoONvW/VvblYix13We6MNeRKdbDg0ufRQC"
"$2y$10$2H7Lx340yXWBFXFgv2LUJuN.luODBmJtNwfrCVQh2A37O0Es9Ud/K"
"$2y$10$.xUl/0zKnt.m26MSVwUBDOFVx29Bd8XxNyI.t7RqonfP8pmwIIVRC"
Every Time changes
Is it cause the error of doesn't match the password?
please help me
---update question
$HashInputPassword = password_hash($this->input->post('Password'), PASSWORD_DEFAULT);
$UserPassword = $result[0]->Password;
if($HashInputPassword === $UserPassword) {
$this->response("Login Success");
} else {
$this->response("Login Failed");
}
I have added the password_hash PHP function to my registration page, where users create accounts and store passwords. I applied the same password_hash line of code in the registration form. The data is saved in the database, but when I try to log in, the password submitted isn't matching the password stored. I also tried the password_verify function, which I read in the PHP manual, but nothing works. I really don't know what else to do, after trying and trying, so if anybody has an advice, I'd appreciated it.
P.S. I'm currently using PHP version 5.6.25.
Here's the code:
<?php
// AJAX CALLS THIS LOGIN CODE TO EXECUTE
if(isset($_POST["e"])){
// CONNECT TO THE DATABASE
include_once("PHP_Includes/db.php");
// GATHER THE POSTED DATA INTO LOCAL VARIABLES AND SANITIZE
$e = mysqli_real_escape_string($db, $_POST['e']);
$p = password_hash($_POST['p'], PASSWORD_DEFAULT,['cost' => 15]);
// FORM DATA ERROR HANDLING
if($e == "" || $p == ""){
echo "login_failed";
exit();
} else {
// END FORM DATA ERROR HANDLING
$sql = "SELECT id, username, password FROM users WHERE email='$e' AND activated='1' LIMIT 1";
$query = mysqli_query($db, $sql);
$row = mysqli_fetch_row($query);
$db_id = $row[0];
$db_username = $row[1];
$db_pass_str = $row[2];
if($p != $db_pass_str){
echo "login_failed";
exit();
} else {
// CREATE THEIR SESSIONS
$_SESSION['userid'] = $db_id;
$_SESSION['username'] = $db_username;
$_SESSION['password'] = $db_pass_str;
}
}
exit();
}
?>
login() function:
function login(){
var e = _("email").value;
var p = _("password").value;
if(e == "" || p == ""){
_("status").innerHTML = "Fill out all of the form data";
} else {
_("loginbtn").style.display = "none";
_("status").innerHTML = 'please wait ...';
var ajax = ajaxObj("POST", "index.php");
ajax.onreadystatechange = function() {
if(ajaxReturn(ajax) == true) {
if(ajax.responseText == "login_failed"){
_("status").innerHTML = "Login unsuccessful, please try again.";
_("loginbtn").style.display = "block";
} else {
window.location = "user.php?u="+ajax.responseText;
}
}
}
ajax.send("e="+e+"&p="+p);
}
}
Your understanding of how password_hash() works is a bit off. Unlike using sha1() or md5() (both of which you should avoid for storing passwords!), the password_hash() doesn't return the same string for every time it's called, even for the same string.
For example:
var_dump(password_hash("hello_world", PASSWORD_DEFAULT));
var_dump(password_hash("hello_world", PASSWORD_DEFAULT));
would output (for example, the strings returned by password_hash() varies for each time its called)
string(60) "$2y$10$Da2HG0dcvfI.3qBivR8Mpu9U5S06PBZ3415lDEh3EcDZ/fELZzHgC"
string(60) "$2y$10$zL6745UkPEvZWS5w1Keco.IKi7ssl.PqldGxucDYHaJW3vgCc366a"
Notice that they are different, even when the function is called twice on the same value? This means, that you cannot compare the stored password against $p = password_hash($_POST['p'], PASSWORD_DEFAULT,['cost' => 15]); like you are currently doing, because the password_hash() function returns a different string every time - you need to use the function password_verify() to verify the password, like below
$p = $_POST['p'];
if (password_verify($p, $fromDataBase)) {
// Valid password!
}
So instead of...
$p = password_hash($_POST['p'], PASSWORD_DEFAULT,['cost' => 15]);
you want
$p = $_POST['p'];
and instead of...
if($p != $db_pass_str){
you want
if (!password_verify($p, $db_pass_str)) {
And two notes on security:
You are not using prepared statements, which you REALLY should! See a link for mysqli_prepare() below. You should treat all your user-input as dangerous, and therefor use prepared statements for all SQL queries that accepts user-input. (When using prepared statements, you don't want to use mysqli_real_escape_string() - use one or the other, most preferably prepared statements!)
You are storing a password in a session - this is highly discouraged, as sessions can be "hijacked".
Readingmaterial:
http://php.net/manual/en/function.password-verify.php
http://php.net/manual/en/mysqli.prepare.php
How can I prevent SQL injection in PHP?
When a user creates a account on my website then their password is stored using SHA512. My problem is when the user tries to login with their password, i believe i am verifying the password incorrectly however i cannot see what i have done wrong.
Here is my register script which works :
$uname = mysql_real_escape_string($_POST['uname']);
$sname = mysql_real_escape_string($_POST['sname']);
$email = mysql_real_escape_string($_POST['email']);
$upass = mysql_real_escape_string($_POST['pass']);
$upass = hash('SHA512', $upass);
The password 'Test' is stored in the database as:
ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f88
Here is my login script:
if($row['password']==hash('SHA512', $upass))
{
$_SESSION['user'] = $row['user_id'];
header("Location: account.php");
If any body could please edit my login code so that it can retrieve and verify the SHA512 string then it would be greatly appreciated.
I am not worried about totally changing my login system to make it more secure, it is a very simple system which is only used to store a users preferences for the site, please could we just sick to using SHA512.
Here is the hash_equals() for php version >= 5.6.0 If you are using lower version then you can use code from below.
if(!function_exists('hash_equals')) {
function hash_equals($str1, $str2) {
if(strlen($str1) != strlen($str2)) {
return false;
} else {
$res = $str1 ^ $str2;
$ret = 0;
for($i = strlen($res) - 1; $i >= 0; $i--) $ret |= ord($res[$i]);
return !$ret;
}
}
}
Matching hash.
$expected = crypt('Test', '$2a$07$addsomecustomstring$');
$correct = crypt('Test', '$2a$07$addsomecustomstring$');
$wrong = crypt('tets', '$2a$07$addsomecustomstring$');
var_dump(hash_equals($expected, $correct)); //true
var_dump(hash_equals($expected, $wrong)); //false
Since you already calculated hash above you no longer need to call hash function again in comparison:
if($row['password']==$upass)
instead of:
if($row['password']==hash('SHA512', $upass))
I use this statement to hash the password with Phalcon:
$hashedPassword= $this->security->hash($password)
but this statement returns different results with the same password.
Example:
Set $password=123
I get $hashedPassword with the following values:
$2a$08$T2Rf9IcQHTj7TpY.gsfGiexZ35/KK9kS3fLElxaw8LGXhjnE01f5K
and
$2a$08$E2mjApECMbRKQFZodgLkEOpDLSV/tEjTe1HV3q2LLG9UINj9M9GBm
and
$2a$08$aZmgsMmG2xRueVzP6tkx2ucWGPZMzUwIccXbLJnqoRwDsSnT4zc.q
Here is the code I use for checking user's password,
please let me know what am I missing.
if ($this->request->isPost() == true)
{
$email = $this->request->getPost ("email");
$password = $this->request->getPost ("password");
$conditions = "email = ?1 AND admin = ?2";
$parameters = array(1 => $email, 2 => 1);
$users = Users::findFirst(array(
$conditions,
"bind" => $parameters
));
if($users)
{
$security = new Phalcon\Security();
$checkHashValue = $security->checkHash($password, $user->password);
if($checkHashValue)
{
$this->flash->success($users->fullname);
}
else
{
//Print debug information
$hash = $security->hash($password);
$checkHash = $security->checkHash($password, $hash);
$this->flash->error("Password: ". $password.
"<br/>Hash: " . $hash . "<br/>Check Hash: " . $checkHash .
"<br/>Check HashValue: ". $checkHashValue);
}
}
else
{
$this->flash->error($password);
}
}
SOLUTION: I have a typo in my variable "user" instead of "users".
That's how it is supposed to work. It creates a random hash each time. To check the password use security->checkPassword()
SOLUTION: I have a typo in my variable "user" instead of "users".
I want to reset user password using php. i got user's current and new password from html form . here's php script to reset password. But it always executes else part even if user enters correct password. how?any solution? i know there might be a simple error but i'm new at this and couldnt find any error.
$uid = $_SESSION['uid'];
$current_pass = $_POST['org_pass'];
$new_pass = $_POST['new_pass'];
if(isset($_POST['submit']))
{
$act_pass = $db_con->prepare("SELECT password FROM user WHERE u_id= ?");
$act_pass->bindParam(1,$uid);
$act_pass->execute();
$actual_pass = $act_pass->fetchColumn();
define('SALT', 'flyingrabbit');
$typed_pass = md5(SALT.$actual_pass);
if ($typed_pass == $current_pass)
{
$new_pass1 = md5(SALT . $new_pass);
$res = $db_con->prepare("UPDATE user SET password= ? WHERE u_id=?");
$res->bindParam(1,$new_pass1);
$res->bindParam(2,$uid);
$res->execute();
header("Location: profile.php");
exit;
}
else
{
echo "<script type=\"text/javascript\">window.alert(\"You entered wrong password.\");window.location.href = 'profile.php';</script>";
}
}
This looks wrong:
$actual_pass = $act_pass->fetchColumn();
// ...
$typed_pass = md5(SALT.$actual_pass);
if ($typed_pass == $current_pass)
You are hashing the information you got from the database which - I assume - is already hashed.
You probably want:
$actual_pass = $act_pass->fetchColumn();
// ...
$typed_pass = md5(SALT.$current_pass);
if ($typed_pass == $actual_pass)
Note that md5 is not recommended to hash passwords.
You should compare hashed $current_pass and **$actual_pas**s.
Replace
$typed_pass = md5(SALT.$actual_pass); with $typed_pass = md5(SALT.$current_pass);
$typed_pass == $current_pass with $typed_pass == $actual_pass
It goes to the else statement because you compare $typed_pass == $current_pass but on the previous line you do this $typed_pass = md5(SALT.$actual_pass) you compare a hashed, salted password to a plain text password