public function check($str, $hash) {
    $crypto  = $this->psl['crypt/crypto'];
    $compare = $this->psl['string/compare'];

    $hashInfo = $this->getInfo($hash);

    switch($hashInfo['algo']) {
      case self::PBKDF2:
        $param = array();
        list( , , $params, $hash, $salt) = explode('$', $hash);
        parse_str($params, $param);

        return $compare->timingSafe($crypto->pbkdf2($str, base64_decode($salt), $param['c'], $param['dk'], $param['f']), base64_decode($hash));
      break;

      case self::DRUPAL:
        $test = strpos($this->phpassHash($str, $hash), $hash);
        if($test === false || $test !== 0) {
        	return false;
        }
        return true;
      break;

      case self::BCRYPT;
      case self::BCRYPT_BC;
      case self::SHA256:
      case self::SHA512:
        return $compare->timingSafe(crypt($str, $hash), $hash);
      break;

      default:
        /* Not any of the supported formats. Try plain hash methods. */
      	$hashLen = strlen($hash);
      	switch($hashLen) {
      		case 32:
        	  $mode = 'md5';
      	  break;
      		case 40:
      		  $mode = 'sha1';
      	  break;
      		case 64:
            $mode = 'sha256';
          break;
      		case 128:
      		  $mode = 'sha512';
      		break;
      		default:
      		  return false;
      	}
      	return $compare->timingSafe(hash($mode, $str), $hash);
      break;
    }
  }