|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2009-2011 Marcus Krause <marcus#exp2009@t3sec.info> 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00027 /** 00028 * Contains class "tx_saltedpasswords_salts_blowfish" 00029 * that provides Blowfish salted hashing. 00030 * 00031 * $Id: class.tx_saltedpasswords_salts_blowfish.php 10120 2011-01-18 20:03:36Z ohader $ 00032 */ 00033 00034 00035 /** 00036 * Class that implements Blowfish salted hashing based on PHP's 00037 * crypt() function. 00038 * 00039 * Warning: Blowfish salted hashing with PHP's crypt() is not available 00040 * on every system. 00041 * 00042 * @author Marcus Krause <marcus#exp2009@t3sec.info> 00043 * 00044 * @since 2009-09-06 00045 * @package TYPO3 00046 * @subpackage tx_saltedpasswords 00047 */ 00048 class tx_saltedpasswords_salts_blowfish extends tx_saltedpasswords_salts_md5 { 00049 /** 00050 * The default log2 number of iterations for password stretching. 00051 */ 00052 const HASH_COUNT = 7; 00053 00054 /** 00055 * The default maximum allowed log2 number of iterations for 00056 * password stretching. 00057 */ 00058 const MAX_HASH_COUNT = 17; 00059 00060 /** 00061 * The default minimum allowed log2 number of iterations for 00062 * password stretching. 00063 */ 00064 const MIN_HASH_COUNT = 4; 00065 00066 00067 /** 00068 * Keeps log2 number 00069 * of iterations for password stretching. 00070 * 00071 * @var integer 00072 */ 00073 static protected $hashCount; 00074 00075 /** 00076 * Keeps maximum allowed log2 number 00077 * of iterations for password stretching. 00078 * 00079 * @var integer 00080 */ 00081 static protected $maxHashCount; 00082 00083 /** 00084 * Keeps minimum allowed log2 number 00085 * of iterations for password stretching. 00086 * 00087 * @var integer 00088 */ 00089 static protected $minHashCount; 00090 00091 /** 00092 * Keeps length of a Blowfish salt in bytes. 00093 * 00094 * @var integer 00095 */ 00096 static protected $saltLengthBlowfish = 16; 00097 00098 /** 00099 * Setting string to indicate type of hashing method (blowfish). 00100 * 00101 * @var string 00102 */ 00103 static protected $settingBlowfish = '$2a$'; 00104 00105 00106 /** 00107 * Method applies settings (prefix, hash count) to a salt. 00108 * 00109 * Overwrites {@link tx_saltedpasswords_salts_md5::applySettingsToSalt()} 00110 * with Blowfish specifics. 00111 * 00112 * @param string $salt: a salt to apply setting to 00113 * @return string salt with setting 00114 */ 00115 protected function applySettingsToSalt($salt) { 00116 $saltWithSettings = $salt; 00117 00118 $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength()); 00119 00120 // salt without setting 00121 if (strlen($salt) == $reqLenBase64) { 00122 $saltWithSettings = $this->getSetting() 00123 . sprintf('%02u', $this->getHashCount()) . '$' 00124 . $salt; 00125 } 00126 00127 return $saltWithSettings; 00128 } 00129 00130 /** 00131 * Parses the log2 iteration count from a stored hash or setting string. 00132 * 00133 * @param string $setting: complete hash or a hash's setting string or to get log2 iteration count from 00134 * @return integer used hashcount for given hash string 00135 */ 00136 protected function getCountLog2($setting) { 00137 $countLog2 = NULL; 00138 $setting = substr($setting, strlen($this->getSetting())); 00139 $firstSplitPos = strpos($setting, '$'); 00140 00141 // hashcount existing 00142 if (($firstSplitPos !== FALSE) 00143 && ($firstSplitPos <= 2) && is_numeric(substr($setting, 0, $firstSplitPos))) { 00144 $countLog2 = intval(substr($setting, 0, $firstSplitPos)); 00145 } 00146 00147 return $countLog2; 00148 } 00149 00150 /** 00151 * Method returns log2 number of iterations for password stretching. 00152 * 00153 * @return integer log2 number of iterations for password stretching 00154 * @see HASH_COUNT 00155 * @see $hashCount 00156 * @see setHashCount() 00157 */ 00158 public function getHashCount() { 00159 return isset(self::$hashCount) ? self::$hashCount : self::HASH_COUNT; 00160 } 00161 00162 /** 00163 * Method returns maximum allowed log2 number of iterations for password stretching. 00164 * 00165 * @return integer maximum allowed log2 number of iterations for password stretching 00166 * @see MAX_HASH_COUNT 00167 * @see $maxHashCount 00168 * @see setMaxHashCount() 00169 */ 00170 public function getMaxHashCount() { 00171 return isset(self::$maxHashCount) ? self::$maxHashCount : self::MAX_HASH_COUNT; 00172 } 00173 00174 /** 00175 * Returns wether all prequesites for the hashing methods are matched 00176 * 00177 * @return boolean method available 00178 */ 00179 public function isAvailable() { 00180 return CRYPT_BLOWFISH; 00181 } 00182 00183 /** 00184 * Method returns minimum allowed log2 number of iterations for password stretching. 00185 * 00186 * @return integer minimum allowed log2 number of iterations for password stretching 00187 * @see MIN_HASH_COUNT 00188 * @see $minHashCount 00189 * @see setMinHashCount() 00190 */ 00191 public function getMinHashCount() { 00192 return isset(self::$minHashCount) ? self::$minHashCount : self::MIN_HASH_COUNT; 00193 } 00194 00195 /** 00196 * Returns length of a Blowfish salt in bytes. 00197 * 00198 * Overwrites {@link tx_saltedpasswords_salts_md5::getSaltLength()} 00199 * with Blowfish specifics. 00200 * 00201 * @return integer length of a Blowfish salt in bytes 00202 */ 00203 public function getSaltLength() { 00204 return self::$saltLengthBlowfish; 00205 } 00206 00207 /** 00208 * Returns setting string of Blowfish salted hashes. 00209 * 00210 * Overwrites {@link tx_saltedpasswords_salts_md5::getSetting()} 00211 * with Blowfish specifics. 00212 * 00213 * @return string setting string of Blowfish salted hashes 00214 */ 00215 public function getSetting() { 00216 return self::$settingBlowfish; 00217 } 00218 00219 /** 00220 * Checks whether a user's hashed password needs to be replaced with a new hash. 00221 * 00222 * This is typically called during the login process when the plain text 00223 * password is available. A new hash is needed when the desired iteration 00224 * count has changed through a change in the variable $hashCount or 00225 * HASH_COUNT. 00226 * 00227 * @param string $saltedPW: salted hash to check if it needs an update 00228 * @return boolean TRUE if salted hash needs an update, otherwise FALSE 00229 */ 00230 public function isHashUpdateNeeded($saltedPW) { 00231 // Check whether this was an updated password. 00232 if ((strncmp($saltedPW, '$2', 2)) || !$this->isValidSalt($saltedPW)) { 00233 return TRUE; 00234 } 00235 // Check whether the iteration count used differs from the standard number. 00236 $countLog2 = $this->getCountLog2($saltedPW); 00237 00238 return (!is_NULL($countLog2) && ($countLog2 < $this->getHashCount())); 00239 } 00240 00241 /** 00242 * Method determines if a given string is a valid salt. 00243 * 00244 * Overwrites {@link tx_saltedpasswords_salts_md5::isValidSalt()} with 00245 * Blowfish specifics. 00246 * 00247 * @param string $salt: string to check 00248 * @return boolean TRUE if it's valid salt, otherwise FALSE 00249 */ 00250 public function isValidSalt($salt) { 00251 $isValid = $skip = FALSE; 00252 00253 $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength()); 00254 00255 if (strlen($salt) >= $reqLenBase64) { 00256 // salt with prefixed setting 00257 if (!strncmp('$', $salt, 1)) { 00258 if (!strncmp($this->getSetting(), $salt, strlen($this->getSetting()))) { 00259 $isValid = TRUE; 00260 $salt = substr($salt, strrpos($salt, '$') + 1); 00261 } else { 00262 $skip = TRUE; 00263 } 00264 } 00265 00266 // checking base64 characters 00267 if (!$skip && (strlen($salt) >= $reqLenBase64)) { 00268 if (preg_match('/^[' . preg_quote($this->getItoa64(),'/') . ']{' . $reqLenBase64 . ',' . $reqLenBase64 . '}$/', substr($salt, 0, $reqLenBase64))) { 00269 $isValid = TRUE; 00270 } 00271 } 00272 } 00273 00274 return $isValid; 00275 } 00276 00277 /** 00278 * Method determines if a given string is a valid salted hashed password. 00279 * 00280 * @param string $saltedPW: string to check 00281 * @return boolean TRUE if it's valid salted hashed password, otherwise FALSE 00282 */ 00283 public function isValidSaltedPW($saltedPW) { 00284 $isValid = FALSE; 00285 00286 $isValid = (!strncmp($this->getSetting(), $saltedPW, strlen($this->getSetting()))) ? TRUE : FALSE; 00287 00288 if ($isValid) { 00289 $isValid = $this->isValidSalt($saltedPW); 00290 } 00291 00292 return $isValid; 00293 } 00294 00295 /** 00296 * Method sets log2 number of iterations for password stretching. 00297 * 00298 * @param integer $hashCount: log2 number of iterations for password stretching to set 00299 * @see HASH_COUNT 00300 * @see $hashCount 00301 * @see getHashCount() 00302 */ 00303 public function setHashCount($hashCount = NULL) { 00304 self::$hashCount = !is_NULL($hashCount) && is_int($hashCount) && $hashCount >= $this->getMinHashCount() && $hashCount <= $this->getMaxHashCount() ? $hashCount : self::HASH_COUNT; 00305 } 00306 00307 /** 00308 * Method sets maximum allowed log2 number of iterations for password stretching. 00309 * 00310 * @param integer $maxHashCount: maximum allowed log2 number of iterations for password stretching to set 00311 * @see MAX_HASH_COUNT 00312 * @see $maxHashCount 00313 * @see getMaxHashCount() 00314 */ 00315 public function setMaxHashCount($maxHashCount = NULL) { 00316 self::$maxHashCount = !is_NULL($maxHashCount) && is_int($maxHashCount) ? $maxHashCount : self::MAX_HASH_COUNT; 00317 } 00318 00319 /** 00320 * Method sets minimum allowed log2 number of iterations for password stretching. 00321 * 00322 * @param integer $minHashCount: minimum allowed log2 number of iterations for password stretching to set 00323 * @see MIN_HASH_COUNT 00324 * @see $minHashCount 00325 * @see getMinHashCount() 00326 */ 00327 public function setMinHashCount($minHashCount = NULL) { 00328 self::$minHashCount = !is_NULL($minHashCount) && is_int($minHashCount) ? $minHashCount : self::MIN_HASH_COUNT; 00329 } 00330 } 00331 00332 00333 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/saltedpasswords/classes/salts/class.tx_saltedpasswords_salts_blowfish.php'])) { 00334 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/saltedpasswords/classes/salts/class.tx_saltedpasswords_salts_blowfish.php']); 00335 } 00336 ?>
1.8.0