[TASK] Use name-resolution instead of strings where possible: 9
[Packages/TYPO3.CMS.git] / typo3 / sysext / saltedpasswords / Tests / Unit / Salt / Md5SaltTest.php
1 <?php
2 namespace TYPO3\CMS\Saltedpasswords\Tests\Unit\Salt;
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
17 /**
18 * Testcases for Md5Salt
19 *
20 * @author Marcus Krause <marcus#exp2009@t3sec.info>
21 */
22 class Md5SaltTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
23
24 /**
25 * Keeps instance of object to test.
26 *
27 * @var \TYPO3\CMS\Saltedpasswords\Salt\Md5Salt
28 */
29 protected $objectInstance = NULL;
30
31 /**
32 * Sets up the fixtures for this testcase.
33 *
34 * @return void
35 */
36 public function setUp() {
37 $this->objectInstance = $this->getMock(\TYPO3\CMS\Saltedpasswords\Salt\Md5Salt::class, array('dummy'));
38 }
39
40 /**
41 * Prepares a message to be shown when a salted hashing is not supported.
42 *
43 * @return string Empty string if salted hashing method is available, otherwise an according warning
44 */
45 protected function getWarningWhenMethodUnavailable() {
46 $warningMsg = '';
47 if (!CRYPT_MD5) {
48 $warningMsg = 'MD5 is not supported on your platform. ' . 'Then, some of the md5 tests will fail.';
49 }
50 return $warningMsg;
51 }
52
53 /**
54 * @test
55 */
56 public function hasCorrectBaseClass() {
57 $hasCorrectBaseClass = get_class($this->objectInstance) === \TYPO3\CMS\Saltedpasswords\Salt\Md5Salt::class;
58 // XCLASS ?
59 if (!$hasCorrectBaseClass && FALSE != get_parent_class($this->objectInstance)) {
60 $hasCorrectBaseClass = is_subclass_of($this->objectInstance, \TYPO3\CMS\Saltedpasswords\Salt\Md5Salt::class);
61 }
62 $this->assertTrue($hasCorrectBaseClass);
63 }
64
65 /**
66 * @test
67 */
68 public function nonZeroSaltLength() {
69 $this->assertTrue($this->objectInstance->getSaltLength() > 0);
70 }
71
72 /**
73 * @test
74 */
75 public function emptyPasswordResultsInNullSaltedPassword() {
76 $password = '';
77 $this->assertNull($this->objectInstance->getHashedPassword($password));
78 }
79
80 /**
81 * @test
82 */
83 public function nonEmptyPasswordResultsInNonNullSaltedPassword() {
84 $password = 'a';
85 $this->assertNotNull($this->objectInstance->getHashedPassword($password), $this->getWarningWhenMethodUnavailable());
86 }
87
88 /**
89 * @test
90 */
91 public function createdSaltedHashOfProperStructure() {
92 $password = 'password';
93 $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
94 $this->assertTrue($this->objectInstance->isValidSaltedPW($saltedHashPassword), $this->getWarningWhenMethodUnavailable());
95 }
96
97 /**
98 * @test
99 */
100 public function createdSaltedHashOfProperStructureForCustomSaltWithoutSetting() {
101 $password = 'password';
102 // custom salt without setting
103 $randomBytes = \TYPO3\CMS\Core\Utility\GeneralUtility::generateRandomBytes($this->objectInstance->getSaltLength());
104 $salt = $this->objectInstance->base64Encode($randomBytes, $this->objectInstance->getSaltLength());
105 $this->assertTrue($this->objectInstance->isValidSalt($salt), $this->getWarningWhenMethodUnavailable());
106 $saltedHashPassword = $this->objectInstance->getHashedPassword($password, $salt);
107 $this->assertTrue($this->objectInstance->isValidSaltedPW($saltedHashPassword), $this->getWarningWhenMethodUnavailable());
108 }
109
110 /**
111 * Tests authentication procedure with alphabet characters.
112 *
113 * Checks if a "plain-text password" is every time mapped to the
114 * same "salted password hash" when using the same salt.
115 *
116 * @test
117 */
118 public function authenticationWithValidAlphaCharClassPassword() {
119 $password = 'aEjOtY';
120 $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
121 $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
122 }
123
124 /**
125 * Tests authentication procedure with numeric characters.
126 *
127 * Checks if a "plain-text password" is every time mapped to the
128 * same "salted password hash" when using the same salt.
129 *
130 * @test
131 */
132 public function authenticationWithValidNumericCharClassPassword() {
133 $password = '01369';
134 $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
135 $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
136 }
137
138 /**
139 * Tests authentication procedure with US-ASCII special characters.
140 *
141 * Checks if a "plain-text password" is every time mapped to the
142 * same "salted password hash" when using the same salt.
143 *
144 * @test
145 */
146 public function authenticationWithValidAsciiSpecialCharClassPassword() {
147 $password = ' !"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~';
148 $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
149 $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
150 }
151
152 /**
153 * Tests authentication procedure with latin1 special characters.
154 *
155 * Checks if a "plain-text password" is every time mapped to the
156 * same "salted password hash" when using the same salt.
157 *
158 * @test
159 */
160 public function authenticationWithValidLatin1SpecialCharClassPassword() {
161 $password = '';
162 for ($i = 160; $i <= 191; $i++) {
163 $password .= chr($i);
164 }
165 $password .= chr(215) . chr(247);
166 $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
167 $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
168 }
169
170 /**
171 * Tests authentication procedure with latin1 umlauts.
172 *
173 * Checks if a "plain-text password" is every time mapped to the
174 * same "salted password hash" when using the same salt.
175 *
176 * @test
177 */
178 public function authenticationWithValidLatin1UmlautCharClassPassword() {
179 $password = '';
180 for ($i = 192; $i <= 214; $i++) {
181 $password .= chr($i);
182 }
183 for ($i = 216; $i <= 246; $i++) {
184 $password .= chr($i);
185 }
186 for ($i = 248; $i <= 255; $i++) {
187 $password .= chr($i);
188 }
189 $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
190 $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
191 }
192
193 /**
194 * @test
195 */
196 public function authenticationWithNonValidPassword() {
197 $password = 'password';
198 $password1 = $password . 'INVALID';
199 $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
200 $this->assertFalse($this->objectInstance->checkPassword($password1, $saltedHashPassword), $this->getWarningWhenMethodUnavailable());
201 }
202
203 /**
204 * @test
205 */
206 public function passwordVariationsResultInDifferentHashes() {
207 $pad = 'a';
208 $criticalPwLength = 0;
209 // We're using a constant salt.
210 $saltedHashPasswordCurrent = $salt = $this->objectInstance->getHashedPassword($pad);
211 for ($i = 0; $i <= 128; $i += 8) {
212 $password = str_repeat($pad, max($i, 1));
213 $saltedHashPasswordPrevious = $saltedHashPasswordCurrent;
214 $saltedHashPasswordCurrent = $this->objectInstance->getHashedPassword($password, $salt);
215 if ($i > 0 && $saltedHashPasswordPrevious === $saltedHashPasswordCurrent) {
216 $criticalPwLength = $i;
217 break;
218 }
219 }
220 $this->assertTrue($criticalPwLength == 0 || $criticalPwLength > 32, $this->getWarningWhenMethodUnavailable() . 'Duplicates of hashed passwords with plaintext password of length ' . $criticalPwLength . '+.');
221 }
222
223 /**
224 * @test
225 */
226 public function noUpdateNecessityForMd5() {
227 $password = 'password';
228 $saltedHashPassword = $this->objectInstance->getHashedPassword($password);
229 $this->assertFalse($this->objectInstance->isHashUpdateNeeded($saltedHashPassword));
230 }
231
232 }