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.
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.