PageRenderTime 25ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/securehash.class.php

https://bitbucket.org/hugolm84/php-login
PHP | 105 lines | 48 code | 9 blank | 48 comment | 9 complexity | 08ff762621c22b00027105575eb60dd3 MD5 | raw file
  1. <?php
  2. /**
  3. * Taken from https://gist.github.com/cballou/2439237
  4. */
  5. class SecureHash
  6. {
  7. /**
  8. * Creates a very secure hash. Uses blowfish by default with a fallback on SHA512.
  9. *
  10. * Usage of CRYPT_BLOWFISH:
  11. * -----------------------
  12. * Blowfish hashing with a salt is as follows:
  13. * "$2a$" + a two digit cost parameter + "$" + 22 digits from the base64 alphabet
  14. * "./0-9A-Za-z" + "$".
  15. *
  16. * Using characters outside of this range in the salt will cause crypt() to return
  17. * a zero-length string. The two digit cost parameter is the base-2 logarithm
  18. * of the iteration count for the underlying Blowfish-based hashing algorithmeter
  19. * and must be in range 04-31, values outside this range will cause crypt() to fail.
  20. *
  21. * @access public
  22. * @param string $password
  23. * @param string $salt
  24. * @param int $stretch_cost
  25. */
  26. public function create_hash($password, &$salt = '', $stretch_cost = 10)
  27. {
  28. $salt = strlen($salt) != 21 ? $this->_create_salt() : $salt;
  29. if (function_exists('crypt') && defined('CRYPT_BLOWFISH')) {
  30. return crypt($password, '$2a$' . $stretch_cost . '$' . $salt . '$');
  31. }
  32. // fallback encryption
  33. if (!function_exists('hash') || !in_array('sha512', hash_algos())) {
  34. throw new Exception('You must have the PHP PECL hash module installed or use PHP 5.1.2+');
  35. }
  36. return $this->_create_hash($password, $salt);
  37. }
  38. /**
  39. * @param string $pass The user submitted password
  40. * @param string $hashed_pass The hashed password pulled from the database
  41. * @param string $salt The salt used to generate the encrypted password
  42. */
  43. public function validate_hash($pass, $hashed_pass, $salt)
  44. {
  45. return $hashed_pass === $this->create_hash($pass, $salt);
  46. }
  47. /**
  48. * Create a new salt string which conforms to the requirements of CRYPT_BLOWFISH.
  49. *
  50. * @access protected
  51. * @return string
  52. */
  53. protected function _create_salt()
  54. {
  55. $salt = $this->_pseudo_rand(128);
  56. return substr(preg_replace('/[^A-Za-z0-9_]/is', '.', base64_encode($salt)), 0, 21);
  57. }
  58. /**
  59. * Generates a secure, pseudo-random password with a safe fallback.
  60. *
  61. * @access public
  62. * @param int $length
  63. */
  64. protected function _pseudo_rand($length)
  65. {
  66. if (function_exists('openssl_random_pseudo_bytes')) {
  67. $is_strong = false;
  68. $rand = openssl_random_pseudo_bytes($length, $is_strong);
  69. if ($is_strong === true) return $rand;
  70. }
  71. $rand = '';
  72. $sha = '';
  73. for ($i = 0; $i < $length; $i++) {
  74. $sha = hash('sha256', $sha . mt_rand());
  75. $chr = mt_rand(0, 62);
  76. $rand .= chr(hexdec($sha[$chr] . $sha[$chr + 1]));
  77. }
  78. return $rand;
  79. }
  80. /**
  81. * Fall-back SHA512 hashing algorithm with stretching.
  82. *
  83. * @access private
  84. * @param string $password
  85. * @param string $salt
  86. * @return string
  87. */
  88. private function _create_hash($password, $salt)
  89. {
  90. $hash = '';
  91. for ($i = 0; $i < 20000; $i++) {
  92. $hash = hash('sha512', $hash . $salt . $password);
  93. }
  94. return $hash;
  95. }
  96. }