This question already has answers here:
Secure hash and salt for PHP passwords
(14 answers)
Closed 9 years ago.
I have found an article with the code below on the web I want to use to learn more php/mysql...
$username = 'Admin';
$password = 'gf45_gdf#4hg';
$salt = hash('sha256', uniqid(mt_rand(), true) . 'a random string will go here' . strtolower($username));
$hash = $salt . $password;
for ( $i = 0; $i < 100000; $i ++ ) {
$hash = hash('sha256', $hash); }
$hash = $salt . $hash;
How would I validate the password in PHP when a user wants to log in?
You would run the exact same procedure and see if the results match.
This is a general procedure for seeing if a sumbitted password stores a matched password.
You create a function which hashes and stores the known password, and typically salts it as well
You store that in the database
When the user submits a password to login, you run it through the exact same hashing and salting algorithm, and see if the resulting hash matches the hash stored in the database
You should also consider using bcrypt instead: How do you use bcrypt for hashing passwords in PHP?
It's recommended to compose a function within PHP that similarly mimics the process you've outlined above. That way, when you're attempting to validate submitted credentials, you will run the password through the same hashing process as it was during conception with the exception of generating the random salt.
Related
This question already has answers here:
Using PHP 5.5's password_hash and password_verify function
(4 answers)
Closed 7 years ago.
I am thinking of using password_hash() function to encrypt user passwords. I understand that this function generates salt by default if you don't provide it, and it is even encouraged to use the default salt instead of your own. I am currently weighing in 3 options and can't decide which one to go with so I'd appreciate it if you could help me out.
1. option: password_hash() with default salt
$passwordInput = $_POST['password'];
$passwordHash = password_hash($passwordInput, PASSWORD_BCRYPT);
//INSERT $passwordHash INTO DATABASE
2. option: password_hash() with custom salt
$options = ['salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM)];
$passwordInput = $_POST['password'];
$passwordHash = password_hash($passwordInput, PASSWORD_BCRYPT, $options);
//INSERT $passwordHash INTO DATABASE
3. option: not using password_hash() at all
I am basing this option on a post from 2014: The definitive guide to form-based website authentication. Basically if it is a more secure approach than password_hash() I'd use something like this:
$salt = uniqid(rand(0, 1000000);
$passwordInput = $_POST['password'];
$password = hash('sha512', $salt . $passwordInput);
//INSERT $password AND $salt INTO DATABASE SEPARATELY
The really short answer to this question is to use password_hash() with the default salt (your first option), custom salt is deprecated in PHP7 because, to quote php.net:
The salt option for the password_hash() function has been deprecated to prevent developers from generating their own (usually insecure) salts. The function itself generates a cryptographically secure salt when no salt is provided by the developer - therefore custom salt generation should not be needed.
By the same token, your third option, hash() should be avoided as again you'll need to generate your own salt.
This question already has an answer here:
How to check a mysql encrypt value with a salt in PHP?
(1 answer)
Closed 9 years ago.
I would like to encrypt some passwords and put it in database. How do I keep this stuff in a database so I can retrieve the data if the owner matches.
Example
<?php
// some validations and other staff
$data = $_POST['input'];
$hash = crypt($data);
//then database insert code
?>
If I echo the $hash, it's giving me some encrypted data but when I refresh the page, the numbers are changing from time to time. How do I keep the data static? How will I tell the encrypted password that this was the owner when username and password entered.
Example
<?php
//time of encryption
$name = "someone";
$pass = "p1x6Fui0p>j";
$hash = "$pass"; //outcome of $hash e.g. $1$aD2.bo0.$S93XNfgOFLskhis0qjE.Q/
// $hash and $name inserted in database
?>
When the user tries to login with collect details, how will I refer $hash "$1$aD2.bo0.$S93XNfgOFLskhis0qjE.Q/" was equal to $pass "p1x6Fui0p>j" ?
crypt() has an unfortunate name. It's not an encryption function, but a one-way hashing function.
If you're using PHP 5.5+, just use password_hash and password_verify:
$hash = password_hash($data, PASSWORD_BCRYPT); // Bcrypt is slow, which is good
And to verify the entered password:
if (password_verify($pass, $hash)) {
// The password is correct
}
Now to answer your actual question: the purpose of password hashing is to authenticate users without actually storing their plaintext passwords. If hash(a) == hash(b), then you can be pretty sure that a == b. In your case, you already have hash(a) ($hash), so you just need to hash the inputted password and compare the resulting hashes.
crypt() does this for you:
if (crypt($pass, $hash) === $hash) {
// The password is correct
}
From the php crypt page
if (crypt($user_input, $hashed_password) == $hashed_password) {
echo "Password verified!";
}
You are not using your own salt, so for every call salt is automatically generated, and salted password is hashed. To get the same hash from this password, you need to run crypt with exact salt that was generated during first run.
Generated salt varies depending on algorithm used for hashing, but from your example it's MD5, and salt is delimited by first and third dollar sign inclusively:
$hash = '$1$aD2.bo0.$S93XNfgOFLskhis0qjE.Q/';
// \ salt /
So to get Exact same hash you need to call crypt($pass, '$1$aD2.bo0.$');
Remember that if you want to use your own salt, it needs to be in proper format for given algorithm. For best results use php 5.5+ password_hash mentioned by #Blender, and for older php versions there is password_compat library, with this you don't have to worry about proper salt format.
This question already has answers here:
How do you use bcrypt for hashing passwords in PHP? [duplicate]
(11 answers)
Closed 9 years ago.
I have a PHP login script with salt on the database, but in my register script I see:
$qry = "INSERT INTO accounts(username, firstname, lastname, password) " .
VALUES('$username','$fname','$lname','" . md5($_POST['password']) . "')";
and for the login:
$qry="SELECT * FROM accounts WHERE username='$username' AND password='" .
md5($_POST['password']) . "'";
Is there some code that can replace the MD5? Something more secure?
I've heard of SHA1 or something.
Short answer
Use bcrypt not md5 or sha1
Longer answer
Using the crypt() is hard. There is a new PHP password hashing API coming in PHP version 5.5, you can read about it here:
https://gist.github.com/nikic/3707231
It uses bcrypt and makes the whole process very easy. Of course php 5.5 isn't ready yet, so in the meantime there is a library to provide this new API right now:
https://github.com/ircmaxell/password_compat
Edit: See this thread for a much more thorough answer on the topic:
How do you use bcrypt for hashing passwords in PHP?
In consideration of #jszbody post, you should also update your password field to tell you want scheme you're using.
Where you have an MD5 hash now, you might have just "BAC232BC1334DE" or something.
When you go to SHA or whatever, you should change it to: "SHA:YOURSHAHASHHERE".
Because you can't change any of your existing passwords right now. This will make it more backward compatible, since now you can support both schemes.
Since you get the original password during login, you can dynamically upgrade your passwords in place as people login.
You get your user record, check the password. If there is no scheme, use MD5, and compare passwords. If they're correct (i.e. they can log in), you can update their old MD5 password to the new SHA password.
Also, it seems you are not salting your passwords. You must salt your passwords so that when Mary Sue uses "ilovekittens" for her password, and Big Jake Mahoney uses "ilovekittens" as his password, you don't get the same has for identical passwords.
You can store the salt in the password as well: "SHA:RANDOMSALTCHARACTERS:YOURSALTEDHASHHERE".
Salting is highly recommended. Unsalted, it pretty much doesn't matter a whole lot what scheme you use.
Try using the following class:
<?php
class PassHash {
// blowfish
private static $algo = '$2a';
// cost parameter
private static $cost = '$31';
// mainly for internal use
public static function unique_salt() {
return substr(sha1(mt_rand()),0,22);
}
// this will be used to generate a hash
public static function hash($password) {
return crypt($password,
self::$algo .
self::$cost .
'$' . self::unique_salt());
}
// this will be used to compare a password against a hash
public static function check_password($hash, $password) {
$full_salt = substr($hash, 0, 29);
$new_hash = crypt($password, $full_salt);
return ($hash == $new_hash);
}
}
?>
include it in your page with the following:
include_once('passhash.class.php');
Hash the password by:
PassHash::hash("test");
And check it with:
if (PassHash::check_password($databasepassword, $formpassword)){
// do stuff
}
This function uses Blowfish encryption. For more information on Blowfish goto PHP.net/crypt
Blowfish is considered the most effective yet most powerfull way of encrypting passwords. Do not use MD5 or SHA1 without using a salt!
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do you use bcrypt for hashing passwords in PHP?
What is the secure way or hash function to store password to Mysql Database? Now I'm using this sha1() function to store my password to DB with following code. Is it really Safe?
<?php
$pass = 123456789;
$pass = sha1($pass);
echo $pass;
?>
Thanks for your advise.
Update
I see salt is something like this.
$salt = "this is a salt";
$password = 'this is an password';
$hash = sha1($salt.$password);
So, Can i use any number/random number/something to $salt value? After that is it Now SAFE?
The SHA* variants should not be used for password hashing. Use the Blowfish algorithm and the crypt() function.
phpass is a PHP password hashing library that can simplify this for you.
You could also do more research on the topic and write some code to generate your own Bcrypt/Blowfish compatible Salts and use crypt() directly, rather than using the phpass library.
The best (and recommended) way of hashing passwords in PHP is using crypt().
Here's a simple example from the PHP documentation:
$hashed_password = crypt('mypassword');
// now store $hashed_password in the database
Later, to check an entered password (assuming $user_input is the entered password):
// retrieve $hashed_password from the database, then:
if (crypt($user_input, $hashed_password) == $hashed_password) {
echo "Password verified!";
}
Note that in this example (above) the salt is automatically generated when the password is first hashed. This is dangerous and should be avoided. A pseudo-random salt should be provided and could be generated like so:
$salt = substr(str_replace('+', '.', base64_encode(pack('N4', mt_rand(), mt_rand(), mt_rand(), mt_rand()))), 0, 22);
For a much better explanation, see the Stack Overflow question linked by citricsquid.
You cannot use a random value for salt, since you wont be able to compare the inputed password and the one stored in database afterwards.
You encryption is mainly ok, but you can go real crazy if you want...
<?php
$salt = "fF#$GGG$T##4309g9jERGWrgrew#GH";
$pepper = "vV###V90Ù39009gfjigwjorn)(";
$pass = "123456789";
$pass = $salt.$pass.$pepper;
for ($i=0;$i<40;$i++){
$pass = hash("sha256", $pass)
}
echo $pass;
?>
I'm trying to transition to Blowfish for an authentication system. Bear with me, I'm not a cryptographer and my understanding of Blowfish is not quite there yet.
The current setup uses sha1 and salts. The salts are generated for each user and stored in the database. It boils down to this:
$salt = $this->getSalt($username);
$hash = sha1($password . $salt);
if ($hash == $hashInDB)
{
// user is authenticated, set session id etc ...
}
The getSalt() method gets the salt stored in the database for the specified user.
Now if I understand everything correctly, with crypt I should be doing:
$salt = '$2a$07$' . $this->getSalt($username) . '$';
$hash = crypt($password, $salt);
if ($hash == crypt($password, $saltInDB))
{
// The user is authenticated, set session id etc..
}
To clarify, for the second example the $saltInDB variable, is a value like `'$2a$07$arandomsaltcreatedatregistration$'.
Am I doing it right?
Your example is almost correct.
When you create a hash with the crypt() function, you will see that the used parameters (algorithm, cost and salt) are part of the generated hash (the begin of the hash):
$2a$07$LCzy1mE0b9lS8Uyx9HEeUgHm8zH1iDDZ5...
That means, you can replace $saltInDB with $hashInDB, the crypt() function will extract the needed parameters automatically from $hashInDB. This also answers your question about storing the salt, just store the hash value in the database, the salt is included there. And yes you should generate a new salt for each password.
The '$' after the salt is not needed.
More information about how to generate a bcrypt-hash you can find here, if you are looking for a well established library, i can recommend phpass.