-4

will this function be safe for password and email hash/crypt? EDIT: Cleary not!

$password = mysql_real_escape_string(htmlspecialchars(trim($_POST['password'])));
$hash_algo = "sha512";
$raw_output = false;

$hash = hash($hash_algo, $password, $raw_output);
$hash_20 = substr($hash, 0, 20);

$salt = substr($hash, -20); 
$crypt = crypt ( $hash_20, $salt);
$crypt_20 = substr($crypt, 0, 20);

EDIT: Here is the code I'm using now. I think this one is pretty safe. It's a PBKDF2 password hash function with a random salt generator.

So, here is the PBKDF2 function. p is for password. s is for salt. c is for iteration kl is for key lenght. a is for hash algorithm.

function pbkdf2( $p, $s, $c, $kl, $a = 'sha256' )
{ 
    $hl = strlen(hash($a, null, true)); # Hash length
    $kb = ceil($kl / $hl);              # Key blocks to compute
    $dk = '';                           # Derived key

    # Create key
    for ( $block = 1; $block <= $kb; $block ++ ) {

        # Initial hash for this block
        $ib = $b = hash_hmac($a, $s . pack('N', $block), $p, true);

        # Perform block iterations
        for ( $i = 1; $i < $c; $i ++ )

            # XOR each iterate
            $ib ^= ($b = hash_hmac($a, $b, $p, true));

        $dk .= $ib; # Append iterated block
    }

    # Return derived key of correct length
    return substr($dk, 0, $kl);
}

Salt generator:

function salt( $length )
{
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";  
    $salt="";
    $size = strlen( $chars );

    for( $i = 0; $i < $length; $i++ )
    {
        $salt.= $chars[ rand( 0, $size - 1 ) ];
    }

    return $salt;

}

In use:

if(isset($_POST['submit']))
{

    $Password = mysql_real_escape_string(htmlspecialchars(trim($_POST['Password'])));

    //To make sure the salt has never more chars than the password.
    $salt_length = strlen($Password); 
    $salt = salt($salt_length);

    //Hash Password 
    $hash = base64_encode(pbkdf2($Password, $salt, 100000, 32));
    //--------------//
}

Googling a bit find out that 100000 iterations is pretty safe but I guess 10000 will be enough tho.

Ruble Gomes
  • 117
  • 1
  • 7
  • 1
    http://stackoverflow.com/questions/401656/secure-hash-and-salt-for-php-passwords , http://stackoverflow.com/questions/1581610/how-can-i-store-my-users-passwords-safely , http://stackoverflow.com/questions/4795385/how-do-you-use-bcrypt-for-hashing-passwords-in-php – Adi Aug 15 '12 at 08:40
  • Also, no need to `mysql_real_escape_string(htmlspecialchars($password));`, you're hashing it, that pretty much handles everything. The output will always be a hex string. – Adi Aug 15 '12 at 08:42
  • I read all that. Not really what I ask tho. I just wanna know if this function will be safe or not. – Ruble Gomes Aug 15 '12 at 08:43
  • 1
    "Safe" against/for what? – deceze Aug 15 '12 at 08:43
  • 1
    this is better suited for http://codereview.stackexchange.com/ – Yoshi Aug 15 '12 at 08:44
  • If someone get into my database how hard will it be to get the actual password/email? – Ruble Gomes Aug 15 '12 at 08:44
  • 3
    And I'm sorry to say this, but no. No, you didn't read all that. If you've read all that you'd be able to answer this question. Those questions provide you with the required tools and knowledge to asses your own code and figure out if it's safe or not. – Adi Aug 15 '12 at 08:45
  • Way to alter an already closed and accepted question. Did you unaccept my answer because it doesn't match the question anymore? – deceze Aug 16 '12 at 08:43
  • Sorry. I'm trying to figure out how this site works. I can't post more question and the faq say to edit or answer question and to be more helpful to others. I edit this one because it's the post that I think can maybe help the most. I didn't find any PBKDF2 function so I put one here. Hoping for a reopening. – Ruble Gomes Aug 16 '12 at 08:50

1 Answers1

3

Since you're hashing the input, you cannot simply reverse it to the original value. Assuming an attacker knows this algorithm, the question is how long does it take to brute force the password. For that, test how long one iteration of the algorithm takes. Then calculate how many tries an attacker would have to do to try all possible passwords on a high-end machine. Then you have your answer how "safe" the algorithm is. You are looking for an answer measured at least in millennia, but preferably big bangs.

That is, assuming there are no actual attacks against the algorithm an attacker could try that would shorten that time.

Since you are deriving the salt from the input itself, you're simply stretching the algorithm a bit. You're not using an actual salt, which is a random unique value that is independent of the input. As such, you are using an unsalted input with a not so complicated hashing algorithm. My bet would be that it's not very hard to brute force a whole database of passwords "secured" with this algorithm.

deceze
  • 510,633
  • 85
  • 743
  • 889