Esempio n. 1
0
 /**
  * @see phpsecStore::read()
  */
 public function read($type, $id)
 {
     /* The first part is prettu basic. Get stuff from databse. */
     $sth = $this->dbh->prepare('SELECT * FROM ' . $this->table . ' WHERE type = :type AND id = :id LIMIT 1');
     $data = array('id' => $id, 'type' => $type);
     $sth->execute($data);
     $data = $sth->fetch(PDO::FETCH_ASSOC);
     if ($data === false) {
         return false;
     }
     /* Calculate expected MAC. */
     $mac = phpsecCrypt::pbkdf2($data['data'], $id, 1000, 32);
     /* Compare MAC */
     if ($mac != $data['mac']) {
         phpsec::error('Message authentication code invalid while reading store');
         return false;
     }
     /* And success! */
     return unserialize($data['data']);
 }
Esempio n. 2
0
 /**
  * @see phpsecStore::write()
  */
 public function write($type, $id, $data)
 {
     $fileName = $this->fileName($type, $id);
     $data = serialize($data);
     $saveData['id'] = base64_encode($id);
     $saveData['mac'] = base64_encode(phpsecCrypt::pbkdf2($data, $id, 1000, 32));
     $saveData['time'] = time();
     $jsonData = json_encode($saveData);
     $fp = fopen($fileName, 'w');
     if ($fp !== false) {
         if (flock($fp, LOCK_EX)) {
             fwrite($fp, $jsonData . "\n\n");
             fwrite($fp, $data);
             flock($fp, LOCK_UN);
             fclose($fp);
             return true;
         } else {
             phpsec::error('Could not lock file while writing to store');
         }
     }
     return false;
 }
Esempio n. 3
0
 /**
  * Validate a user-supplied password against a stored password generated
  * using the phpsecPw::hash() method.
  *
  * @param string $password
  *   The password supplied by the user in the login form.
  *
  * @param string $dbPassword
  *   The json string fetched from the database, in the exact format
  *   as created by phpsecPw::hash().
  *
  * @return boolean
  *   True on password match, false otherwise.
  */
 public static function check($password, $dbPassword)
 {
     /**
      * Unserialize registered password array and validate it to ensure
      * we got a valid array.
      */
     $data = json_decode($dbPassword, true);
     $dataStructure = array('hash' => true, 'salt' => true, 'algo' => true);
     /* Check structure of array. */
     if ($data !== null && phpsec::arrayCheck($data, $dataStructure)) {
         /* Try to Base64 decode the salt.  base64_decode() will return false
          * if the string passed is not Base64 encoded. This way we can separate
          * binary salts from the old type of salts. */
         $decodedSalt = base64_decode($data['salt'], true);
         if ($decodedSalt !== false) {
             /* The salt was Base64 encoded. Use the decoded version. */
             $data['salt'] = $decodedSalt;
         }
         /**
          * We do a switch on the 6 first characters on the used hashing method.
          * This way we are able to catch when pbkdf2 is used, since this has
          * it's iteration count, derived key length and PRF attached to it:
          * "pbkdf2:iteration count:derived key length:PRF"
          */
         switch (substr($data['algo'], 0, 6)) {
             case self::phpsecPw_PBKDF2:
                 /* As described above, we need to seperate out the iteration count
                  * and derived key length. */
                 list($method, $iterationCount, $dkLen, $prf) = explode(':', $data['algo']);
                 /* Just to make sure anything fishy isn't going on. */
                 if (!is_numeric($iterationCount) || !is_numeric($dkLen)) {
                     return false;
                 }
                 /* Create a new derived key, with the iteration count and derived key length
                  * that were used when generating the original dk. */
                 $dk = phpsecCrypt::pbkdf2($password, $data['salt'], $iterationCount, $dkLen, $prf);
                 /* Check the new dk against the old base64 encoded dk. */
                 if ($dk === base64_decode($data['hash'])) {
                     return true;
                 }
                 break;
             default:
                 /* If not pbkdf2, we assume normal hash. */
                 $pwInjected = self::inject($password, $data['salt']);
                 /* Create a hash and see if it matches. */
                 if (hash($data['algo'], $pwInjected) == $data['hash']) {
                     return true;
                 }
         }
     } else {
         /* Invalid array supplied. */
         phpsec::error('Invalid data supplied. Expected serialized array as returned by pwHash()');
     }
     return false;
 }
