TYPO3 CMS  TYPO3_8-7
BlowfishSaltTest.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 
18 
22 class BlowfishSaltTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
23 {
29  protected $objectInstance = null;
30 
34  protected function setUp()
35  {
36  $this->objectInstance = $this->getMockBuilder(\TYPO3\CMS\Saltedpasswords\Salt\BlowfishSalt::class)
37  ->setMethods(['dummy'])
38  ->getMock();
39  }
40 
44  protected function skipTestIfBlowfishIsNotAvailable()
45  {
46  if (!CRYPT_BLOWFISH) {
47  $this->markTestSkipped('Blowfish is not supported on your platform.');
48  }
49  }
50 
54  public function hasCorrectBaseClass()
55  {
56  $hasCorrectBaseClass = get_class($this->objectInstance) === \TYPO3\CMS\Saltedpasswords\Salt\BlowfishSalt::class;
57  // XCLASS ?
58  if (!$hasCorrectBaseClass && false != get_parent_class($this->objectInstance)) {
59  $hasCorrectBaseClass = is_subclass_of($this->objectInstance, \TYPO3\CMS\Saltedpasswords\Salt\BlowfishSalt::class);
60  }
61  $this->assertTrue($hasCorrectBaseClass);
62  }
63 
67  public function nonZeroSaltLength()
68  {
69  $this->assertTrue($this->objectInstance->getSaltLength() > 0);
70  }
71 
76  {
77  $password = '';
78  $this->assertNull($this->objectInstance->getHashedPassword($password));
79  }
80 
85  {
87  $password = 'a';
88  $this->assertNotNull($this->objectInstance->getHashedPassword($password));
89  }
90 
95  {
97  $password = 'password';
98  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
99  $this->assertTrue($this->objectInstance->isValidSaltedPW($saltedHashPassword));
100  }
101 
106  {
108  $password = 'password';
109  // custom salt without setting
110  $randomBytes = (new Random())->generateRandomBytes($this->objectInstance->getSaltLength());
111  $salt = $this->objectInstance->base64Encode($randomBytes, $this->objectInstance->getSaltLength());
112  $this->assertTrue($this->objectInstance->isValidSalt($salt));
113  $saltedHashPassword = $this->objectInstance->getHashedPassword($password, $salt);
114  $this->assertTrue($this->objectInstance->isValidSaltedPW($saltedHashPassword));
115  }
116 
121  {
123  $password = 'password';
124  $minHashCount = $this->objectInstance->getMinHashCount();
125  $this->objectInstance->setHashCount($minHashCount);
126  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
127  $this->assertTrue($this->objectInstance->isValidSaltedPW($saltedHashPassword));
128  // reset hashcount
129  $this->objectInstance->setHashCount(null);
130  }
131 
141  {
142  $password = 'password';
143  $saltedHashPassword = '$2a$07$Rvtl6CyMhR8GZGhHypjwOuydeN0nKFAlgo1LmmGrLowtIrtkov5Na';
144  $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword));
145  }
146 
153  {
154  $password = 'password';
155  $saltedHashPassword = '$2a$07$Rvtl6CyMhR8GZGhHypjwOuydeN0nKFAlgo1LmmGrLowtIrtkov5N';
156  $this->assertFalse($this->objectInstance->checkPassword($password, $saltedHashPassword));
157  }
158 
168  {
170  $password = 'aEjOtY';
171  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
172  $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword));
173  }
174 
184  {
186  $password = '01369';
187  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
188  $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword));
189  }
190 
200  {
202  $password = ' !"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~';
203  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
204  $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword));
205  }
206 
216  {
218  $password = '';
219  for ($i = 160; $i <= 191; $i++) {
220  $password .= chr($i);
221  }
222  $password .= chr(215) . chr(247);
223  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
224  $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword));
225  }
226 
236  {
238  $password = '';
239  for ($i = 192; $i <= 214; $i++) {
240  $password .= chr($i);
241  }
242  for ($i = 216; $i <= 246; $i++) {
243  $password .= chr($i);
244  }
245  for ($i = 248; $i <= 255; $i++) {
246  $password .= chr($i);
247  }
248  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
249  $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword));
250  }
251 
256  {
258  $password = 'password';
259  $password1 = $password . 'INVALID';
260  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
261  $this->assertFalse($this->objectInstance->checkPassword($password1, $saltedHashPassword));
262  }
263 
268  {
270  $pad = 'a';
271  $criticalPwLength = 0;
272  // We're using a constant salt.
273  $saltedHashPasswordCurrent = $salt = $this->objectInstance->getHashedPassword($pad);
274  for ($i = 0; $i <= 128; $i += 8) {
275  $password = str_repeat($pad, max($i, 1));
276  $saltedHashPasswordPrevious = $saltedHashPasswordCurrent;
277  $saltedHashPasswordCurrent = $this->objectInstance->getHashedPassword($password, $salt);
278  if ($i > 0 && $saltedHashPasswordPrevious === $saltedHashPasswordCurrent) {
279  $criticalPwLength = $i;
280  break;
281  }
282  }
283  $this->assertTrue($criticalPwLength == 0 || $criticalPwLength > 32, 'Duplicates of hashed passwords with plaintext password of length ' . $criticalPwLength . '+.');
284  }
285 
289  public function modifiedMinHashCount()
290  {
291  $minHashCount = $this->objectInstance->getMinHashCount();
292  $this->objectInstance->setMinHashCount($minHashCount - 1);
293  $this->assertTrue($this->objectInstance->getMinHashCount() < $minHashCount);
294  $this->objectInstance->setMinHashCount($minHashCount + 1);
295  $this->assertTrue($this->objectInstance->getMinHashCount() > $minHashCount);
296  }
297 
301  public function modifiedMaxHashCount()
302  {
303  $maxHashCount = $this->objectInstance->getMaxHashCount();
304  $this->objectInstance->setMaxHashCount($maxHashCount + 1);
305  $this->assertTrue($this->objectInstance->getMaxHashCount() > $maxHashCount);
306  $this->objectInstance->setMaxHashCount($maxHashCount - 1);
307  $this->assertTrue($this->objectInstance->getMaxHashCount() < $maxHashCount);
308  }
309 
313  public function modifiedHashCount()
314  {
315  $hashCount = $this->objectInstance->getHashCount();
316  $this->objectInstance->setMaxHashCount($hashCount + 1);
317  $this->objectInstance->setHashCount($hashCount + 1);
318  $this->assertTrue($this->objectInstance->getHashCount() > $hashCount);
319  $this->objectInstance->setMinHashCount($hashCount - 1);
320  $this->objectInstance->setHashCount($hashCount - 1);
321  $this->assertTrue($this->objectInstance->getHashCount() < $hashCount);
322  // reset hashcount
323  $this->objectInstance->setHashCount(null);
324  }
325 
330  {
332  $password = 'password';
333  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
334  $this->assertFalse($this->objectInstance->isHashUpdateNeeded($saltedHashPassword));
335  }
336 
341  {
342  $password = 'password';
343  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
344  $increasedHashCount = $this->objectInstance->getHashCount() + 1;
345  $this->objectInstance->setMaxHashCount($increasedHashCount);
346  $this->objectInstance->setHashCount($increasedHashCount);
347  $this->assertTrue($this->objectInstance->isHashUpdateNeeded($saltedHashPassword));
348  // reset hashcount
349  $this->objectInstance->setHashCount(null);
350  }
351 
356  {
358  $password = 'password';
359  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
360  $decreasedHashCount = $this->objectInstance->getHashCount() - 1;
361  $this->objectInstance->setMinHashCount($decreasedHashCount);
362  $this->objectInstance->setHashCount($decreasedHashCount);
363  $this->assertFalse($this->objectInstance->isHashUpdateNeeded($saltedHashPassword));
364  // reset hashcount
365  $this->objectInstance->setHashCount(null);
366  }
367 }