Is it a good way to change password value each time a user log in to the database?
I have wrote a hash function to hash the password when a user register a new account on the system.
Each time the user logs in, the hash value in the database will be changed. Is it good or bad?
If you designed this hash function all by your self then... It is a very very bad idea. Why would you need something like this? If you store salted SHA-256 hashed passwords the security is good enough. You do not need to regenerate passwords, it does not provide any additional security. If lets say your app is prone to SQL-Injection, then this scheme won't protect your app. You would be a lot better if you used salted and keyed SHA-256, something like this: (I'm not a php coder, I just want our apps to be secure)
$username = 'Admin';
$password = 'gf45_gdf#4hg';
$key = 'MySuperSecretKEY!!!!';
$salt = hash('sha256', uniqid(mt_rand(), true) . 'something random' . strtolower($username));
$hash = $salt . $password . $key;
$hash = hash('sha256', $hash);
$hash = $salt . $hash;
and then checking:
$username = 'Admin';
$password = 'gf45_gdf#4hg';
$sql = '
SELECT
`hash`
FROM `users`
WHERE
`username` = "' . mysql_real_escape_string($username) . '"
LIMIT 1
;';
$r = mysql_fetch_assoc(mysql_query($sql));
$salt = substr($r['hash'], 0, 64);
$hash = $salt . $password . $key;
$hash = hash('sha256', $hash);
$hash = $salt . $hash;
if ( $hash == $r['hash'] ) {
//OK
}
So even if attacker will be able to trick the salting algorithm he does not know, a key so he won't be able to reproduce a valid hash in SQL-Injection attack.
Related
I'm obviously new to blowfish encryption to be asking this. I believe to have one side of the equation figured out but cannot figure out how to login once the hash is in the DB. I have the following for encrypting the password on registration:
$blowfish_hash = "$2y$10$";
$salt_length = 22;
$salt = Generate_Salt($salt_length);
$hash_combined = $blowfish_hash . $salt;
$hash = crypt($password, $hash_combined);
$password = $hash;
The Generate_Salt() function is as follows:
function Generate_Salt($length) {
$unique_rndm_str = md5(uniqid(mt_rand(), true));
$base64_string = base64_encode($unique_rndm_str);
$mod_Base64_str = str_replace('+', '.', $base64_string);
$salt = substr($mod_Base64_str, 0, $length);
return $salt;
}
Once I register I get this nice long hash - great! but, when I go to login I'm unsure on how to call the hash to check against the given password: $_POST['log_password'];
Using md5 is was easy, I just encrypted this way $password = md5($password); and recalled this way $password = md5($_POST['log_password']); however reading up I realize that this is not a secure method.
I've been at this for hours, can anyone shed some light on this for me please? Any help would be appreciated.
ep
It is much easier than you think. Just use the function password_hash() instead, it will do the call to the crypt() function and handles the generation of a safe salt.
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($_POST['password'], PASSWORD_DEFAULT);
// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($_POST['password'], $existingHashFromDb);
When I store my hashed password, it goes in as 29 characters, but when I hash for the password validation it is 64. The first 29 characters match, but I either need to lengthen the stored hash or shorten the validation hash. I have looked around the net and SO but can't seem to explicitly find out how to do this.
Which option (lengthen or shorten) is preferable and how would I go about doing this?
Here is my hash storage:
$hash = hash('sha256', $password1);
function createSalt(){
$text = md5(uniqid(rand(), true));
return substr($text, 0, 3);
}
$salt = createSalt();
$password = hash('sha256', $salt . $hash);
and here is my password validation and echoing of the hashes (which don't match up):
$userData = mysql_fetch_array($result, MYSQL_ASSOC);
$hash = hash('sha256', $userData['salt'] . hash('sha256', $password) );
if($hash != $userData['password']) // Incorrect password.
{ echo $userData['password'];
echo $hash;
die ('incorrect password : ' . mysql_error());
}
Thanks for any help, I sincerely appreciate it!
I have a register page that allow user to insert password so i need to hash it to become more secure in the database this work fine
but when it come to the login the entered password do not match the register one how to fix this problemmm
this is my first time to use hash so it did not work as i want
This is the register code for hash:
//ADD MD5 hash to the password
function cryptPass($input, $rounds = 9)
{
$salt = "";
$saltChars = array_merge(range('A','Z'), range('a','z'), range('0','9'));
for($i = 0; $i<22; $i++)
{
$salt .=$saltChars[array_rand($saltChars)];
}
return crypt($input, sprintf('$2y$%02d$test$', $rounds) . $salt);
}
$hashedpass = cryptPass($pass1);
echo $hashedpass;
the hashing password = $2y$09$test$5I9x8HWhA4UHi5TMu.AxfdWvZadDCE.LD6HCkrK3ZsqJeN7e
This is the login code for hash:
function cryptPass($input, $rounds = 9)
{
$salt = "";
$saltChars = array_merge(range('A','Z'), range('a','z'), range('0','9'));
for($i = 0; $i<22; $i++)
{
$salt .=$saltChars[array_rand($saltChars)];
}
return crypt($input, sprintf('$2y$%02d$test$', $rounds) . $salt);
}
$hashedpass = cryptPass($pass);
echo $hashedpass;
the hashing password = $2y$09$test$4ZGgCiXdKzgQvuzwu.AxfdWvZadDCE.LD6HCkrK3ZsqJeN7e
Upon registration you create a unique salt. That salt is now part of the hash. If you look closely, you'll see it's embedded in the first part of the hash. To check the password, use the previous hashed password's salt, so you're using the same salt again.
$correctPasswordHash = getPasswordFromDatabase($_POST['username']);
$hash = crypt($_POST['password'], $correctPasswordHash);
if ($correctPasswordHash === $hash) ...
To make this easier and more foolproof, use the password_compat library, which wraps this in an easy to use API, which will also be integrated into a future version of PHP. Inspect its source code for the correct usage of crypt, since there are some pitfalls you need to take care of. The password_compat library is also using a custom binary comparison instead of a simple === to thwart timing attacks.
If I understand your code correctly, the login-time code is generating a fresh salt, ignoring the one that's stored with the password. Using different salts to hash the same password will generate different hashes.
Either use a constant salt pepper (scroll to the bottom of this answer), as per #c2's answer:
function cryptPass($input, $rounds = 9)
{
return crypt($input, sprintf('$2y$%02d$mysalt$', $rounds));
}
$hash = cryptPass($pass);
Or use the same salt both times:
// Login time (register-time code is unchanged)
function cryptPass($input, $salt, $rounds = 9)
{
return crypt($input, sprintf('$2y$%02d$%s$', $rounds, $salt));
}
function checkPass($freshPass, $hashFromDatabase) {
$salt = explode('$', $hashfromDatabase, 5);
$salt = $salt[3];
return cryptPass($freshPass, $salt) === $hashFromDatabase;
}
I am having a serious issue with trying to validate my password when logging into my site. I am using php to create a blowfish encrypted password with salt using the code below.
<?php
function cryptPass($p, $rounds = 9) {
$salt = "";
$saltChars = array_merge(range('A','Z'),range('a','z'),range('0','9'));
for($i = 0; $i < 22; $i++){
$salt .= $saltChars[array_rand($saltChars)];
}
return crypt($p, sprintf('$2y$%02d$', $rounds) . $salt);
}
?>
This works fine and the crypted password is put into my mysql database. the problem is on login it will not validate. this is the login script.
if(isset($_POST["u"])){
// CONNECT TO THE DATABASE
include_once("php_includes/db_connect.php");
// GATHER THE POSTED DATA INTO LOCAL VARIABLES AND SANITIZE
$u = mysqli_real_escape_string($db_connect, $_POST['u']);
include_once("php_includes/hasher.php");
$p = (cryptPass($_POST['p']));
// GET USER IP ADDRESS
$ip = preg_replace('#[^0-9.]#', '', getenv('REMOTE_ADDR'));
// FORM DATA ERROR HANDLING
if($u == "" || $p == ""){
echo "login_failed";
exit();
} else {
// END FORM DATA ERROR HANDLING
$sql = "SELECT id, username, password FROM users WHERE username='$u' AND activated='1' LIMIT 1";
$query = mysqli_query($db_connect, $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 {
//goto the users account
should I not be running the cryptPass function on the incoming user data?
Also of note would be that the mysql database password column is set up as VARCHAR(255) so its got plenty of room. At this point the password crypts right, I am just not able to compare it to the one in database properly. This is my first real try with blowfish pieced together from tutorials all over, I wanted to get away from md5 as php.net advises. Any help would be greatly appreciated. Thanks in advance for reading this.
Here's a slightly more in-depth demonstration as what's found on the PHP crypt() man page:
// Only for demonstration, see mcrypt_create_iv() for a better salt:
// http://php.net/manual/en/function.mcrypt-create-iv.php
$salt = substr(sha1(date('r')), rand(0, 17), 22);
$cost = 10;
$hash = '$2y$' . $cost . '$' . $salt;
$pass = 'mypass';
$notpass = 'notmypass';
$hashed = crypt($pass, "$hash");
echo "
Hash:
$hash
Hashed:
$hashed
Verified:
" . crypt($pass, $hashed) . "
Not Verified:
" . crypt($notpass, $hashed);
https://ignite.io/code/51323c3aec221e7b73000000
Which gives (at least this time):
Hash:
$2y$10$a80ded6289240c2e41a5e4
Hashed:
$2y$10$a80ded6289240c2e41a5euUFPvmt.sb6lBwOE.JTAdxQsDWmmM.Me
Verified:
$2y$10$a80ded6289240c2e41a5euUFPvmt.sb6lBwOE.JTAdxQsDWmmM.Me
Not Verified:
$2y$10$a80ded6289240c2e41a5euj06Emi8HigWM6BpqVFZ.ZtpA9wK5c8G
To verify the password you need the salt that was used to create the first password hash. This salt is included in the output string of the crypt() function, and crypt can extract this salt from the password hash.
You can see well how it works when you look at the new hash functions from PHP 5.5 password_hash() and password_verify()...
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
$isPasswordCorrect = password_verify($password, $existingHashFromDb);
...the function that verifies the login password, needs the hash of the first password. It then can extract the salt and the cost factor from this string, to hash the login password with the same parameters.
I can recommend this new functions, there is a compatibility pack for earlier versions.
I am making a login system in PHP and I was wondering if this current hash function I have is secure enough.
public function genHash( $user, $pass )
{
$user = strtoupper($user);
$staticSalt = $this->staticSalt;
$dynamicSalt = hash('SHA512', md5($user . $pass) . sha1($pass) . hash('SHA512', $user . $pass));
$final = hash('WHIRLPOOL', $pass . $dynamicSalt . $staticSalt);
return $final;
}
The static salt is just a bunch of random characters. Anyway, how can I make it more secure?
You could use different salts for each user and store them in the database but besides that this system looks pretty secure. (Not knowing the details of the server).
EDIT:
Theoretically multihashing a string increases the chance of hash collisions but I haven't found anything reliable that says this is a practical risk.