Here ya go:
define('CNF_PASSWORD_SALT1', 'fvuiyt8635t394nng'); //Change this to some random stuff
define('CNF_PASSWORD_SALT2', 'sdfkofuhnA%^%^23J'); //Change this to some random stuff
define('CNF_PASSWORD_HASH0', 'sha512');
define('CNF_PASSWORD_HASH1', 'whirlpool');
define('CNF_PASSWORD_HASH2', 'sha512');
//20 rounds by default. Change to more if more security is required
define('CNF_PASSWORD_EXTRA_ROUNDS', 20);
class HashPassword {
protected static $level0PassHash = null;
protected static $level1PassHash = null;
protected static $level2PassHash = null;
protected static $defaultHashRounds = null;
protected static function _init(){
self::$level0PassHash = CNF_PASSWORD_HASH0;
self::$level1PassHash = CNF_PASSWORD_HASH1;
self::$level2PassHash = CNF_PASSWORD_HASH2;
self::$defaultHashRounds = CNF_PASSWORD_EXTRA_ROUNDS;
}
public static function Make($inputData, $extraSalt = false, $extraRounds = false) {
if (!isset(self::$level0PassHash)){
self::_init();
}
if ($extraRounds === false) {
$extraRounds = self::$defaultHashRounds;
}
if ($extraRounds > 0) {//More rounds through recursion
$halfStringPos = floor(strlen($inputData) / 2);
$inputData = substr($inputData, $halfStringPos) . substr($inputData, 0, $halfStringPos); //This shifts the string on each round - '123456' into '456123' etc.
$inputData = self::Make($inputData, $extraSalt, $extraRounds - 1); // Recursion
}
$hashLevel0 = $extraSalt ?
hash(self::$level0PassHash, $extraSalt.$inputData.$extraSalt) :
hash(self::$level0PassHash, $inputData);
$hashLevel1 = hash(self::$level1PassHash, CNF_PASSWORD_SALT1.$inputData.CNF_PASSWORD_SALT1);
$output = hash(self::$level2PassHash, CNF_PASSWORD_SALT2.$hashLevel0.CNF_PASSWORD_SALT2);
return $output;
}
}
3 layered hashing, different salt on each layer. Level 3 salting is optional.
There are 3 smaller rounds in a single big round, so a total of 20 rounds (default) gives you 60 salted hashing rounds in total for a single password. Benchmark your scripts and change the number of rounds depending of the power of your servers. Too many rounds can clog up the server as users logging in massively will use a lot of CPU.
20 big rounds should be enough for everyone for starters.
Usage:
HashPassword::Make($data, [optional] $additionalLevel3Salt = null, [optional] $changeNumberOfRounds = 20);
If you want some serious security, put (for example) user's registration date (or anything else generated randomly on registration) into the $additionalLevel3Salt parameter. It will make rainbow tables attack unfeasible.
This is a production - grade code. It should work without any modifications.
License:
WTFPL License,
http://en.wikipedia.org/wiki/WTFPL---------------------
EDIT:
Also, there is a useful list of different hashing algorithms' speed on php.net
Performance test results on my laptop:
Results are here shorten to fit php web notes ...
This was tested with 1024000 bytes (1000 KB) of random data, md4 always gets the first place, and md2 always get the last place
Results: (in microseconds)
1. md4 5307.912
2. md5 6890.058
3. crc32b 7298.946
4. crc32 7561.922
5. sha1 8886.098
6. tiger128,3 11054.992
7. haval192,3 11132.955
8. haval224,3 11160.135
9. tiger160,3 11162.996
10. haval160,3 11242.151
11. haval256,3 11327.981
12. tiger192,3 11630.058
13. haval128,3 11880.874
14. tiger192,4 14776.945
15. tiger128,4 14871.12
16. tiger160,4 14946.937
17. haval160,4 15661.954
18. haval192,4 15717.029
19. haval256,4 15759.944
20. adler32 15796.184
21. haval128,4 15887.022
22. haval224,4 16047.954
23. ripemd256 16245.126
24. haval160,5 17818.927
25. haval128,5 17887.115
26. haval224,5 18085.002
27. haval192,5 18135.07
28. haval256,5 18678.903
29. sha256 19020.08
30. ripemd128 20671.844
31. ripemd160 21853.923
32. ripemd320 22425.889
33. sha384 45102.119
34. sha512 45655.965
35. gost 57237.148
36. whirlpool 64682.96
37. snefru 80352.783
38. md2 705397.844
Plus the lengths of hashes produced by each of the algos:
md2 32
md4 32
md5 32
sha1 40
sha256 64
sha384 96
sha512 128
ripemd128 32
ripemd160 40
ripemd256 64
ripemd320 80
whirlpool 128
tiger128,3 32
tiger160,3 40
tiger192,3 48
tiger128,4 32
tiger160,4 40
tiger192,4 48
snefru 64
gost 64
adler32 8
crc32 8
crc32b 8
haval128,3 32
haval160,3 40
haval192,3 48
haval224,3 56
haval256,3 64
haval128,4 32
haval160,4 40
haval192,4 48
haval224,4 56
haval256,4 64
haval128,5 32
haval160,5 40
haval192,5 48
haval224,5 56
haval256,5 64
Have fun.