Esempio n. 1
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;
 }
 /**
  * Strip PKCS7 padding and decrypt
  * data encrypted by encrypt().
  *
  * @param string $data
  *   JSON string containing the encrypted data and meta information in the
  *   excact format as returned by encrypt().
  *
  * @return mixed
  *   Decrypted data in it's original form.
  */
 public static function decrypt($data, $key)
 {
     /* Decode the JSON string */
     $data = json_decode($data, true);
     $dataStructure = array('algo' => true, 'mode' => true, 'iv' => true, 'cdata' => true, 'mac' => true);
     if ($data === null || phpsec::arrayCheck($data, $dataStructure) !== true) {
         phpsec::error('Invalid data passed to decrypt()');
         return false;
     }
     /* Everything looks good so far. Let's continue.*/
     $td = mcrypt_module_open($data['algo'], '', $data['mode'], '');
     $block = mcrypt_enc_get_block_size($td);
     /* Check MAC. */
     if (base64_decode($data['mac']) != self::pbkdf2($data['cdata'], $key, 1000, 32)) {
         phpsec::error('Message authentication code invalid');
         return false;
     }
     /* Init mcrypt. */
     mcrypt_generic_init($td, $key, base64_decode($data['iv']));
     $decrypted = rtrim(mdecrypt_generic($td, base64_decode(self::stripPadding($block, $data['cdata']))));
     /* Close up. */
     mcrypt_generic_deinit($td);
     mcrypt_module_close($td);
     /*Return decrypted data. */
     return unserialize($decrypted);
 }