Esempio n. 4
0
 /**
  * Initialize the library.
  * This method actually does several things:
  * 1. Registers the phpsec::load() method as autoload function.
  * 2. Opens the store. (connect to database etc.)
  * 3. Set charset for multibyte functions.
  * 4. Enable the phpSec session handler and starts a session (if session handler is enabled).
  * 5. Set's or get a UID that is used by phpsecCache.
  * 6. Decrypts cookies (if enabled).
  *
  * If no DSN (storage method) is configured. This method will stop after completing step 1.
  *
  * @return bool true
  *   Will always return true.
  */
 public static function init()
 {
     /* First of all, register the autoloading function.
      * If we have one set from somewhere else, keep it. */
     $autoLoadFunctions = spl_autoload_functions();
     $autoLoadFunctions[] = 'phpsec::load';
     foreach ($autoLoadFunctions as $autoLoadFunction) {
         spl_autoload_register($autoLoadFunction);
     }
     /* Autoloader all good to go. If we don't have a storage set
      * we can skip the rest of this method. */
     if (self::$_dsn === null) {
         return true;
     }
     /* Open store. */
     list($storeType, $storeDest) = explode(':', self::$_dsn);
     switch ($storeType) {
         case 'filesystem':
             self::$store = new phpsecStoreFilesystem($storeDest);
             break;
         case 'mysql':
             self::$store = new phpsecStorePdo($storeDest);
             break;
         default:
             self::error('Store type(' . $storeType . ') invalid', E_USER_ERROR);
     }
     /* Set the charset of the multibyte functions in PHP. */
     mb_internal_encoding(self::$_charset);
     mb_regex_encoding(self::$_charset);
     /* Enable the custom session handler if enabled. */
     if (self::$_sessenable === true) {
         ini_set('session.save_handler', 'user');
         session_set_save_handler('phpsecSession::open', 'phpsecSession::close', 'phpsecSession::read', 'phpsecSession::write', 'phpsecSession::destroy', 'phpsecSession::gc');
         /* Since we set a session cookie on our session handler, disable the built-in cookies. */
         ini_set('session.use_cookies', 0);
         /* Start a new session. */
         session_start();
         /* Check the fingerprint to see if it matches, if not clear session data. */
         $fingerprint = hash(self::HASH_TYPE, 'phpSec-fingerprint' . $_SERVER['HTTP_USER_AGENT']);
         if (!isset($_SESSION['phpSec-fingerprint'])) {
             $_SESSION['phpSec-fingerprint'] = $fingerprint;
         }
         if ($fingerprint != $_SESSION['phpSec-fingerprint']) {
             $_SESSION = array();
         }
     }
     /* Create a random token for each visitor and store it the users session.
        This is for example used to identify owners of cache data. */
     if (!isset($_SESSION['phpSec-uid'])) {
         self::$uid = self::genUid();
         $_SESSION['phpSec-uid'] = self::$uid;
     } else {
         self::$uid = $_SESSION['phpSec-uid'];
     }
     /* If the phpSec secure cookie monster is enabled detect encrypted cookies. */
     if (self::$_cookieenable === true) {
         phpsecCookie::detect();
     }
     return true;
 }
Esempio n. 5
0
 /**
  * XSS filter. Returns a string that is safe to use on the page.
  *
  * There are three modes:
  * strip: HTML is stripped from the string
  * before it is inserted.
  * escapeAll: HTML and special characters is escaped from the string
  * before it is inserted.
  * escape: Only HTML is escaped from the string. Special characters
  * is kept as is.
  * url: Encode a string according to RFC 3986 for use in a URL.
  *
  * @see https://phpseclib.com/manual/filter
  * @see http://www.faqs.org/rfcs/rfc3986
  *
  * @param string $str
  *   String to filter
  *
  * @param string $mode
  *   String defining what filter to apply.
  */
 public static function f($str, $mode = 'escape')
 {
     switch ($mode) {
         case 'strip':
             /* HTML tags are stripped from the string
                before it is used. */
             return strip_tags($str);
         case 'escapeAll':
             /* HTML and special characters are escaped from the string
                before it is used. */
             return htmlentities($str, ENT_QUOTES, phpSec::$_charset);
         case 'escape':
             /* Only HTML tags are escaped from the string. Special characters
                is kept as is. */
             return htmlspecialchars($str, ENT_NOQUOTES, phpSec::$_charset);
         case 'url':
             /* Encode a string according to RFC 3986 for use in a URL. */
             return rawurlencode($str);
         default:
             phpsec::error('Unknown variable type', E_USER_NOTICE);
     }
 }
 /**
  * Implement PBKDF2 as described in RFC 2898.
  *
  * @param string $p
  *   Password to protect.
  *
  * @param string $s
  *   Salt.
  *
  * @param integer $c
  *   Iteration count.
  *
  * @param integer $dkLen
  *   Derived key length.
  *
  * @param string $a
  *   A hash algorithm.
  *
  * @return binary
  *   Derived key.
  */
 public static function pbkdf2($p, $s, $c, $dkLen, $a = 'sha256')
 {
     $hLen = strlen(hash($a, null, true));
     /* Hash length. */
     $l = ceil($dkLen / $hLen);
     /* Length in blocks of derived key. */
     $dk = '';
     /* Derived key. */
     /* Step 1. Check dkLen. */
     if ($dkLen > (2 ^ 32 - 1) * $hLen) {
         phpsec::error('Derived key too long');
         return false;
     }
     for ($block = 1; $block <= $l; $block++) {
         /* Initial hash for this block. */
         $ib = $b = hash_hmac($a, $s . pack('N', $block), $p, true);
         /* Do block iterations. */
         for ($i = 1; $i < $c; $i++) {
             /* XOR iteration. */
             $ib ^= $b = hash_hmac($a, $b, $p, true);
         }
         /* Append iterated block. */
         $dk .= $ib;
     }
     /* Returned derived key. */
     return substr($dk, 0, $dkLen);
 }