TYPO3 CMS  TYPO3_8-7
Md5SaltTest.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 Md5SaltTest 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\Md5Salt::class)
37  ->setMethods(['dummy'])
38  ->getMock();
39  }
40 
46  protected function getWarningWhenMethodUnavailable()
47  {
48  $warningMsg = '';
49  if (!CRYPT_MD5) {
50  $warningMsg = 'MD5 is not supported on your platform. ' . 'Then, some of the md5 tests will fail.';
51  }
52  return $warningMsg;
53  }
54 
58  public function hasCorrectBaseClass()
59  {
60  $hasCorrectBaseClass = get_class($this->objectInstance) === \TYPO3\CMS\Saltedpasswords\Salt\Md5Salt::class;
61  // XCLASS ?
62  if (!$hasCorrectBaseClass && false != get_parent_class($this->objectInstance)) {
63  $hasCorrectBaseClass = is_subclass_of($this->objectInstance, \TYPO3\CMS\Saltedpasswords\Salt\Md5Salt::class);
64  }
65  $this->assertTrue($hasCorrectBaseClass);
66  }
67 
71  public function nonZeroSaltLength()
72  {
73  $this->assertTrue($this->objectInstance->getSaltLength() > 0);
74  }
75 
80  {
81  $password = '';
82  $this->assertNull($this->objectInstance->getHashedPassword($password));
83  }
84 
89  {
90  $password = 'a';
91  $this->assertNotNull($this->objectInstance->getHashedPassword($password), $this->getWarningWhenMethodUnavailable());
92  }
93 
98  {
99  $password = 'password';
100  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
101  $this->assertTrue($this->objectInstance->isValidSaltedPW($saltedHashPassword), $this->getWarningWhenMethodUnavailable());
102  }
103 
108  {
109  $password = 'password';
110  // custom salt without setting
111  $randomBytes = (new Random())->generateRandomBytes($this->objectInstance->getSaltLength());
112  $salt = $this->objectInstance->base64Encode($randomBytes, $this->objectInstance->getSaltLength());
113  $this->assertTrue($this->objectInstance->isValidSalt($salt), $this->getWarningWhenMethodUnavailable());
114  $saltedHashPassword = $this->objectInstance->getHashedPassword($password, $salt);
115  $this->assertTrue($this->objectInstance->isValidSaltedPW($saltedHashPassword), $this->getWarningWhenMethodUnavailable());
116  }
117 
127  {
128  $password = 'password';
129  $saltedHashPassword = '$1$GNu9HdMt$RwkPb28pce4nXZfnplVZY/';
130  $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
131  }
132 
139  {
140  $password = 'password';
141  $saltedHashPassword = '$1$GNu9HdMt$RwkPb28pce4nXZfnplVZY';
142  $this->assertFalse($this->objectInstance->checkPassword($password, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
143  }
144 
154  {
155  $password = 'aEjOtY';
156  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
157  $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
158  }
159 
169  {
170  $password = '01369';
171  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
172  $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
173  }
174 
184  {
185  $password = ' !"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~';
186  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
187  $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
188  }
189 
199  {
200  $password = '';
201  for ($i = 160; $i <= 191; $i++) {
202  $password .= chr($i);
203  }
204  $password .= chr(215) . chr(247);
205  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
206  $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
207  }
208 
218  {
219  $password = '';
220  for ($i = 192; $i <= 214; $i++) {
221  $password .= chr($i);
222  }
223  for ($i = 216; $i <= 246; $i++) {
224  $password .= chr($i);
225  }
226  for ($i = 248; $i <= 255; $i++) {
227  $password .= chr($i);
228  }
229  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
230  $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
231  }
232 
237  {
238  $password = 'password';
239  $password1 = $password . 'INVALID';
240  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
241  $this->assertFalse($this->objectInstance->checkPassword($password1, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
242  }
243 
248  {
249  $pad = 'a';
250  $criticalPwLength = 0;
251  // We're using a constant salt.
252  $saltedHashPasswordCurrent = $salt = $this->objectInstance->getHashedPassword($pad);
253  for ($i = 0; $i <= 128; $i += 8) {
254  $password = str_repeat($pad, max($i, 1));
255  $saltedHashPasswordPrevious = $saltedHashPasswordCurrent;
256  $saltedHashPasswordCurrent = $this->objectInstance->getHashedPassword($password, $salt);
257  if ($i > 0 && $saltedHashPasswordPrevious === $saltedHashPasswordCurrent) {
258  $criticalPwLength = $i;
259  break;
260  }
261  }
262  $this->assertTrue($criticalPwLength == 0 || $criticalPwLength > 32, $this->getWarningWhenMethodUnavailable() . 'Duplicates of hashed passwords with plaintext password of length ' . $criticalPwLength . '+.');
263  }
264 
268  public function noUpdateNecessityForMd5()
269  {
270  $password = 'password';
271  $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
272  $this->assertFalse($this->objectInstance->isHashUpdateNeeded($saltedHashPassword));
273  }
274 }