Advertisement
BaSs_HaXoR

PHP PBKDF2 Password Hashing Code

Sep 9th, 2014
356
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 5.22 KB | None | 0 0
  1. /*
  2.  * Password Hashing With PBKDF2 (http://crackstation.net/hashing-security.htm).
  3.  * Copyright (c) 2013, Taylor Hornby
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions are met:
  8.  *
  9.  * 1. Redistributions of source code must retain the above copyright notice,
  10.  * this list of conditions and the following disclaimer.
  11.  *
  12.  * 2. Redistributions in binary form must reproduce the above copyright notice,
  13.  * this list of conditions and the following disclaimer in the documentation
  14.  * and/or other materials provided with the distribution.
  15.  *
  16.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  20.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  24.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  25.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  26.  * POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. // These constants may be changed without breaking existing hashes.
  30. define("PBKDF2_HASH_ALGORITHM", "sha256");
  31. define("PBKDF2_ITERATIONS", 1000);
  32. define("PBKDF2_SALT_BYTE_SIZE", 24);
  33. define("PBKDF2_HASH_BYTE_SIZE", 24);
  34.  
  35. define("HASH_SECTIONS", 4);
  36. define("HASH_ALGORITHM_INDEX", 0);
  37. define("HASH_ITERATION_INDEX", 1);
  38. define("HASH_SALT_INDEX", 2);
  39. define("HASH_PBKDF2_INDEX", 3);
  40.  
  41. function create_hash($password)
  42. {
  43.     // format: algorithm:iterations:salt:hash
  44.     $salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTE_SIZE, MCRYPT_DEV_URANDOM));
  45.     return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" .  $salt . ":" .
  46.         base64_encode(pbkdf2(
  47.             PBKDF2_HASH_ALGORITHM,
  48.             $password,
  49.             $salt,
  50.             PBKDF2_ITERATIONS,
  51.             PBKDF2_HASH_BYTE_SIZE,
  52.             true
  53.         ));
  54. }
  55.  
  56. function validate_password($password, $correct_hash)
  57. {
  58.     $params = explode(":", $correct_hash);
  59.     if(count($params) < HASH_SECTIONS)
  60.        return false;
  61.     $pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]);
  62.     return slow_equals(
  63.         $pbkdf2,
  64.         pbkdf2(
  65.             $params[HASH_ALGORITHM_INDEX],
  66.             $password,
  67.             $params[HASH_SALT_INDEX],
  68.             (int)$params[HASH_ITERATION_INDEX],
  69.             strlen($pbkdf2),
  70.             true
  71.         )
  72.     );
  73. }
  74.  
  75. // Compares two strings $a and $b in length-constant time.
  76. function slow_equals($a, $b)
  77. {
  78.     $diff = strlen($a) ^ strlen($b);
  79.     for($i = 0; $i < strlen($a) && $i < strlen($b); $i++)
  80.     {
  81.         $diff |= ord($a[$i]) ^ ord($b[$i]);
  82.     }
  83.     return $diff === 0;
  84. }
  85.  
  86. /*
  87.  * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
  88.  * $algorithm - The hash algorithm to use. Recommended: SHA256
  89.  * $password - The password.
  90.  * $salt - A salt that is unique to the password.
  91.  * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
  92.  * $key_length - The length of the derived key in bytes.
  93.  * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
  94.  * Returns: A $key_length-byte key derived from the password and salt.
  95.  *
  96.  * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
  97.  *
  98.  * This implementation of PBKDF2 was originally created by https://defuse.ca
  99.  * With improvements by http://www.variations-of-shadow.com
  100.  */
  101. function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
  102. {
  103.     $algorithm = strtolower($algorithm);
  104.     if(!in_array($algorithm, hash_algos(), true))
  105.         trigger_error('PBKDF2 ERROR: Invalid hash algorithm.', E_USER_ERROR);
  106.     if($count <= 0 || $key_length <= 0)
  107.         trigger_error('PBKDF2 ERROR: Invalid parameters.', E_USER_ERROR);
  108.  
  109.     if (function_exists("hash_pbkdf2")) {
  110.         // The output length is in NIBBLES (4-bits) if $raw_output is false!
  111.         if (!$raw_output) {
  112.             $key_length = $key_length * 2;
  113.         }
  114.         return hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output);
  115.     }
  116.  
  117.     $hash_length = strlen(hash($algorithm, "", true));
  118.     $block_count = ceil($key_length / $hash_length);
  119.  
  120.     $output = "";
  121.     for($i = 1; $i <= $block_count; $i++) {
  122.         // $i encoded as 4 bytes, big endian.
  123.         $last = $salt . pack("N", $i);
  124.         // first iteration
  125.         $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
  126.         // perform the other $count - 1 iterations
  127.         for ($j = 1; $j < $count; $j++) {
  128.             $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
  129.         }
  130.         $output .= $xorsum;
  131.     }
  132.  
  133.     if($raw_output)
  134.         return substr($output, 0, $key_length);
  135.     else
  136.         return bin2hex(substr($output, 0, $key_length));
  137. }
  138. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement