TYPO3 API  SVNRelease
class.tx_saltedpasswords_salts_md5.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 class "tx_saltedpasswords_salts_md5"
00029  * that provides MD5 salted hashing.
00030  *
00031  * $Id: class.tx_saltedpasswords_salts_md5.php 10120 2011-01-18 20:03:36Z ohader $
00032  */
00033 
00034 
00035 /**
00036  * Class that implements MD5 salted hashing based on PHP's
00037  * crypt() function.
00038  *
00039  * MD5 salted hashing with PHP's crypt() should be available
00040  * on most of the systems.
00041  *
00042  * @author      Marcus Krause <marcus#exp2009@t3sec.info>
00043  *
00044  * @since       2009-09-06
00045  * @package     TYPO3
00046  * @subpackage  tx_saltedpasswords
00047  */
00048 class tx_saltedpasswords_salts_md5 extends tx_saltedpasswords_abstract_salts implements tx_saltedpasswords_salts {
00049     /**
00050      * Keeps a string for mapping an int to the corresponding
00051      * base 64 character.
00052      */
00053     const ITOA64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
00054 
00055     /**
00056      * Keeps length of a MD5 salt in bytes.
00057      *
00058      * @var integer
00059      */
00060     static protected $saltLengthMD5 = 6;
00061 
00062     /**
00063      * Keeps suffix to be appended to a salt.
00064      *
00065      * @var string
00066      */
00067     static protected $saltSuffixMD5 = '$';
00068 
00069     /**
00070      * Setting string to indicate type of hashing method (md5).
00071      *
00072      * @var string
00073      */
00074     static protected $settingMD5 = '$1$';
00075 
00076 
00077     /**
00078      * Method applies settings (prefix, suffix) to a salt.
00079      *
00080      * @param   string      $salt: a salt to apply setting to
00081      * @return  string      salt with setting
00082      */
00083     protected function applySettingsToSalt($salt) {
00084         $saltWithSettings = $salt;
00085 
00086         $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength());
00087 
00088             // salt without setting
00089         if (strlen($salt) == $reqLenBase64) {
00090             $saltWithSettings = $this->getSetting() . $salt . $this->getSaltSuffix();
00091 
00092         }
00093 
00094         return $saltWithSettings;
00095     }
00096 
00097     /**
00098      * Method checks if a given plaintext password is correct by comparing it with
00099      * a given salted hashed password.
00100      *
00101      * @param   string      $plainPW: plain-text password to compare with salted hash
00102      * @param   string      $saltedHashPW: salted hash to compare plain-text password with
00103      * @return  boolean     TRUE, if plain-text password matches the salted hash, otherwise FALSE
00104      */
00105     public function checkPassword($plainPW, $saltedHashPW) {
00106         $isCorrect = FALSE;
00107 
00108         if ($this->isValidSalt($saltedHashPW)) {
00109             $isCorrect = (crypt($plainPW,$saltedHashPW) == $saltedHashPW);
00110         }
00111 
00112         return $isCorrect;
00113     }
00114 
00115     /**
00116      * Generates a random base 64-encoded salt prefixed and suffixed with settings for the hash.
00117      *
00118      * Proper use of salts may defeat a number of attacks, including:
00119      *  - The ability to try candidate passwords against multiple hashes at once.
00120      *  - The ability to use pre-hashed lists of candidate passwords.
00121      *  - The ability to determine whether two users have the same (or different)
00122      *    password without actually having to guess one of the passwords.
00123      *
00124      * @return  string      a character string containing settings and a random salt
00125      */
00126     protected function getGeneratedSalt() {
00127         $randomBytes = t3lib_div::generateRandomBytes($this->getSaltLength());
00128 
00129         return $this->base64Encode($randomBytes, $this->getSaltLength());
00130     }
00131 
00132     /**
00133      * Method creates a salted hash for a given plaintext password
00134      *
00135      * @param   string      $password: plaintext password to create a salted hash from
00136      * @param   string      $salt: optional custom salt with setting to use
00137      * @return  string      salted hashed password
00138      */
00139     public function getHashedPassword($password, $salt = NULL) {
00140         $saltedPW = NULL;
00141         if (!empty($password)) {
00142             if (empty($salt) || !$this->isValidSalt($salt)) {
00143                 $salt = $this->getGeneratedSalt();
00144             }
00145             $saltedPW = crypt($password, $this->applySettingsToSalt($salt));
00146         }
00147 
00148         return $saltedPW;
00149     }
00150 
00151     /**
00152      * Returns a string for mapping an int to the corresponding base 64 character.
00153      *
00154      * @return  string      string for mapping an int to the corresponding base 64 character
00155      */
00156     protected function getItoa64() {
00157         return self::ITOA64;
00158     }
00159 
00160     /**
00161      * Returns wether all prequesites for the hashing methods are matched
00162      *
00163      * @return  boolean     method available
00164      */
00165     public function isAvailable() {
00166         return CRYPT_MD5;
00167     }
00168 
00169     /**
00170      * Returns length of a MD5 salt in bytes.
00171      *
00172      * @return  integer     length of a MD5 salt in bytes
00173      */
00174     public function getSaltLength() {
00175         return self::$saltLengthMD5;
00176     }
00177 
00178     /**
00179      * Returns suffix to be appended to a salt.
00180      *
00181      * @return  string      suffix of a salt
00182      */
00183     protected function getSaltSuffix() {
00184         return self::$saltSuffixMD5;
00185     }
00186 
00187     /**
00188      * Returns setting string of MD5 salted hashes.
00189      *
00190      * @return  string      setting string of MD5 salted hashes
00191      */
00192     public function getSetting() {
00193         return self::$settingMD5;
00194     }
00195 
00196     /**
00197      * Checks whether a user's hashed password needs to be replaced with a new hash.
00198      *
00199      * This is typically called during the login process when the plain text
00200      * password is available.  A new hash is needed when the desired iteration
00201      * count has changed through a change in the variable $hashCount or
00202      * HASH_COUNT or if the user's password hash was generated in an bulk update
00203      * with class ext_update.
00204      *
00205      * @param   string      $passString: salted hash to check if it needs an update
00206      * @return  boolean     TRUE if salted hash needs an update, otherwise FALSE
00207      */
00208     public function isHashUpdateNeeded($passString) {
00209         return FALSE;
00210     }
00211 
00212     /**
00213      * Method determines if a given string is a valid salt
00214      *
00215      * @param   string      $salt:  string to check
00216      * @return  boolean     TRUE if it's valid salt, otherwise FALSE
00217      */
00218     public function isValidSalt($salt) {
00219         $isValid = $skip = FALSE;
00220 
00221         $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength());
00222 
00223         if (strlen($salt) >= $reqLenBase64) {
00224                         // salt with prefixed setting
00225             if (!strncmp('$', $salt, 1)) {
00226                 if (!strncmp($this->getSetting(), $salt, strlen($this->getSetting()))) {
00227                     $isValid = TRUE;
00228                     $salt = substr($salt, strlen($this->getSetting()));
00229                 } else {
00230                     $skip = TRUE;
00231                 }
00232             }
00233 
00234                 // checking base64 characters
00235             if (!$skip && (strlen($salt) >= $reqLenBase64)) {
00236                 if (preg_match('/^[' . preg_quote($this->getItoa64(),'/') . ']{' . $reqLenBase64 . ',' . $reqLenBase64 . '}$/', substr($salt, 0, $reqLenBase64))) {
00237                     $isValid = TRUE;
00238                 }
00239             }
00240         }
00241 
00242         return $isValid;
00243     }
00244 
00245     /**
00246      * Method determines if a given string is a valid salted hashed password.
00247      *
00248      * @param   string      $saltedPW: string to check
00249      * @return  boolean     TRUE if it's valid salted hashed password, otherwise FALSE
00250      */
00251     public function isValidSaltedPW($saltedPW) {
00252         $isValid = FALSE;
00253 
00254         $isValid = (!strncmp($this->getSetting(), $saltedPW, strlen($this->getSetting()))) ? TRUE : FALSE;
00255         if ($isValid) {
00256             $isValid = $this->isValidSalt($saltedPW);
00257         }
00258 
00259         return $isValid;
00260     }
00261 }
00262 
00263 
00264 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/saltedpasswords/classes/salts/class.tx_saltedpasswords_salts_md5.php'])) {
00265     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/saltedpasswords/classes/salts/class.tx_saltedpasswords_salts_md5.php']);
00266 }
00267 ?>