3

I have been looking into the best way to encrypt passwords for use with my panel, I decided to go ahead and use BCRYPT, simply due to the cost of each encryption and the fact that it is generally regarded as one of the best available at the current time.

I am using two-way salts, so a unique salt that each user has, and then obviously the salt stored within my application, I noticed some rather strange behavior.. and according to the PHP Documentation this behavior is normal?

Anyway, here is the code I use:

$Crypto = new Crypto;
echo $Crypto->encrypt( "123456789abcdefghijklm", "StackOverflow_Is_Awesome!" ); // First parameter being the "User Salt", second being the password.

// Above outputs $2y$13$123456789abcdefghijkleepFY8JLvsf2YbnWolqQyO3DIzrCeNIu

And now, the Crypto class:

<?php
// ASSUMING $this->hashingSalt = HBSNi3y7ruhbVGkhdg83ijdbvghiojkgudL;JP
class Crypto {

private $hashingSalt, $database;

public function __construct( $salt )
{
    $this->hashingSalt = $salt;
    $this->database = new DatabaseFunctions();
}

public function encrypt( $salt, $password )
{
    $options = array(
        'cost' => 13,
        'salt' => $salt //22 chars
    );

    return password_hash( $password . $this->hashingSalt, PASSWORD_BCRYPT, $options);
}
}

So, my interest is, why on earth is this function simply adding the salt set within the options to the start of the outputted string? It really is baffling... because that isn't exactly what I would call secure, rather defeats the object to me.

Can anyone advise, try and explain what I am completely looking past? Thanks

PHP Doc: http://php.net/manual/en/function.password-hash.php

Jake Ball
  • 798
  • 2
  • 8
  • 26

1 Answers1

5

The salt is there to prevent the possibility of making a pre-computed table with hashes and it is not meant to stay safe once "the bad guys" get their hands on the hashes.

Also what you are doing:

and then obviously the salt stored within my application

is called a pepper (and is really not that obvious to do) and AFAIK it hasn't been proven to be more secure. For more information read this blogpost (also by the author of the password API): http://blog.ircmaxell.com/2012/04/properly-salting-passwords-case-against.html

Also note that your method called encrypt is not encrypting anything. Encryption is two way. What you are doing is called hashing: https://stackoverflow.com/a/4948393/508666

Community
  • 1
  • 1
PeeHaa
  • 71,436
  • 58
  • 190
  • 262
  • Hello, thank you. Firstly thanks for educating me on the difference between hashing and encrypting, silly mistake. I will get onto changing that now! I have read both links and gained some valuable intel on hashing and the api I am using, so I would like to thank you for that. So, in all I am doing the right thing just the pepper is merely not making much of a difference, correct? – Jake Ball Apr 08 '13 at 00:23
  • Hmmm I see you are trying to set the salt yourself. In most cases you don't want to do that, because it is something the API will do for you and it is something that can easily be "screwed up". If you want to find out how it works better you can look into the code [in PHP](https://github.com/ircmaxell/password_compat). – PeeHaa Apr 08 '13 at 00:26
  • Thank you for your reply, I have to use that compat-library as I am still waiting for my host to upgrade to 5.5>. I have looked through the code, found it quite helpful actually, reason why my passwords weren't originally being validated by the function within the api is because I was hashing them before using the password_verify() function. Thanks for your help PeeHaa, it seems I was over-complicating things which really is, no different to the norm! So, now I have it set up to do all the salt business itself, rules out the middle man... thanks! :) – Jake Ball Apr 08 '13 at 01:02
  • 1
    @JakeBall - Absolutely agree with PeeHaa's answer. There is one situation where a pepper _does_ increase security, in the case an attacker got access to your database (SQL-injection), but does not know the pepper (no access to the server). The pepper then thwarts dictionary attacks and can protect weak passwords. To add a pepper, do something like this `$pepperedPassword = hash_hmac('sha256', $password, $pepper, false);`, then call `password_hash()` with the peppered password. As PeeHaa already wrote, don't pass your own salt to the function. – martinstoeckli Apr 08 '13 at 11:54
  • 1
    It also may be worth noting that peppers should be avoided in all cases. Here is an [explanation why](http://stackoverflow.com/questions/16891729/best-practices-salting-peppering-passwords/16896216#16896216). There are better cryptographic practices that you can use that have been actually studied and understood. Rather than inventing your own method... – ircmaxell Jun 21 '13 at 14:16