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