# Evaluating a hashing function used to create secure API key

What are your thoughts on the following code? is it secure enough?

Note: $password is used to represent the secret, which would essentially be a SHA512 hash of username . password . signupdate(unixtime)  Do you think I'm covered? error_reporting(E_ALL & ~E_NOTICE | E_STRICT); ini_set("display_errors", "1"); echo '<pre>';$break = '<br/>';
$password = trim("password"); echo 'step1 the password is posted<br/>'; echo$password;
echo $break; echo$break;
$time = date("F j, Y, g:i a"); echo 'step2 get the time in human readable format<br/>'; echo$time;
echo $break; echo$break;
$salt1 =$time . hash('sha512', (sha1 .$time)); echo 'step3 create salt1<br/>'; echo$salt1;
echo $break; echo$break;
$salt2 = substr(md5(uniqid(rand(), true)), 0, 25); echo 'step4 create salt2<br/>'; echo$salt2;
echo $break; echo$break;
$hash = str_split($password);
echo 'step5 split the password into an array<br/>';
print_r($hash, false); echo$break;
echo $break; echo 'step6 hash each charachter of the password in the array<br/>'; foreach($hash as $key =>$value) {
$hashed[] =$salt2 . hash('sha512', ($salt .$value)) . $salt . hash('sha256', (salt2 .$key));
}
print_r($hashed, false); echo$break;
echo $break;$hashed_2 = implode($hashed); echo 'step7 implode the array into a single hash<br/>'; echo$hashed_2;
echo $break; echo$break;
$hashfinal = str_shuffle($hashed_2);
echo 'step8 shuffle the hash to decrease entropy<br/>';
print_r($hashfinal, false);  ## 1 Answer No, it isn't secure. Inventing your own hashing algorithms is a horrible idea. When doing password hashing, use something invented by cryptographers that was made for password hashing, e.g. bcrypt. Because I'm not a cryptographer either, I can't give you a full explanation why your code is insecure. In short, the mistake you made was hashing each character of the password on its own. A few things I spotted: • The final output has a length proportional to the length of the password. This can be abused for denial-of-service attacks or to limit the search space when cracking via brute force. • In your final hash, the letters of $salt2 will occur more often. Therefore the resulting hash isn't evenly distributed over the output domain.
• Same letters in the password obviously have the same hash. But as that is directly reflected in the output, this can be used as an attack vector (even if I don't know which letter is repeated).
• It is not possible to extract the salt(s) from a given hash because you shuffle the string – therefore it is impossible to say whether a given password is the same as the hashed password (we can only check whether the lengths are the same). This makes your hash function unsuitable for authentication – but for what are you using it then? For an API key, an unique random number that does not depend on user input would be better.

Your code also uses, but does not define the $salt variable – it assigns $salt1 and $salt2. The $salt1 variable isn't used anywhere.

Secure password hashing is only difficult if you try to use a home-brewed solution. I outlined suggested authentication workflows in another answer which includes a list of recommended password hashing solutions (neither your code, SHA-512, nor MD5 is on that list, don't use them for passwords).

• did you even read? it says it in the opening stanza "used for api key generation". i'm builing a cryptocurrency exchange, and one of the things it doesn't have that is fairly standard is an api(so that users can make trade bots to handle their trading.) this is the early stages of the api key generation. once it is generated, it would be stored in the database table as their api key. basically, the thing i'm trying to avoid is collision. nevertheless i appreciate your comment. you gave me a fair deal to think about and pointed out a mistake i made. thank you
– r3wt
Dec 29 '13 at 16:49