Basic hashing of passwords is poor. LinkedIn should have expected that one day that their password list would be stolen and when that happened it should have been hashed better so a standard dictionary could not reverse the passwords. Tthe LinkedIn passwords were leaked all over internet and with the help of crowd-sourced hackers the passwords were easily reversed back from SHA-1 hashes substrings to the plain text passwords. With tools like John the Ripper social hackers like Francois Pesce was able to reverse over 2 million LinkedIn passwords.

This is a really important lesson to software engineers, even the biggest get hacked. So all we can do is put things in place to minimise the damage hackers can do, which lets face there is a millions of hacker far smarter than me and know way more than me about security holes.

Below is a class I have built that takes the password, adds some salt, which is variable based on the length of the password, changes it up a bit applies the first hash and scrambles the hash and adds some more salt then applies a second hash. All of this is done in 1 / 10000th of a second.

Download the source code.

Preview a demo.

class password_hash{

	/*
	*	hide_password is designed to take a password and scrumble it
	*	this to overcome standard password hashing like MD5 which
	*	dictionaries have been created to reverse it.
	*	this will turn my_password into 80990593eeb87f8db0c90dac271146f0551208bb
	*/
	function hide_password($password='')
	{
		$salt_words=array( //change this list of words to what ever you want
			'Duck!',
			'rEd#',
			'liT%Tle',
			'FiRe!',
			'B!o0k',
			'o^p^3^n',
			'w4&t&eR',
			);

		$salt_words_reversed=array_reverse($salt_words);//this is for our second salting

		$password_length=strlen($password);//get the length

		//avoid using a consistant salt word by dividing the length of the password by the size salt words and use the remainer to select a word
		$salt_word=$salt_words[$password_length%sizeof($salt_words)];
		$second_salt_word=$salt_words_reversed[$password_length%sizeof($salt_words_reversed)];

		//make the password a little scrumbled
		$scrumbled_password=$salt_word.($password_length%2).$password.$password_length;//e.g. my_password becomes B!o0k1my_password11

		//it is still pretty easy to see the password so lets use a standard hash
		$hidden_password=md5($scrumbled_password);//e.g. Bo0k1my_password11 becomes 949c0cc48ba92864c0bf0acc5d984420

		/*
		*	that seems like it is secure except a standard Linux
		*	dictionary tool could still reverse that by brute force e.g.
		*	check out https://community.qualys.com/blogs/securitylabs/2012/06/08/lessons-learned-from-cracking-2-million-linkedin-passwords
		*	where the author uses a 10 year old John the Ripper app which
		*	cracks through the basic logic of password salting
		*/

		//lets just make it a little more confusing
		$hidden_password_reversed=strrev($hidden_password);//949c0cc48ba92864c0bf0acc5d984420 becomes 024489d5cca0fb0c46829ab84cc0c949

		//and a bit more
		$hidden_password_reversed_swapped_around=substr($hidden_password_reversed, 16, 16) . $second_salt_word . substr($hidden_password_reversed, 16, 16);
		//024489d5cca0fb0c46829ab84cc0c949 becomes 46829ab84cc0c949liT%Tle46829ab84cc0c949

		//one more hash for good measure, using the hash of LinkedIn =P
		$final_hash=sha1($hidden_password_reversed_swapped_around);//our final result is 80990593eeb87f8db0c90dac271146f0551208bb

		/*
		*	In this example we have a turned my_password into 80990593eeb87f8db0c90dac271146f0551208bb
		*	which without knowing the algorithm would be almost impossible to brute force reverse
		*/

		return $final_hash;
	}

	//just to time the tool for those haters that want to complain about load time
	private $start_time;
	function __construct()// construct is the method called when a new main object is created
	{
		$this->start_time=microtime(true);
	}
	function __destruct()// destruct is the method called when a main object is released
	{
		$execution=round(microtime(true)-$this->start_time, 4);
		echo "nloaded in $execution seconds";
	}
}

If you do use it play around with different words, hash algorithms etc.

