开发者社区> 问答> 正文

如何安全的存储用户密码二:加密源代码(php)


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



附Php,Java,C#的Hash代码:


如何安全的存储用户的密码一:常见攻击方法




如何安全的存储用户密码三:hash源代码(java)



如何安全的存储用户的密码四:hash源代码(c#)


展开
收起
千鸟 2014-07-02 15:56:18 9963 0
4 条回答
写回答
取消 提交回答
  • Re如何安全的存储用户密码二:加密源代码(php)
    这个放在什么位置啊?
    2014-08-19 19:34:27
    赞同 展开评论 打赏
  • LT是个伪程序员
    回 2楼(trcher) 的帖子
    都是封装好的函数,直接用即可。码估让人只看代码有点眼花的感觉。
    2014-08-19 05:20:09
    赞同 展开评论 打赏
  • 回 楼主(千鸟) 的帖子
    很实用啊,但是你没把方法贴出来,我们这些菜鸟不知道如何用啊
    2014-08-18 20:34:00
    赞同 展开评论 打赏
  • 您的帖子很精彩!希望很快能再分享您的下一帖!
    2014-07-03 14:02:47
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
PHP安全开发:从白帽角度做安全 立即下载
PHP 2017.北京 全球开发者大会——高可用的PHP 立即下载
复杂PHP系统性能瓶颈排查及优化 立即下载