Before I start I'd like to apologise for bringing up this subject once again, as many users did, but with a research I did, I wasn't happy with what I've found. I just hope to come up with something really helpful here.
Since md5 or sha1 are considered bad practice (even when using salts ???), I have tried to create this function for hashing my password
$password = $_POST['password']; // lets say that my password is: my_sercretp#ssword123
function encrypt_the_password($password){
$salt = "lorem_ipsumd0l0rs1t#m3tc0ns3ct3tur#d1p1sc1ng3lit";
return hash('sha256', $salt.$password);// can use also different algorithm like sha512 or whirlpool
}
$hashed_password = encrypt_the_password($password);
Note that this one I use it in a personal website with only one user, me. In case of having more than one users I come up with something like this:
$password = $_POST['password'];
function generate_salt() {
$salt = uniqid(md5("lorem_ipsumd0l0rs1t#m3tc0ns3ct3tur#d1p1sc1ng3lit".microtime()));
$salt = hash('sha256', $salt);// can use also different algorithm like sha512 or whirlpool
return $salt;
}
function encrypt_the_password($password,$salt){
return hash('sha256', $salt.$password);// can use also different algorithm like sha512 or whirlpool
}
$hashed_password = encrypt_the_password($password,generate_salt());
Is this secure enough (in each case) or can this improved more???
MY EDIT: I tried to come up with something new using the crypt() function. Here's my code in case of having a site with only one user, admin:
$password = $_POST['password'];
$salt = "L0r3mIpsUmD0l0rS1tAm3t";
$hashed_password = crypt($password', '$2a$12$' . $salt);
and in case of having a site with more than one users:
$password = $_POST['password'];
function generate_salt() {
$salt = uniqid(sha1("L0r3mIpsUmD0l0rS1tAm3tc0ns3CT3tur4d1p1sc1ng3lit".microtime()));
$salt = substr(sha1($salt), 0, 22);
return $salt;
}
$hashed_password = crypt($password', '$2a$12$' . generate_salt());
Is this ok or needs improvements???
Improve it by not making up your own algorithm. Your algorithm is insecure because your salt is constant and you only hash with one iteration of SHA256, which is computationally cheap.
Instead, use Bcrypt, which is both computationally expensive and verified by people who know what they're doing, so it's much safer than your solution.
You should use the password functions that will come inbuilt in PHP 5.5. There's a fallback library by ircmaxell that can provide the functions in earlier versions of PHP: https://github.com/ircmaxell/password_compat
It will always use the most recent hashing technique available, and in case even update the records for you. Make sure you read the README coming along with this library.
Do not make your own hashing function.
Related
I'v googled around for way to do this properly and there's just a lot of variations on how to do so. So i've come up with this and wouldn't mind some critique and links to better practices.
// Register Form - User providese username(email) password(text) //
So i grab the data:
$user = mysql_real_escape_string($_POST['user']);
$pswd = mysql_real_escape_string($_POST['pass']);
$salt = hash( 'sha256', microtime() . rand() );
$encrypt = hash( 'sha256', $pswd . $salt );
Then insert into database user_email | encrypted_pass | salt
// Login Form - User providese username(email) password(text) //
So first based on user(email) i grab encrypted_pass and salt info. Then,
$user = mysql_real_escape_string($_POST['user']);
$pswd = mysql_real_escape_string($_POST['pass']);
$encrypted_pass_fromDB = $var['encrypted_pass'];
$salt_fromDB = $var['salt'];
if (hash( 'sha256', $passwrd . $salt_fromDB) === $encrypted_pass_fromDB)
{
echo "GOT IT!";
}
I've read bcrypt is a better option, but for now i want to understand the SALT method better. Also, when i use $options = ['cost' => 11,]; i get an error Parse error: syntax error, unexpected '[' but that's a separate issue i guess. Used code based on PHP salt and hash SHA256 for login password
Any comments are appreciated! Thanks!
The only thing that you are protected against when adding a salt to your hash is the use of huge tables of pre-computed hashes called "Rainbow Tables". These have not been a major problem in quite some time, though because:
Rainbow tables containing extended character sets are massive, some requiring upwards of 16GB of RAM to search.
Parallelized bruteforce cracking across multiple computers, or offloaded to cloud services like AWS are faster, cheaper, and makes the addition of simple salts virtually inconsequential.
Better algorithms hash the password thousands of times and apply the given salt in a cryptographically "proper" way to make it more difficult to crack. However, the hashing algorithms that they are based on like SHA and MD5 are designed to be small and fast, and bruteforcing them requires large amounts of CPU time, which is cheap and easy to parallelize.
Bcrypt is different. It uses the Blowfish algorithm which requires relatively large amounts of RAM, which is expensive, and thus difficult to parallelize. This is why everyone recommends it so strongly.
TL;DR Hashing is better than plaintext, salted is better than unsalted, bcrypt is miles better than pretty much everything else out there so frickin use it.
You should use the built in crypt function:
http://php.net/crypt
You have two options:
Let PHP Crypt generate the salt
$user = mysql_real_escape_string($_POST['user']);
$pswd = mysql_real_escape_string($_POST['pass']);
//Salt is generated automatically
$encrypt = crypt( $pswd );
Generate the Salt yourself
$user = mysql_real_escape_string($_POST['user']);
$pswd = mysql_real_escape_string($_POST['pass']);
//These are the settings for the salt (Separated so you can understand it)
$algorithm = "2a";
$length = "12";
//Start the salt by specifying the algorithm and length
$salt = "$" . $algorithm . "$" . $length . "$";
//Add on random salt and make base64 adjusted for bcrypt's version
$salt .= substr( str_replace( "+", ".", base64_encode( mcrypt_create_iv( 128, MCRYPT_DEV_URANDOM ) ) ), 0, 22 );
//Encrypt with your generated salt
$encrypt = crypt( $pswd, $salt );
Verifying it is easy:
if ( $encrypted_pass_fromDB_with_salt === crypt( $passwrd, $encrypted_pass_fromDB_with_salt ) ) echo "ok";
PHP offers now such an easy way to generate safe password hashes, that we should use it, have a look at the function password_hash().
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
// 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($password, $existingHashFromDb);
Of course it is good to understand how a salt works (and how difficult it is to handle it correctly), so try it out but use the function above for your life system.
I'm trying to make register and log in forms having salt encryption, and I'm not really familiar with it. So everything is working except that log in can't recognize password so I'm pretty sure it's encryption problem. These are lines for register:
$hash = hash('sha256', $password1);
function createSalt()
{
$text = md5(uniqid(rand(), true));
return substr($text, 0, 3);
}
$salt = createSalt();
$password = hash('sha256', $salt . $hash);
and these are for login:
$userData = mysql_fetch_array($result, MYSQL_ASSOC);
$hash = hash('sha256', $userData['salt'] . hash('sha256', $password) );
if($hash != $userData['password'])
{
echo "Incorrect password";
}
Can anybody point the problem. Thanks!
Actually your code should work as far as i can see, though it is very unsafe!
Problem: SHA256 is not appropriate to hash passwords, because it is ways too fast. Use a slow key-derivation function like BCrypt.
Problem: A three character salt with only letters is nearly no protection.
Maybe your database field is smaller than 64 characters, or you are comparing different passwords. In every case there is an easier and safer way to hash passwords, just use the new functions password_hash() and password_verify(). There exists also a compatibility pack for earlier PHP versions.
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
// 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($password, $existingHashFromDb);
There are quite a few things wrong with this. For starters: Are you storing the salt with the password? If not, then passwords become unverifiable.
Security considerations:
hash('sha256', ... is insufficient; consider bcrypt, scrypt, or pbkdf2
https://github.com/DomBlack/php-scrypt
http://us2.php.net/password_hash
https://defuse.ca/php-pbkdf2.htm
$text = md5(uniqid(rand(), true)); Ever heard of openssl_random_pseudo_bytes()?
(Also, you shouldn't seek to decrypt passwords, only verify them.)
If you're not familiar with these concepts, play it safe and use a tried and true library.
I am developing a system using Codeigniter!
All I wanted to know is if it would be possible for someone to find out what the password is if he/she knows the function and steps I have used to generate the encrypted hash?
For now all I have to generate my hash strings is:
$pass = str_split($password, 2);
$hashPass = '';
foreach($pass as $p){
$hashPass .= md5($p);
}
Your hash method is not hash and its very bad idea.. You must hash your password strings!
Here is 2 pretty simple functions for that..
function hash_my_pass($password){
return generate_hash($password);
}
function generate_hash($password){
return hash('sha256', $password . substr($password, 1, 3));
# In this case I put to hash $password + some substr of the password..
# Its good when you hash pass to add something secret..
}
function check_password($password, $hashed_pass){
return generate_hash($password) == $hashed_pass;
}
$password = '123456789';
$hash = hash_my_pass($password);
echo $hash;#this hash you must keep at your DB.
#when user login just compare his pass with the hash from your DB
var_dump(check_password($password, $hash));
Honestly if you are not using Bcrypt in the year 2013 then passwords will be vulnerable. What you have going at the moment is quite low grade if any grade at that matter in terms of "encryption".
I use CodeIgniter with Bcrypt with this class
Then all you have to do is call this file bcrypt.php and then the class name is :
class Bcrypt extends CI_Controller {............}
Keep in mind though with php 5.5 > the new password hashing functions will be supported which will automatically use Bcrypt until a stronger method comes out. Info here
Good luck and at the end of the day stop trying to roll your own "encryption/hashing" algorithms / methods / disasters. Doing so might leave your clients vulnerable.
If they know the actual method of encryption, they have an easiert time hacking it.
For all hashes there exist rainbow tables for instance, which allow for fast reverting of passwords. That's why hashed password usually get salted.
str_split on the other hand is not a hash function, as far as i know.
look at Ion_auth http://benedmunds.com/ion_auth/ and use the bcrypt option - password hashing isn't something to try to create yourself.
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 am creating a custom CMS and have built a login system and was wandering how vulnerable hashing the passwords this way would be compared to just using the md5 php function like this:
<?php $token = md5($salt . $password . $pepper); ?>
Most people just add a salt but adding pepper just makes sense if your going to add salt :)
Here is how I am doing it
<?php $token = hash_hmac('sha512', $salt . $password . $pepper, $key); ?>
The $key would be a value in the database that is unique to each user.
The $salt and the $pepper are randomly generated strings.
The $password is the password of course.
Added on 07/24/09
Thanks for all your responses. Does anyone have an examples of how they do a hash script for creating passwords to store in a database?
Similar to: https://stackoverflow.com/questions/1111494
Make sure you read this:
http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/
And this:
bcrypt is obsolete
Your method is using a stronger hash.
I don't see you opening yourself to any extra vulnerabilities.
MD5 is not suitable for any cryptographic purpose, use SHA-1 or preferable SHA-256.
http://www.mscs.dal.ca/~selinger/md5collision/