|
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: tx_saltedpasswords_salts_blowfishTest.php 10120 2011-01-18 20:03:36Z ohader $ 00032 */ 00033 00034 /** 00035 * Testcases for class tx_saltedpasswords_salts_blowfish. 00036 * 00037 * @author Marcus Krause <marcus#exp2009@t3sec.info> 00038 * @package TYPO3 00039 * @subpackage tx_saltedpasswords 00040 */ 00041 class tx_saltedpasswords_salts_blowfishTest extends tx_phpunit_testcase { 00042 00043 00044 /** 00045 * Keeps instance of object to test. 00046 * 00047 * @var tx_saltedpasswords_salts_blowfish 00048 */ 00049 protected $objectInstance = NULL; 00050 00051 00052 /** 00053 * Sets up the fixtures for this testcase. 00054 * 00055 * @return void 00056 */ 00057 public function setUp() { 00058 $this->objectInstance = t3lib_div::makeInstance('tx_saltedpasswords_salts_blowfish'); 00059 } 00060 00061 /** 00062 * Tears down objects and settings created in this testcase. 00063 * 00064 * @return void 00065 */ 00066 public function tearDown() { 00067 unset($this->objectInstance); 00068 } 00069 00070 /** 00071 * Marks tests as skipped if the blowfish method is not available. 00072 * 00073 * @return void 00074 */ 00075 protected function skipTestIfBlowfishIsNotAvailable() { 00076 if (!CRYPT_BLOWFISH) { 00077 $this->markTestSkipped('Blowfish is not supported on your platform.'); 00078 } 00079 } 00080 00081 /** 00082 * @test 00083 */ 00084 public function hasCorrectBaseClass() { 00085 00086 $hasCorrectBaseClass = (0 === strcmp('tx_saltedpasswords_salts_blowfish', get_class($this->objectInstance))) ? TRUE : FALSE; 00087 00088 // XCLASS ? 00089 if (!$hasCorrectBaseClass && FALSE != get_parent_class($this->objectInstance)) { 00090 $hasCorrectBaseClass = is_subclass_of($this->objectInstance, 'tx_saltedpasswords_salts_blowfish'); 00091 } 00092 00093 $this->assertTrue($hasCorrectBaseClass); 00094 } 00095 00096 /** 00097 * @test 00098 */ 00099 public function nonZeroSaltLength() { 00100 $this->assertTrue($this->objectInstance->getSaltLength() > 0); 00101 } 00102 00103 /** 00104 * @test 00105 */ 00106 public function emptyPasswordResultsInNullSaltedPassword() { 00107 $password = ''; 00108 $this->assertNull($this->objectInstance->getHashedPassword($password)); 00109 } 00110 00111 /** 00112 * @test 00113 */ 00114 public function nonEmptyPasswordResultsInNonNullSaltedPassword() { 00115 $this->skipTestIfBlowfishIsNotAvailable(); 00116 00117 $password = 'a'; 00118 $this->assertNotNull($this->objectInstance->getHashedPassword($password)); 00119 } 00120 00121 /** 00122 * @test 00123 */ 00124 public function createdSaltedHashOfProperStructure() { 00125 $this->skipTestIfBlowfishIsNotAvailable(); 00126 00127 $password = 'password'; 00128 $saltedHashPassword = $this->objectInstance->getHashedPassword($password); 00129 $this->assertTrue($this->objectInstance->isValidSaltedPW($saltedHashPassword)); 00130 } 00131 00132 /** 00133 * @test 00134 */ 00135 public function createdSaltedHashOfProperStructureForCustomSaltWithoutSetting() { 00136 $this->skipTestIfBlowfishIsNotAvailable(); 00137 00138 $password = 'password'; 00139 00140 // custom salt without setting 00141 $randomBytes = t3lib_div::generateRandomBytes($this->objectInstance->getSaltLength()); 00142 $salt = $this->objectInstance->base64Encode($randomBytes, $this->objectInstance->getSaltLength()); 00143 $this->assertTrue($this->objectInstance->isValidSalt($salt)); 00144 00145 $saltedHashPassword = $this->objectInstance->getHashedPassword($password, $salt); 00146 $this->assertTrue($this->objectInstance->isValidSaltedPW($saltedHashPassword)); 00147 } 00148 00149 /** 00150 * @test 00151 */ 00152 public function createdSaltedHashOfProperStructureForMaximumHashCount() { 00153 $this->skipTestIfBlowfishIsNotAvailable(); 00154 00155 $password = 'password'; 00156 $maxHashCount = $this->objectInstance->getMaxHashCount(); 00157 $this->objectInstance->setHashCount($maxHashCount); 00158 $saltedHashPassword = $this->objectInstance->getHashedPassword($password); 00159 $this->assertTrue($this->objectInstance->isValidSaltedPW($saltedHashPassword)); 00160 // reset hashcount 00161 $this->objectInstance->setHashCount(NULL); 00162 } 00163 00164 /** 00165 * @test 00166 */ 00167 public function createdSaltedHashOfProperStructureForMinimumHashCount() { 00168 $this->skipTestIfBlowfishIsNotAvailable(); 00169 00170 $password = 'password'; 00171 $minHashCount = $this->objectInstance->getMinHashCount(); 00172 $this->objectInstance->setHashCount($minHashCount); 00173 $saltedHashPassword = $this->objectInstance->getHashedPassword($password); 00174 $this->assertTrue($this->objectInstance->isValidSaltedPW($saltedHashPassword)); 00175 // reset hashcount 00176 $this->objectInstance->setHashCount(NULL); 00177 } 00178 00179 /** 00180 * Tests authentication procedure with alphabet characters. 00181 * 00182 * Checks if a "plain-text password" is everytime mapped to the 00183 * same "salted password hash" when using the same salt. 00184 * 00185 * @test 00186 */ 00187 public function authenticationWithValidAlphaCharClassPassword() { 00188 $this->skipTestIfBlowfishIsNotAvailable(); 00189 00190 $password = 'aEjOtY'; 00191 00192 $saltedHashPassword = $this->objectInstance->getHashedPassword($password); 00193 $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword)); 00194 } 00195 00196 /** 00197 * Tests authentication procedure with numeric characters. 00198 * 00199 * Checks if a "plain-text password" is everytime mapped to the 00200 * same "salted password hash" when using the same salt. 00201 * 00202 * @test 00203 */ 00204 public function authenticationWithValidNumericCharClassPassword() { 00205 $this->skipTestIfBlowfishIsNotAvailable(); 00206 00207 $password = '01369'; 00208 00209 $saltedHashPassword = $this->objectInstance->getHashedPassword($password); 00210 $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword)); 00211 } 00212 00213 /** 00214 * Tests authentication procedure with US-ASCII special characters. 00215 * 00216 * Checks if a "plain-text password" is everytime mapped to the 00217 * same "salted password hash" when using the same salt. 00218 * 00219 * @test 00220 */ 00221 public function authenticationWithValidAsciiSpecialCharClassPassword() { 00222 $this->skipTestIfBlowfishIsNotAvailable(); 00223 00224 $password = ' !"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~'; 00225 00226 $saltedHashPassword = $this->objectInstance->getHashedPassword($password); 00227 $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword)); 00228 } 00229 00230 /** 00231 * Tests authentication procedure with latin1 special characters. 00232 * 00233 * Checks if a "plain-text password" is everytime mapped to the 00234 * same "salted password hash" when using the same salt. 00235 * 00236 * @test 00237 */ 00238 public function authenticationWithValidLatin1SpecialCharClassPassword() { 00239 $this->skipTestIfBlowfishIsNotAvailable(); 00240 00241 $password = ''; 00242 for ($i = 160; $i <= 191; $i++) { 00243 $password .= chr($i); 00244 } 00245 $password .= chr(215) . chr(247); 00246 00247 $saltedHashPassword = $this->objectInstance->getHashedPassword($password); 00248 $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword)); 00249 } 00250 00251 /** 00252 * Tests authentication procedure with latin1 umlauts. 00253 * 00254 * Checks if a "plain-text password" is everytime mapped to the 00255 * same "salted password hash" when using the same salt. 00256 * 00257 * @test 00258 */ 00259 public function authenticationWithValidLatin1UmlautCharClassPassword() { 00260 $this->skipTestIfBlowfishIsNotAvailable(); 00261 00262 $password = ''; 00263 for ($i = 192; $i <= 214; $i++) { 00264 $password .= chr($i); 00265 } 00266 for ($i = 216; $i <= 246; $i++) { 00267 $password .= chr($i); 00268 } 00269 for ($i = 248; $i <= 255; $i++) { 00270 $password .= chr($i); 00271 } 00272 00273 $saltedHashPassword = $this->objectInstance->getHashedPassword($password); 00274 $this->assertTrue($this->objectInstance->checkPassword($password, $saltedHashPassword)); 00275 } 00276 00277 /** 00278 * @test 00279 */ 00280 public function authenticationWithNonValidPassword() { 00281 $this->skipTestIfBlowfishIsNotAvailable(); 00282 00283 $password = 'password'; 00284 $password1 = $password . 'INVALID'; 00285 $saltedHashPassword = $this->objectInstance->getHashedPassword($password); 00286 $this->assertFalse($this->objectInstance->checkPassword($password1, $saltedHashPassword)); 00287 } 00288 00289 /** 00290 * @test 00291 */ 00292 public function passwordVariationsResultInDifferentHashes() { 00293 $this->skipTestIfBlowfishIsNotAvailable(); 00294 00295 $pad = 'a'; 00296 $password = ''; 00297 $criticalPwLength = 0; 00298 // We're using a constant salt. 00299 $saltedHashPasswordPrevious = $saltedHashPasswordCurrent = $salt = $this->objectInstance->getHashedPassword($pad); 00300 00301 for ($i = 0; $i <= 128; $i += 8) { 00302 $password = str_repeat($pad, max($i, 1)); 00303 $saltedHashPasswordPrevious = $saltedHashPasswordCurrent; 00304 $saltedHashPasswordCurrent = $this->objectInstance->getHashedPassword($password, $salt); 00305 if ($i > 0 && 0 == strcmp($saltedHashPasswordPrevious, $saltedHashPasswordCurrent)) { 00306 $criticalPwLength = $i; 00307 break; 00308 } 00309 } 00310 $this->assertTrue(($criticalPwLength == 0) || ($criticalPwLength > 32), 'Duplicates of hashed passwords with plaintext password of length ' . $criticalPwLength . '+.'); 00311 } 00312 00313 /** 00314 * @test 00315 */ 00316 public function modifiedMinHashCount() { 00317 $minHashCount = $this->objectInstance->getMinHashCount(); 00318 $this->objectInstance->setMinHashCount($minHashCount - 1); 00319 $this->assertTrue($this->objectInstance->getMinHashCount() < $minHashCount); 00320 $this->objectInstance->setMinHashCount($minHashCount + 1); 00321 $this->assertTrue($this->objectInstance->getMinHashCount() > $minHashCount); 00322 } 00323 00324 /** 00325 * @test 00326 */ 00327 public function modifiedMaxHashCount() { 00328 $maxHashCount = $this->objectInstance->getMaxHashCount(); 00329 $this->objectInstance->setMaxHashCount($maxHashCount + 1); 00330 $this->assertTrue($this->objectInstance->getMaxHashCount() > $maxHashCount); 00331 $this->objectInstance->setMaxHashCount($maxHashCount - 1); 00332 $this->assertTrue($this->objectInstance->getMaxHashCount() < $maxHashCount); 00333 } 00334 00335 /** 00336 * @test 00337 */ 00338 public function modifiedHashCount() { 00339 $hashCount = $this->objectInstance->getHashCount(); 00340 $this->objectInstance->setMaxHashCount($hashCount + 1); 00341 $this->objectInstance->setHashCount($hashCount + 1); 00342 $this->assertTrue($this->objectInstance->getHashCount() > $hashCount); 00343 $this->objectInstance->setMinHashCount($hashCount - 1); 00344 $this->objectInstance->setHashCount($hashCount - 1); 00345 $this->assertTrue($this->objectInstance->getHashCount() < $hashCount); 00346 // reset hashcount 00347 $this->objectInstance->setHashCount(NULL); 00348 } 00349 00350 /** 00351 * @test 00352 */ 00353 public function updateNecessityForValidSaltedPassword() { 00354 $this->skipTestIfBlowfishIsNotAvailable(); 00355 00356 $password = 'password'; 00357 $saltedHashPassword = $this->objectInstance->getHashedPassword($password); 00358 $this->assertFalse($this->objectInstance->isHashUpdateNeeded($saltedHashPassword)); 00359 } 00360 00361 /** 00362 * @test 00363 */ 00364 public function updateNecessityForIncreasedHashcount() { 00365 $password = 'password'; 00366 $saltedHashPassword = $this->objectInstance->getHashedPassword($password); 00367 $increasedHashCount = $this->objectInstance->getHashCount() + 1; 00368 $this->objectInstance->setMaxHashCount($increasedHashCount); 00369 $this->objectInstance->setHashCount($increasedHashCount); 00370 $this->assertTrue($this->objectInstance->isHashUpdateNeeded($saltedHashPassword)); 00371 // reset hashcount 00372 $this->objectInstance->setHashCount(NULL); 00373 } 00374 00375 /** 00376 * @test 00377 */ 00378 public function updateNecessityForDecreasedHashcount() { 00379 $this->skipTestIfBlowfishIsNotAvailable(); 00380 00381 $password = 'password'; 00382 $saltedHashPassword = $this->objectInstance->getHashedPassword($password); 00383 $decreasedHashCount = $this->objectInstance->getHashCount() - 1; 00384 $this->objectInstance->setMinHashCount($decreasedHashCount); 00385 $this->objectInstance->setHashCount($decreasedHashCount); 00386 $this->assertFalse($this->objectInstance->isHashUpdateNeeded($saltedHashPassword)); 00387 // reset hashcount 00388 $this->objectInstance->setHashCount(NULL); 00389 } 00390 } 00391 ?>
1.8.0