A really basic example of using the class:

$hash='';
$password='';
if(isset($_POST['password']))
{
	include_once('class.password_hash.php');
	$password_helper=new password_hash;
	$hash=$password_helper->hide_password($_POST['password']);
	$password=$_POST['password'];
	echo $password . " became " . $hash;
}

Basically you are check if a password was sent and if so load the class, create a new object, create a hash and display the original and the hash to the user.

Advertisements

6 thoughts on “Password Hashing – With some smart salt

  1. s/secrete/secret/g

    s/SHA-1 hashes substrings/SHA-1 hash substrings/

    s/Pesce was able/Pesce were able/

    s/face there is a millions/face it there are millions/

    “which lets face [it] there [are] millions of hacker far smarter than me”

    Which is exactly why you should not be writing your own password hashing class. Your class contains at least two obvious errors:

    1) you salt from a short, fixed, set of strings – to properly be effective a salt needs to be a large, truly random, value, not a pick from a short word list;

    2) your comment about avoiding using a consistent salt word does not match your code, your code will always pick the same salt word for a same size password, because the result of dividing a length 10 password by a length 20 word list will always be the same remainder value;

    3) you state that this all happens in “1 / 10000th” of a second, which shows why you should not be writing your own password hash class. Anyone with a GPU and the willingness to implement your weak algorithm would be able to brute force many passwords hashed with your algorithm in very little time. In order to be resistant to brute force, the hash function must take a considerable amount of time to compute, sufficient time that an attacker with a GPU array can’t check 4 billion passwords per minute.

    What your code is instead is an excellent example of why someone should simply pick one of PKBDF, bcrypt, or script, and use that instead.

  2. That’s not the way to do it either. You’re only using a small number of salts, so the likelyhood of two passwords using the same salt is increased. Salts should be randomly generated per password if you’re going to use them. The idea behind salts is to prevent the use of rainbow tables, but if passwords are sharing salts then I can generate a rainbow table for that salt and use it to crack all those passwords.

    “which without knowing the algorithm would be almost impossible to brute force”. Security through obscurity is also almost never desirable when dealing with cryptography. If you’re not using a standard algorithm who knows how many security holes you’ve managed to introduce. In your example the swapping around of the hash string could undo some of the diffusion of the md5, and then applying a sha1 pass might increase the number of collisions you produce, meaning a brute force may be more likely to produce a viable password even if it isn’t the original.

    Finally, speed is not a good thing either when referring to password hashing. The faster a password can be hashed, the faster it can be cracked using brute force. Use an adaptive password hashing algorithm rather than a generalized hashing algorithm. See How To Safely Store A Password for more details.

    The really important lesson to take from the LinkedIn crack is to never ever ever roll your own solution. Always use a standardized password hashing scheme, bcrypt or PBKDF2 preferably.

    1. Some really good points – though I think you may have missed some of the comments in the source.

      Also it is possible to build hash tables for bcrypt and PBKDF2 which are ultra-fast.

      1. The comments, while explaining why you’ve done what you’ve done, don’t make what you’ve done any less wrong.

        As for hash tables for bcrypt and PBKDF2, yes it would be possible to build them, however for bcrypt at least it would be pointless, I don’t know the details of PBKDF2. bcrypt already includes a salt, so you’d be building a table just to crack a single password (assuming you’re generating salts properly) and building the table would be slow (assuming you’re using a decent number of rounds). The whole point of password hashing is to make the password as impractical as possible to crack. In the beginning passwords were just hashed, but then crackers started using rainbow tables. So passwords were hashed with salts, then GPUs started to be able to brute force billions of passwords a second. So now we (should!) use hash functions with an adaptable number of rounds in them to hash a password with a salt. This prevents the use of rainbow tables, because we’re using a salt, and slows down the brute forcing because calculating each hash takes longer.

      1. Better but still not right. The salt needs to be randomly generated per password. That means a random series of bytes, and a different salt for every single password. As soon as you’ve got a repeated salt you’re opening yourself up to rainbow tables.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s