PHP Password Salt and Pepper using sha1 MD5 Hash

battery salt and pepper shakers

Adding salt to passwords has become a very popular topic. In this tutorial we will look at adding more then just a little salt in hope to make the passwords stored in the database a lot more complicated to break.

What we aim to do is change “HelloKitty” into “bd6656780b4fcad95b4326dd6ee46cbcdb4d8a”.

This is the final code:
[cc lang=”PHP”]
$pepper=”HelloKitty”;
echo saltPlease($pepper);
function saltPlease($pepper){
$salt=0; //create some salt
$dinner=$pepper; //add our pepper to our dinner
$pepper= preg_split(‘//’, $pepper, -1, PREG_SPLIT_NO_EMPTY); //split out the pepper into an array
foreach($pepper as $key => $value){
$salt+=ord($value); //get the ascii values of our pepper
}
$sodium = $salt % 4;
$salt = $salt % 5; //devide the salt by 5 and return the remainder
if($salt==0){$salt=”Dawdlerubefacient”;} //based on the salt value we will choose the type of salt
if($salt==1){$salt=”Slubbingbilly”;}
if($salt==2){$salt=”fearsomeTogo”;}
if($salt==3){$salt=”cephushandclasp”;}
if($salt==4){$salt=”Conquestpriggishness”;}
if($sodium==0){$sodium=”earnestnessClovehook”;} //based on the salt value we will choose the type of salt
if($sodium==1){$sodium=”GyroseAcclamation”;}
if($sodium==2){$sodium=”cartelhorsebarn”;}
if($sodium==3){$sodium=”Chivieddulles”;}
$dinner=md5($salt) . sha1($dinner) . hash(‘sha256’,$sodium);//add the salt to our dinner and mix it right up
$dinner=sha1($dinner);//mix our dinner up some more
return $dinner;
}
[/cc]

The common stories in the media about hacking related to simple scripts being used to get access a database with unencoded passwords. Generally the sites broken into are less popular sites which have not seriously considered security, or thought the cost was too much. The hackers hope the users have used the same password, username and email address for other sites they are a member of such as FaceBook. Adding salt to stored passwords and using an encryption method has proven to be floored as md5 has been reversed engineered and the salt is pretty much the same as it becomes obvious that the word “salt” is on the start of every password.

The Create My solution was to make it just that little bit more annoying and complicated to reverse adding enough deterrents for the hackers just find the time to break the encoding just too annoying. Along with encoding the password in the database you need to add SQL injection protection measures.

The Solution
The solution is composed of a method to make a fairly random raw password and then a highly encrypted password using several encryption methods.

Method

  1. Analysis of the password to find a number using the sum of the ASCII values
  2. The results is divided by 5 and the remainder is used for the salt and divided by 4 and the remainder is used for the sodium (I recommend much higher values used)
  3. The value of the salt and sodium is used to select some random text (the higher the division the more values which need to be added
  4. The salt, dinner and sodium is encrypted using three different methods and concatenated to make a very long encrypted password
  5. Once more the password is encrypted just for good measure

Code Broken Down

First $pepper (the password) is set to HelloKitty and the second line is to print the result of the encryption of $pepper.
[cc lang=”PHP”]
$pepper=”HelloKitty”;
echo saltPlease($pepper);
[/cc]

Next we have our function saltPlease. We set salt to 0 and add the $pepper to the $dinner. $salt = 0, $pepper=”HelloKitty” and $dinner=”HelloKitty”.
[cc lang=”PHP”]
function saltPlease($pepper){
$salt=0; //create some salt
$dinner=$pepper; //add our pepper to our dinner
[/cc]

To create some randomness to the password while maintaining the structure the ASCII values are summed up to produce a value. First the $pepper string is transposed into an array then each ASCII value is derived using the ord() function. $pepper = ‘H’,’e’,’l’,’l’,’o’,’K’,’i’,’t’,’t’,’y’ and $salt=1033

[cc lang=”PHP”]
$pepper= preg_split(‘//’, $pepper, -1, PREG_SPLIT_NO_EMPTY); //split out the pepper into an array
foreach($pepper as $key => $value){
$salt+=ord($value); //get the ascii values of our pepper
}
[/cc]

Using the MOD operator (%) we are able to set the sodium and salt to the remainder of the value of salt divided by 4 and 5 retrospectively. Sodium and Salt should be different so you don’t always have the same salt with the same sodium. I recommend using much higher values then 4 and 5. $salt=3 and $sodium=1.

[cc lang=”PHP”]
$sodium = $salt % 4;
$salt = $salt % 5; //devide the salt by 5 and return the remainder
[/cc]

As 5 was used for the salt, it is set to one of the following 5 values. $salt=”cephushandclasp”

[cc lang=”PHP”]
if($salt==0){$salt=”Dawdlerubefacient”;} //based on the salt value we will choose the type of salt
if($salt==1){$salt=”Slubbingbilly”;}
if($salt==2){$salt=”fearsomeTogo”;}
if($salt==3){$salt=”cephushandclasp”;}
if($salt==4){$salt=”Conquestpriggishness”;}
[/cc]

As 4 was used for the sodium, it is set to one of the following 4 values. $sodium=”GyroseAcclamation”

[cc lang=”PHP”]
if($sodium==0){$sodium=”earnestnessClovehook”;} //based on the salt value we will choose the type of sodium
if($sodium==1){$sodium=”GyroseAcclamation”;}
if($sodium==2){$sodium=”cartelhorsebarn”;}
if($sodium==3){$sodium=”Chivieddulles”;}
[/cc]

This is where it get a little crazy.

md5($salt)=cc92e6fbd43788cac81ed0e78ab63f47
sha1($dinner)=5aa28664dfab74ba2d0ad632df19fc3150333a73
hash(‘sha256’,$sodium)=5df3ce0c86289881f9ff983a7c63676c7cc836de8a75a60b2d7ca1ec0af59508
$dinner=cc92e6fbd43788cac81ed0e78ab63f475aa28664dfab74ba2d0ad632df19fc3150333a735df3ce0c86289881f9ff983a7c63676c7cc836de8a75a60b2d7ca1ec0af59508

[cc lang=”PHP”]
$dinner=md5($salt) . sha1($dinner) . hash(‘sha256’,$sodium);//add the salt to our dinner and mix it right up
[/cc]

One last mix up of the dinner. $dinner=b2bd6656780b4fcad95b4326dd6ee46cbcdb4d8a

[cc lang=”PHP”]
$dinner=sha1($dinner);//mix our dinner up some more
[/cc]

Finally dinner is return for the password. This then is stored in the DB and the same function is used to encrypt the password to be equal when the user logs in.

[cc lang=”PHP”]
return $dinner;
}
[/cc]

Advertisements

14 comments

  1. I’m not an expert and I’m sure this was just a clever example, but don’t you think this is a lot of work? Since you’re using sha256, you may as well hash the data with the salt directly.

    [php]
    $someData = ‘my very secret password’;
    $salt = ‘aq:=IOz6`|q686iGim(!LN712d5Or6*s*KzBca,2).*bNW)-8@Nf]r^:93Kok8tR’; // from wordpress, http://api.wordpress.org/secret-key/1.1/
    $to = $salt . $someData;
    $hash = hash(‘sha256’, $someData);
    [/php]

  2. Why would u take so much effort ?

    $pass = escape_etc ( $_POSt[‘passowrd”] );

    $user = new User;
    $user->create = time();
    $user->email = ‘mail@mail.com’;
    switch( substr( $user->created,0,1 ) ) {
    case 1:
    $user->pass = md5(‘your’ , $pass . $user->created . ‘mother’);
    break;
    case 2:
    $user->pass = md5($pass . substr( $user->created, 0, 5) . ‘smells’);
    break;
    case …
    }
    $user->save();

    • if your algorithm is known, and the time of registry know (since you have to store this info to compare the pass it could be) then to crack it i just need to do this:
      $pass=one result of a rainbow table attack
      $thetime=the result bit i stole from the database telling when they were created
      $hashedPass=the hashed pass i stole from your datbase
      if(md5(‘your’.$pass.$time.’mother’)==$hashedPass)
      {
      doStuff();
      }
      and i can do the other one too, under the same algorithm (since i know $user->created, i know which one its using)
      the thing with salts is both the salt AND the algorithm to make them have to be secret or someone can just crack it.

      yours has the advantage though that the algorithm has 16 permutations (but to be honest it will almost always evaluate to 1, you needed substr(-1,1) to get the last digit…you got the first digit which almost never changes) but if you know the method you can derive the pass.

  3. Pingback: LimeSpace – IT » Der Wochenr?ckblick: Grafiken, PHP Kennw?rter mit Salt, JQuery + Formulare.

  4. What I don’t understand about all this salt n pepper… Isn’t it always like this, that as soon as the attacker knows my database and my function, encoding it, that it becomes very easy to crack the password?
    I’m surely not an expert, but just trying to understand such issues better…

    In the example given, wouldn’t it be possible, to do a bruteforce easily as well, if i get hold of the function???
    e.g.
    [PHP]
    function bruteforce() {creates different possible passwords
    from either dictonary, or systamatic approach, e.g.
    return ‘HelloKitty’;}

    //then i do:
    $numberOFtrys=100000000000000;
    whilte ($i<$numberOFtrys){
    $test=bruteforce();
    if (saltPlease($test) == $HASHfromYOURdb){
    echo $test." is the password";
    exit;
    }
    }
    [/PHP]

    So as far as I understand this issue, salt (and pepper) make a password safer, as long as "just" the database has been accessed by the attacker, but as soon as he gets hold of the function used, as well, it doesnt matter how complex the encoding algorythm is, right?

    Or am I completly wrong on this, then please correct me!

    kind regards

  5. Pingback: Chris Paul » Blog Archive » Oct 19, 2009 sweet links

  6. MD5 hasn’t been reverse engineered. The site is simply storing the hashes that were generated, and tries to match those (so they’re using the “rainbow table” approach). When you try to “decrypt” a key they don’t know about yet, you’ll get a simple “Sorry, this MD5 hash wasn’t found in our database”. But when you encrypt that and try it again, it “magically” appears (now how would they do that :p).

  7. Can any please tell me how safe following is and any suggestions will be apprecaited

    $password_hash = $h_cleaned_post[password];
    $salt = rand(1,99999999);

    $password_hash = encrypt($password_hash,$salt); //it encrypts password with md5 function with addon salt

    $result = mysql_query(“insert into login(username,password,salt)values
    (‘$h_cleaned_post[username]’,’$password_hash’,’$salt’)”, $con);

    /* function to mix md5 and salt */
    function encrypt($password_hash, $salt){
    $password_hash = md5($password_hash.$salt);
    return $password_hash;
    }


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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s