12) { $iterations = intval(strpos($itoa64, substr($salt, 3, 1))); $salt = substr($salt, 4, 8); } else { $iterations = 15; $salt = Rhymix\Framework\Security::getRandom(8, 'hex'); } $count = 1 << $iterations; $hash = hash('sha512', $salt . $password, true); do { $hash = hash('sha512', $hash . $password, true); } while (--$count); $hash = self::drupal_base64($hash, strlen($hash), $itoa64); return substr('$S$' . $itoa64[$iterations] . $salt . $hash, 0, 55); } // Drupal's own Base64 implementation. protected static function drupal_base64($input, $count, $chars) { $output = ''; $i = 0; do { $value = ord($input[$i++]); $output .= $chars[$value & 0x3f]; if ($i < $count) $value |= ord($input[$i]) << 8; $output .= $chars[($value >> 6) & 0x3f]; if ($i++ >= $count) break; if ($i < $count) $value |= ord($input[$i]) << 16; $output .= $chars[($value >> 12) & 0x3f]; if ($i++ >= $count) break; $output .= $chars[($value >> 18) & 0x3f]; } while ($i < $count); return $output; } // Joomla's MD5-based password hashing algorithm. public static function joomla($password, $salt = null) { if ($salt !== null && strlen($salt) > 33) { $salt = substr($salt, 33); } else { $salt = Rhymix\Framework\Security::getRandom(32, 'hex'); } return md5($password . $salt) . ':' . $salt; } // KimsQ Rb's algorithms. public static function kimsqrb($password, $salt = null) { if (preg_match('/(\$[1-4])\$([0-9]{14})$/', $salt, $matches)) { $date = '$' . $matches[2]; $fakesalt = substr(base64_encode(substr($date, 1) . 'salt'), 0, 22); switch ($matches[1]) { case '$1': return self::password_hash($password, 1, ['cost' =>10, 'salt' => $fakesalt]) . '$1' . $date; case '$2': return hash('sha512', $password . $fakesalt) . '$2' . $date; case '$3': return hash('sha256', $password . $fakesalt) . '$3' . $date; case '$4': return md5(sha1(md5($password . $fakesalt))) . '$4' . $date; } } $date = '$' . date('YmdHis'); $fakesalt = substr(base64_encode(substr($date, 1) . 'salt'), 0, 22); return self::password_hash($password, 1, ['cost' =>10, 'salt' => $fakesalt]) . '$1' . $date; } // Bcrypt wrapper for PHP 5.4. public static function password_hash($password, $algo = 1, $options = []) { if (!isset($options['salt']) || !preg_match('/^[0-9a-zA-Z\.\/]{22,}$/', $options['salt'])) { $options['salt'] = Rhymix\Framework\Security::getRandom(22, 'alnum'); } if (!isset($options['cost']) || $options['cost'] < 4 || $options['cost'] > 31) { $options['cost'] = 10; } $salt = '$2y$' . sprintf('%02d', $options['cost']) . '$' . $options['salt']; return @crypt($password, $salt); } }