[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Portable PHP password hashing framework. 4 * @package phpass 5 * @since 2.5.0 6 * @version 0.5 / WordPress 7 * @link https://www.openwall.com/phpass/ 8 */ 9 10 # 11 # Portable PHP password hashing framework. 12 # 13 # Version 0.5.4 / WordPress. 14 # 15 # Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in 16 # the public domain. Revised in subsequent years, still public domain. 17 # 18 # There's absolutely no warranty. 19 # 20 # The homepage URL for this framework is: 21 # 22 # http://www.openwall.com/phpass/ 23 # 24 # Please be sure to update the Version line if you edit this file in any way. 25 # It is suggested that you leave the main version number intact, but indicate 26 # your project name (after the slash) and add your own revision information. 27 # 28 # Please do not change the "private" password hashing method implemented in 29 # here, thereby making your hashes incompatible. However, if you must, please 30 # change the hash type identifier (the "$P$") to something different. 31 # 32 # Obviously, since this code is in the public domain, the above are not 33 # requirements (there can be none), but merely suggestions. 34 # 35 36 /** 37 * Portable PHP password hashing framework. 38 * 39 * @package phpass 40 * @version 0.5 / WordPress 41 * @link https://www.openwall.com/phpass/ 42 * @since 2.5.0 43 */ 44 class PasswordHash { 45 var $itoa64; 46 var $iteration_count_log2; 47 var $portable_hashes; 48 var $random_state; 49 50 function __construct($iteration_count_log2, $portable_hashes) 51 { 52 $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; 53 54 if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) { 55 $iteration_count_log2 = 8; 56 } 57 $this->iteration_count_log2 = $iteration_count_log2; 58 59 $this->portable_hashes = $portable_hashes; 60 61 $this->random_state = microtime(); 62 if (function_exists('getmypid')) { 63 $this->random_state .= getmypid(); 64 } 65 } 66 67 function PasswordHash($iteration_count_log2, $portable_hashes) 68 { 69 self::__construct($iteration_count_log2, $portable_hashes); 70 } 71 72 function get_random_bytes($count) 73 { 74 $output = ''; 75 if (@is_readable('/dev/urandom') && 76 ($fh = @fopen('/dev/urandom', 'rb'))) { 77 $output = fread($fh, $count); 78 fclose($fh); 79 } 80 81 if (strlen($output) < $count) { 82 $output = ''; 83 for ($i = 0; $i < $count; $i += 16) { 84 $this->random_state = 85 md5(microtime() . $this->random_state); 86 $output .= md5($this->random_state, TRUE); 87 } 88 $output = substr($output, 0, $count); 89 } 90 91 return $output; 92 } 93 94 function encode64($input, $count) 95 { 96 $output = ''; 97 $i = 0; 98 do { 99 $value = ord($input[$i++]); 100 $output .= $this->itoa64[$value & 0x3f]; 101 if ($i < $count) { 102 $value |= ord($input[$i]) << 8; 103 } 104 $output .= $this->itoa64[($value >> 6) & 0x3f]; 105 if ($i++ >= $count) { 106 break; 107 } 108 if ($i < $count) { 109 $value |= ord($input[$i]) << 16; 110 } 111 $output .= $this->itoa64[($value >> 12) & 0x3f]; 112 if ($i++ >= $count) { 113 break; 114 } 115 $output .= $this->itoa64[($value >> 18) & 0x3f]; 116 } while ($i < $count); 117 118 return $output; 119 } 120 121 function gensalt_private($input) 122 { 123 $output = '$P$'; 124 $output .= $this->itoa64[min($this->iteration_count_log2 + 5, 125 30)]; 126 $output .= $this->encode64($input, 6); 127 128 return $output; 129 } 130 131 function crypt_private($password, $setting) 132 { 133 $output = '*0'; 134 if (substr($setting, 0, 2) === $output) { 135 $output = '*1'; 136 } 137 138 $id = substr($setting, 0, 3); 139 # We use "$P$", phpBB3 uses "$H$" for the same thing 140 if ($id !== '$P$' && $id !== '$H$') { 141 return $output; 142 } 143 144 $count_log2 = strpos($this->itoa64, $setting[3]); 145 if ($count_log2 < 7 || $count_log2 > 30) { 146 return $output; 147 } 148 149 $count = 1 << $count_log2; 150 151 $salt = substr($setting, 4, 8); 152 if (strlen($salt) !== 8) { 153 return $output; 154 } 155 156 # We were kind of forced to use MD5 here since it's the only 157 # cryptographic primitive that was available in all versions 158 # of PHP in use. To implement our own low-level crypto in PHP 159 # would have resulted in much worse performance and 160 # consequently in lower iteration counts and hashes that are 161 # quicker to crack (by non-PHP code). 162 $hash = md5($salt . $password, TRUE); 163 do { 164 $hash = md5($hash . $password, TRUE); 165 } while (--$count); 166 167 $output = substr($setting, 0, 12); 168 $output .= $this->encode64($hash, 16); 169 170 return $output; 171 } 172 173 function gensalt_blowfish($input) 174 { 175 # This one needs to use a different order of characters and a 176 # different encoding scheme from the one in encode64() above. 177 # We care because the last character in our encoded string will 178 # only represent 2 bits. While two known implementations of 179 # bcrypt will happily accept and correct a salt string which 180 # has the 4 unused bits set to non-zero, we do not want to take 181 # chances and we also do not want to waste an additional byte 182 # of entropy. 183 $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 184 185 $output = '$2a$'; 186 $output .= chr((int)(ord('0') + $this->iteration_count_log2 / 10)); 187 $output .= chr(ord('0') + $this->iteration_count_log2 % 10); 188 $output .= '$'; 189 190 $i = 0; 191 do { 192 $c1 = ord($input[$i++]); 193 $output .= $itoa64[$c1 >> 2]; 194 $c1 = ($c1 & 0x03) << 4; 195 if ($i >= 16) { 196 $output .= $itoa64[$c1]; 197 break; 198 } 199 200 $c2 = ord($input[$i++]); 201 $c1 |= $c2 >> 4; 202 $output .= $itoa64[$c1]; 203 $c1 = ($c2 & 0x0f) << 2; 204 205 $c2 = ord($input[$i++]); 206 $c1 |= $c2 >> 6; 207 $output .= $itoa64[$c1]; 208 $output .= $itoa64[$c2 & 0x3f]; 209 } while (1); 210 211 return $output; 212 } 213 214 function HashPassword($password) 215 { 216 if ( strlen( $password ) > 4096 ) { 217 return '*'; 218 } 219 220 $random = ''; 221 222 if (CRYPT_BLOWFISH === 1 && !$this->portable_hashes) { 223 $random = $this->get_random_bytes(16); 224 $hash = 225 crypt($password, $this->gensalt_blowfish($random)); 226 if (strlen($hash) === 60) { 227 return $hash; 228 } 229 } 230 231 if (strlen($random) < 6) { 232 $random = $this->get_random_bytes(6); 233 } 234 $hash = 235 $this->crypt_private($password, 236 $this->gensalt_private($random)); 237 if (strlen($hash) === 34) { 238 return $hash; 239 } 240 241 # Returning '*' on error is safe here, but would _not_ be safe 242 # in a crypt(3)-like function used _both_ for generating new 243 # hashes and for validating passwords against existing hashes. 244 return '*'; 245 } 246 247 function CheckPassword($password, $stored_hash) 248 { 249 if ( strlen( $password ) > 4096 ) { 250 return false; 251 } 252 253 $hash = $this->crypt_private($password, $stored_hash); 254 if ($hash[0] === '*') { 255 $hash = crypt($password, $stored_hash); 256 } 257 258 # This is not constant-time. In order to keep the code simple, 259 # for timing safety we currently rely on the salts being 260 # unpredictable, which they are at least in the non-fallback 261 # cases (that is, when we use /dev/urandom and bcrypt). 262 return $hash === $stored_hash; 263 } 264 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Sun Dec 22 08:20:01 2024 | Cross-referenced by PHPXref |