for more details. * * Copyright 2007-2009 Rejo Zenger * Copyright 2010-2016 Poweradmin Development Team * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * Password functions * * @package Poweradmin * @copyright 2007-2010 Rejo Zenger * @copyright 2010-2016 Poweradmin Development Team * @license http://opensource.org/licenses/GPL-3.0 GPL */ namespace Poweradmin; class Password { /** * Generate random salt for encryption * * @param int $len salt length (default=5) * * @return string salt string */ public static function salt($len = 5) { $valid_characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890@#$%^*()_-!'; $valid_len = strlen($valid_characters) - 1; $salt = ''; for ($i = 0; $i < $len; $i++) { $salt .= $valid_characters[mt_rand(0, $valid_len)]; } return $salt; } public static function hash($password) { global $password_encryption, $password_encryption_cost; if ($password_encryption === 'md5salt') { return self::gen_mix_salt($password); } elseif ($password_encryption === 'bcrypt') { return password_hash($password, PASSWORD_BCRYPT, array('cost' => $password_encryption_cost)); } else { return md5($password); } } public static function verify($password, $hash) { global $password_encryption; if ($password_encryption === 'md5salt') { return self::_strsafecmp(self::mix_salt(self::extract_salt($hash), $password), $hash); } elseif ($password_encryption === 'bcrypt') { return password_verify($password, $hash); } else { return self::_strsafecmp(md5($password), $hash); } } public static function needs_rehash($hash) { // @todo } /** * Generate random salt and salted password * * @param string $pass password * * @return string salted password */ private static function gen_mix_salt($pass) { $salt = self::salt(); return self::mix_salt($salt, $pass); } /** * Generate salted password * * @param string $salt salt * @param string $pass password * * @return string salted password */ private static function mix_salt($salt, $pass) { return md5($salt . $pass) . ':' . $salt; } /** * Extract salt from password * * @param string $password salted password * * @return string salt */ private static function extract_salt($password) { return substr(strstr($password, ':'), 1); } /** * Count the number of bytes in a string * @see https://github.com/ircmaxell/password_compat * * @param string $binary_string The input string * * @return int The number of bytes */ private static function _strlen($binary_string) { if (function_exists('mb_strlen')) { return mb_strlen($binary_string, '8bit'); } return strlen($binary_string); } /** * * @see https://github.com/ircmaxell/password_compat * * @param string $str1 The first string * @param string $str2 The second string * * @return bool true if they are equal, otherwise - false */ private static function _strsafecmp($str1, $str2) { if (!is_string($str1) || !is_string($str2) || self::_strlen($str1) !== self::_strlen($str2)) { return false; } $status = 0; for ($i = 0; $i < self::_strlen($str1); $i++) { $status |= (ord($str1[$i]) ^ ord($str2[$i])); } return $status === 0; } }