This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Mitchfizz05's profile picture

[Php/lua] Best Way To Hash Passwords.

Started by Mitchfizz05, 26 July 2013 - 09:30 AM
Mitchfizz05 #1
Posted 26 July 2013 - 11:30 AM
I know this isn't completely ComputerCraft, but it is related to a ComputerCraft project - and I know that there are many people on these forums that are quite knowledgeable about PHP password hashing, and security.

I want to know what the best way is to secure passwords.
Currently I md5 the password, then hash it with sha256, it that good enough? Would YOU sign up for something with that sort of security.

Thanks, Mitchfizz05.
Zudo #2
Posted 26 July 2013 - 11:42 AM
Sounds pretty good to me, but I am a noob too :)/>
Thib0704 #3
Posted 26 July 2013 - 12:11 PM
Hi,
TheOriginalBit Suggested me to use This

$salt = hash("sha256",mcrypt_create_iv(64));

  // and then encrypt the password

$encrypted = hash("sha256", $inputPass . $salt)


If you need the hole script here it is :

<?php
		// make sure we can redirect (this was just a nice little function that made redirects nicer to user over and over)
		// for your case you would most likely use die("why it died") so that the browser gets the error, and computercraft gets the error message
		// so that you can tell your user why the registration failed
		// NOTE: the scripts at the other end are designed to receive a GET, which is why the redirects are formatted in the way they are (plus its easier to do GET than POST from PHP)
		require_once($_SERVER['DOCUMENT_ROOT'] . "eta/functions/redirect.php");
		if (!isset($_POST['rpass'])){ redirect('index.php?e'); }
		// The salt is just a bunch of random data to help further hide the hashed password and make it harder to do a lookup on the hashed password
		// each user has a different salt so that even two passwords if the same, have different hashed values
		$salt = hash("sha256",mcrypt_create_iv(64));
		// get the register details from the post data
		$input_username = urldecode($_POST["user"]);
		$input_email = urldecode($_POST["email"]);
		$input_password = urldecode($_POST["pass"]);
		$input_repeat_password = urldecode($_POST["rpass"]);
		// deleted variable validation... not needed for this example to you Thib0704
		// create a new mysql connection
		$connection = new mysqli($db_host, $db_user, $db_pass, $db_name);
		// make sure there is a connection
		if (mysqli_connect_error()) { redirect('register.php?d'); }
		// create a prepared statement to check if the username exists already, the ? is where values will end up going
		$query = "SELECT COUNT(username) FROM user WHERE username = ?;";
		// create the statement
		$stmt = $connection->prepare($query);
		// fill in the blanks that were in the query, i.e. place the username in the ? ... s means string, there are other letters for other data types
		$stmt->bind_param("s", $input_username);
		// check if the execution succeeded
		if (!$stmt->execute()){ redirect('register.php?d'); }
		// bind the returned data to variables, this gets the return result from the database and adds it into the $usersWithThatName variable
		$stmt->bind_result($usersWithThatName);
		// complete the process
		$stmt->fetch();
		// make sure no other users have the same username
		if($usersWithThatName != 0){ redirect('register.php?x'); }
		// close the mysql statement, don't close the connection, we have more to do still
		$stmt->close();
		// create a prepared statement to make sure the email hasn't been used before, the process is exactly the same as above
		$query = "SELECT COUNT(email) FROM user WHERE email = ?;";
		$stmt = $connection->prepare($query);
		$stmt->bind_param("s", $input_email);
		if (!$stmt->execute()){ redirect('register.php?d'); }
		$stmt->bind_result($usersWithThatEmail);
		$stmt->fetch();
		if($usersWithThatEmail != 0){ redirect('register.php?l'); }
		$stmt->close();
		// append the salt to the input password and then hash it, making sure to use the same hashing algorithm otherwise the weakest link is the lower hash algo
		$hashed_password = hash("sha256", $input_password . $salt);
		// create a prepared statement to insert many variables into the table (we have to insert the salt so we can know what the users salt is later)
		$insert_stmt = "INSERT INTO user (username, password, salt, email, securityLevel) VALUES(?, ?, ?, ?, 1);";
		$stmt = $connection->prepare($insert_stmt);
		// now notice that we have an 's' per ?, so for each ? you must have a value to put into it, again this is a bad example because all we used were varchar2 everywhere
		// as that was all we needed to use, but there are other letters for other data types
		$stmt->bind_param("ssss", $input_username, $hashed_password, $salt, $input_email);
		if (!$stmt->execute()){ redirect('register.php?d'); }
		// I left this in just so you could see that you can get the primary key of the result, in this case for us it was a number as the unique user id and we then made
		// a folder for them on the server
		$userId = $connection->insert_id;
		mkdir($_SERVER['DOCUMENT_ROOT'] . 'eta/user_data/' . $userId);
		// this line takes us back to a page, but below the closing php tag you could just have html code like "registration successful" and that is:
		// 1 what the browser will show and
		// 2 the only text computercraft will get back
		redirect('index.php?s');
