TYPO3 CMS  TYPO3_7-6
BlowfishSalt.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
24 class BlowfishSalt extends Md5Salt
25 {
29  const HASH_COUNT = 7;
30 
35  const MAX_HASH_COUNT = 17;
36 
41  const MIN_HASH_COUNT = 4;
42 
49  protected static $hashCount;
50 
57  protected static $maxHashCount;
58 
65  protected static $minHashCount;
66 
72  protected static $saltLengthBlowfish = 16;
73 
79  protected static $settingBlowfish = '$2a$';
80 
90  protected function applySettingsToSalt($salt)
91  {
92  $saltWithSettings = $salt;
93  $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength());
94  // salt without setting
95  if (strlen($salt) == $reqLenBase64) {
96  $saltWithSettings = $this->getSetting() . sprintf('%02u', $this->getHashCount()) . '$' . $salt;
97  }
98  return $saltWithSettings;
99  }
100 
107  protected function getCountLog2($setting)
108  {
109  $countLog2 = null;
110  $setting = substr($setting, strlen($this->getSetting()));
111  $firstSplitPos = strpos($setting, '$');
112  // Hashcount existing
113  if ($firstSplitPos !== false && $firstSplitPos <= 2 && is_numeric(substr($setting, 0, $firstSplitPos))) {
114  $countLog2 = (int)substr($setting, 0, $firstSplitPos);
115  }
116  return $countLog2;
117  }
118 
127  public function getHashCount()
128  {
129  return isset(self::$hashCount) ? self::$hashCount : self::HASH_COUNT;
130  }
131 
140  public function getMaxHashCount()
141  {
142  return isset(self::$maxHashCount) ? self::$maxHashCount : self::MAX_HASH_COUNT;
143  }
144 
150  public function isAvailable()
151  {
152  return CRYPT_BLOWFISH;
153  }
154 
163  public function getMinHashCount()
164  {
165  return isset(self::$minHashCount) ? self::$minHashCount : self::MIN_HASH_COUNT;
166  }
167 
176  public function getSaltLength()
177  {
178  return self::$saltLengthBlowfish;
179  }
180 
189  public function getSetting()
190  {
191  return self::$settingBlowfish;
192  }
193 
205  public function isHashUpdateNeeded($saltedPW)
206  {
207  // Check whether this was an updated password.
208  if (strncmp($saltedPW, '$2', 2) || !$this->isValidSalt($saltedPW)) {
209  return true;
210  }
211  // Check whether the iteration count used differs from the standard number.
212  $countLog2 = $this->getCountLog2($saltedPW);
213  return !is_null($countLog2) && $countLog2 < $this->getHashCount();
214  }
215 
225  public function isValidSalt($salt)
226  {
227  $isValid = ($skip = false);
228  $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength());
229  if (strlen($salt) >= $reqLenBase64) {
230  // Salt with prefixed setting
231  if (!strncmp('$', $salt, 1)) {
232  if (!strncmp($this->getSetting(), $salt, strlen($this->getSetting()))) {
233  $isValid = true;
234  $salt = substr($salt, strrpos($salt, '$') + 1);
235  } else {
236  $skip = true;
237  }
238  }
239  // Checking base64 characters
240  if (!$skip && strlen($salt) >= $reqLenBase64) {
241  if (preg_match('/^[' . preg_quote($this->getItoa64(), '/') . ']{' . $reqLenBase64 . ',' . $reqLenBase64 . '}$/', substr($salt, 0, $reqLenBase64))) {
242  $isValid = true;
243  }
244  }
245  }
246  return $isValid;
247  }
248 
255  public function isValidSaltedPW($saltedPW)
256  {
257  $isValid = false;
258  $isValid = !strncmp($this->getSetting(), $saltedPW, strlen($this->getSetting()));
259  if ($isValid) {
260  $isValid = $this->isValidSalt($saltedPW);
261  }
262  return $isValid;
263  }
264 
273  public function setHashCount($hashCount = null)
274  {
275  self::$hashCount = !is_null($hashCount) && is_int($hashCount) && $hashCount >= $this->getMinHashCount() && $hashCount <= $this->getMaxHashCount() ? $hashCount : self::HASH_COUNT;
276  }
277 
286  public function setMaxHashCount($maxHashCount = null)
287  {
288  self::$maxHashCount = !is_null($maxHashCount) && is_int($maxHashCount) ? $maxHashCount : self::MAX_HASH_COUNT;
289  }
290 
299  public function setMinHashCount($minHashCount = null)
300  {
301  self::$minHashCount = !is_null($minHashCount) && is_int($minHashCount) ? $minHashCount : self::MIN_HASH_COUNT;
302  }
303 }