?>
Lyqyd #4
Posted 26 July 2013 - 12:32 PM
Moved to General.
Imque #5
Posted 29 July 2013 - 02:01 AM
Hashing with SHA2 and using a salt is very secure. I mostly hash in SHA512 with a salt.
jesusthekiller #6
Posted 29 July 2013 - 04:36 AM
I md5 the password,
It won't be safe at all…
ElvishJerricco #7
Posted 29 July 2013 - 05:29 AM
I md5 the password,
It won't be safe at all…

md5 isn't the tell of bad security. md5 isn't too much worse than sha256 because they can both be compromised by a rainbow table, although md5 is much more discovered by now. But doubling up with two like OP said would help an awful lot until a hacker was able to penetrate and determine the method of hashing used. That's why using a salt that's difficult for the hacker to obtain is good.
theoriginalbit #8
Posted 29 July 2013 - 05:34 AM
Sorry to be harsh, but no I wouldn't sign up to a service that uses MD5, or multiple hashing algorithms (unless I was completely oblivious to their methods)

Also it needs to be pointed out here that the hash will only be as strong as the weakest hash… Hashing with multiple algorithms reduces entropy, not increases it… A good article to read up about this can be found here

If you're wanting to hash multiple times then you're best to use the same algorithm.

In terms of security MD5 and SHA-1 are easily attacked with rainbow tables, the SHA-2 family (SHA-256/SHA-512) is a lot more secure and there have been no successful attacks on the SHA-2 family, they did however decide to make a SHA3 algorithm, even though there was no need for it.

If you're willing to wait, and make your user wait, and it's activated on the server, you can use an algorithm in PHP called mcrypt, it is a lot stronger against attackers because of the way they must attempt to gain the passwords.

When dealing with hashing passwords there is another method of securing the hash which requires applying a salt to the password. This salt can be applied where ever in the password you wish, however it must be applied in the same spot each time. A salt is normally some kind of random numbers and letters that mean the chance of an attacker having the direct lookup for that password (no matter how insecure) is a lot less likely…

One thing to note is that if two people have the password, "password123", the output that is stored in the database will be the same, to circumvent this we can create a random salt system so that each time a password is hashed, it will be different, even if the passwords are the same. However the drawback of this system is that we obviously need to store that salt somewhere so that in the future the users input can be salted with it to compare the passwords, which of course adds it's own security risks as if someone has access to your database, they have access to the salts for the passwords too.

As you can see in the example that Thib posted, which contains some code I sent him, to create the salt I use the above method, and actually hash a random byte stream with `mcrypt_create_iv` which I then apply to the password and hash the password + salt. This password and the salt is then stored in the database.

Obviously one of the most secure methods of making sure that the passwords are safe, is by cutting your database off from the outside world. Only allowing `localhost` access to your database is one of the best decisions that you can make as it means that only the PHP files on your server have access.


md5 isn't the tell of bad security. md5 isn't too much worse than sha256 because they can both be compromised by a rainbow table, although md5 is much more discovered by now.
MD5 is actually much worse than SHA256. It is not just about how they can be compromised by a rainbow table, but it is also about the amount of collisions in the hashes.

But doubling up with two like OP said would help an awful lot
As I stated above, this actually reduces entropy, not increases it… The hash is only as strong as its weakest link…
jesusthekiller #9
Posted 29 July 2013 - 05:55 AM
I use on my website something like this:


local last = password
for i=1,1000 do
  last = sha2(last..salt)
end
return last

It's a bit too much tho :P/>
theoriginalbit #10
Posted 29 July 2013 - 07:35 AM
I use on my website something like this:


local last = password
for i=1,1000 do
  last = sha2(last..salt)
end
return last

It's a bit too much tho :P/>
You use Lua on your website? o.O and yes, it's a little extreme, it doesn't increase entropy, but it doesn't decrease it either.
jesusthekiller #11
Posted 29 July 2013 - 11:55 AM
I don't, just haven't used PHP since december - it was easier for me to write it in Lua :P/>
And it makes sense - if someone got my database, it would take ages to brute-force pasword :)/>