это мой способ шифрования, который я только что сделал в php и с его помощью я храню свои пароли в базе данных
это мой код для страницы входа
<?php
session_start();
require("db_connection.php");
require("functions.php");
if (!$connect) {
die("Connection failed: " . mysqli_connect_error());
}
if(isset($_SESSION['name'])){
header("location: admin.php");
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($_POST['username']==""||$_POST['password']==""){
header ("location: login.php");
}
$username = mysqli_real_escape_string($connect,$_POST['username']);
$password = $_POST['password'];
$found_admin = attempt_login($username,$password);
if($found_admin) {
$_SESSION['username'] = $found_admin['username'];
$_SESSION['name'] = $found_admin['name'];
header("location: admin.php");
}else {
$status = "Please verify your credentials";
}
}
?>
Я создал функцию в отдельном файле, может кто-нибудь здесь дать мне совет, чтобы настроить этот код
Я учу этот язык только около недели.
планирует запустить объектно-ориентированный php.
функции
function encrypt_password ($password){
$hash_form = "$2y$10$";
$salt_length = 22;
$salt = generate_salt($salt_length);
$form_and_salt = $hash_form . $salt;
$hash = crypt($password,$form_and_salt);
return $hash;
}
function generate_salt ($length){
$unique_random_string = md5(uniqid(mt_rand(),true));
$base64_string = base64_encode($unique_random_string);
$modified_base64_string = str_replace('+', '.',$base64_string);
$salt = substr($modified_base64_string,0,$length);
return $salt;
}
function password_check ($password, $existing_hash){
$hash = crypt($password,$existing_hash);
if($hash===$existing_hash){
return true;
}else {
return false;
}
}
function find_admin_by_username($username){
global $connect;
$safe_username = mysqli_real_escape_string($connect,$username);
$query = "SELECT * FROM admins WHERE username='{$safe_username}' LIMIT 1";
$result = mysqli_query($connect , $query);
if($admin = mysqli_fetch_assoc($result)){
return $admin;
}else{
return null;
}
}
function attempt_login($username, $password){
$admin = find_admin_by_username($username);
if ($admin){
if(password_check($password,$admin['password'])){
return $admin;
}else {
return false;
}
}else {
return false;
}
}
пожалуйста помоги !
этот метод шифрования считается безопасным?
Bcrypt в порядке, но ваша реализация опасна.
Если вы не узнаете ничего из этого ответа, пожалуйста, помните, что вы не шифруете пароли, вы их хешируете. Связанная статья объясняет нюансы, касающиеся различных терминов и понятий криптографии. Если ничего другого, это должно помочь научиться задавать лучшие вопросы если вы столкнетесь с криптографией в других областях.
Если вам нужно хранить пароли, используйте password_hash()
а также password_verify()
. Не пишите свои собственные функции криптографии, если вы не знаете, что делаете.
WordPress уже должен включать password_compat (что позволяет использовать рекомендуемые функции в PHP 5.3.7+), но по состоянию на август 2015 г. вы уже должны быть в PHP 5.5, так что это спорный вопрос.
Если вы используете более старую версию PHP, сразу же заставьте ваш веб-хостинг обновиться до 5.5 или 5.6. Вы сделаете Интернет более безопасным местом, если вы это сделаете.
С рекомендованными функциями (и заменой mysqli_real_escape_string()
с подготовленными заявлениями, которые являются правильное и эффективное решение для SQL-инъекций), ваш код может выглядеть примерно так:
function find_admin_by_username($username)
{
global $connect;
// Create a prepared statement with our query structure
$stmt = mysqli_prepare($connect, "SELECT * FROM admins WHERE username = ? LIMIT 1");
// Bind a string parameter (hence the "s"):
mysqli_stmt_bind_param($stmt, "s", $username);
// If the query was successful
if (mysqli_stmt_execute($stmt)) {
// Grab the result from the prepared statement...
$result = mysqli_stmt_get_result($stmt);
// And then return a single row from the table
return mysqli_fetch_assoc($result);
}
}
function attempt_login($username, $password)
{
$admin = find_admin_by_username($username);
if ($admin) {
if (password_verify($password, $admin['password'])) {
return $admin;
}
}
return false;
}
Я собираюсь пойти дальше и аннотировать (мои комментарии с префиксом ##
) ваш код.
function encrypt_password ($password){ ## You're hashing, not encrypting
$hash_form = "$2y$10$"; ## Why is the cost of 10 hard-coded? Some people might want 11 or 12.
$salt_length = 22; ## This doesn't need to be a variable
$salt = generate_salt($salt_length);
$form_and_salt = $hash_form . $salt; ## This is backwards
$hash = crypt($password,$form_and_salt);
return $hash;
}
function generate_salt ($length){
$unique_random_string = md5(uniqid(mt_rand(),true)); ## This is weak. See footnote
$base64_string = base64_encode($unique_random_string);
$modified_base64_string = str_replace('+', '.',$base64_string);
$salt = substr($modified_base64_string,0,$length);
return $salt;
}
function password_check ($password, $existing_hash){
$hash = crypt($password,$existing_hash);
if($hash===$existing_hash){ ## Timing side-channel (albeit not a practical one)
return true;
}else {
return false;
}
}
function find_admin_by_username($username){
global $connect;
## Editing and concatenating strings fails more often than prepared statements.
## If you want to be conservative about security, get very familiar with
## mysqli_prepare() and friends. You can almost never have to use
## mysqli_real_escape_string() again if you're careful enough.
$safe_username = mysqli_real_escape_string($connect,$username);
$query = "SELECT * FROM admins WHERE username='{$safe_username}' LIMIT 1";
$result = mysqli_query($connect , $query);
if($admin = mysqli_fetch_assoc($result)){
return $admin;
}else{ ## You can just leave this outside the if block
return null; ## If you don't return anything, null is returned
}
}
function attempt_login($username, $password){
$admin = find_admin_by_username($username);
if ($admin){
if(password_check($password,$admin['password'])){
return $admin;
}else { ## unnecessary
return false; ## unnecessary
}
}else { ## unnecessary
return false; ## unnecessary
}
}
md5(uniqid(mt_rand(), true));
Это слабый генератор случайных чисел и никогда не должен использоваться для чего-либо, связанного с криптографией.
Я использовал слабые генераторы случайных чисел для создания библиотеки аутентификации пользователя в бэкдуере в своей победившей записи для Конкурс закулисного крипто на DEFCON 23. Суть в том, что если вы генерирование случайной строки в пределах ста миль от любой криптографической утилиты вам понадобится CSPRNG.
Пожалуйста, скажите мне, кто или что ввел вас в заблуждение md5(uniqid(mt_rand(), true));
это безопасный генератор случайных чисел. Я видел, как многие люди совершают одну и ту же ошибку, и я хотел бы остановить распространение плохих советов по криптографии. Это учебник где-то? Я бы очень хотел это исправить.
Повторить: md5(uniqid(mt_rand(), true));
не безопасно. Не используйте это.
WpPasswordHash.php
<?php
#
# Portable PHP password hashing framework.
#
# Version 0.3 / genuine.
#
# Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
# the public domain. Revised in subsequent years, still public domain.
#
# There's absolutely no warranty.
#
# The homepage URL for this framework is:
#
# http://www.openwall.com/phpass/
#
# Please be sure to update the Version line if you edit this file in any way.
# It is suggested that you leave the main version number intact, but indicate
# your project name (after the slash) and add your own revision information.
#
# Please do not change the "private" password hashing method implemented in
# here, thereby making your hashes incompatible. However, if you must, please
# change the hash type identifier (the "$P$") to something different.
#
# Obviously, since this code is in the public domain, the above are not
# requirements (there can be none), but merely suggestions.
#
class WpPasswordHash {
var $itoa64;
var $iteration_count_log2;
var $portable_hashes;
var $random_state;
function WpPasswordHash($iteration_count_log2, $portable_hashes)
{
$this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31)
$iteration_count_log2 = 8;
$this->iteration_count_log2 = $iteration_count_log2;
$this->portable_hashes = $portable_hashes;
$random_state = microtime() . getmypid();
}
function get_random_bytes($count)
{
$output = '';
if (($fh = @fopen('/dev/urandom', 'rb'))) {
$output = fread($fh, $count);
fclose($fh);
}
if (strlen($output) < $count) {
$output = '';
for ($i = 0; $i < $count; $i += 16) {
$this->random_state =
md5(microtime() . $this->random_state);
$output .=
pack('H*', md5($this->random_state));
}
$output = substr($output, 0, $count);
}
return $output;
}
function encode64($input, $count)
{
$output = '';
$i = 0;
do {
$value = ord($input[$i++]);
$output .= $this->itoa64[$value & 0x3f];
if ($i < $count)
$value |= ord($input[$i]) << 8;
$output .= $this->itoa64[($value >> 6) & 0x3f];
if ($i++ >= $count)
break;
if ($i < $count)
$value |= ord($input[$i]) << 16;
$output .= $this->itoa64[($value >> 12) & 0x3f];
if ($i++ >= $count)
break;
$output .= $this->itoa64[($value >> 18) & 0x3f];
} while ($i < $count);
return $output;
}
function gensalt_private($input)
{
$output = '$P$';
$output .= $this->itoa64[min($this->iteration_count_log2 +
((PHP_VERSION >= '5') ? 5 : 3), 30)];
$output .= $this->encode64($input, 6);
return $output;
}
function crypt_private($password, $setting)
{
$output = '*0';
if (substr($setting, 0, 2) == $output)
$output = '*1';
if (substr($setting, 0, 3) != '$P$')
return $output;
$count_log2 = strpos($this->itoa64, $setting[3]);
if ($count_log2 < 7 || $count_log2 > 30)
return $output;
$count = 1 << $count_log2;
$salt = substr($setting, 4, 8);
if (strlen($salt) != 8)
return $output;
# We're kind of forced to use MD5 here since it's the only
# cryptographic primitive available in all versions of PHP
# currently in use. To implement our own low-level crypto
# in PHP would result in much worse performance and
# consequently in lower iteration counts and hashes that are
# quicker to crack (by non-PHP code).
if (PHP_VERSION >= '5') {
$hash = md5($salt . $password, TRUE);
do {
$hash = md5($hash . $password, TRUE);
} while (--$count);
} else {
$hash = pack('H*', md5($salt . $password));
do {
$hash = pack('H*', md5($hash . $password));
} while (--$count);
}
$output = substr($setting, 0, 12);
$output .= $this->encode64($hash, 16);
return $output;
}
function gensalt_extended($input)
{
$count_log2 = min($this->iteration_count_log2 + 8, 24);
# This should be odd to not reveal weak DES keys, and the
# maximum valid value is (2**24 - 1) which is odd anyway.
$count = (1 << $count_log2) - 1;
$output = '_';
$output .= $this->itoa64[$count & 0x3f];
$output .= $this->itoa64[($count >> 6) & 0x3f];
$output .= $this->itoa64[($count >> 12) & 0x3f];
$output .= $this->itoa64[($count >> 18) & 0x3f];
$output .= $this->encode64($input, 3);
return $output;
}
function gensalt_blowfish($input)
{
# This one needs to use a different order of characters and a
# different encoding scheme from the one in encode64() above.
# We care because the last character in our encoded string will
# only represent 2 bits. While two known implementations of
# bcrypt will happily accept and correct a salt string which
# has the 4 unused bits set to non-zero, we do not want to take
# chances and we also do not want to waste an additional byte
# of entropy.
$itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$output = '$2a$';
$output .= chr(ord('0') + $this->iteration_count_log2 / 10);
$output .= chr(ord('0') + $this->iteration_count_log2 % 10);
$output .= '$';
$i = 0;
do {
$c1 = ord($input[$i++]);
$output .= $itoa64[$c1 >> 2];
$c1 = ($c1 & 0x03) << 4;
if ($i >= 16) {
$output .= $itoa64[$c1];
break;
}
$c2 = ord($input[$i++]);
$c1 |= $c2 >> 4;
$output .= $itoa64[$c1];
$c1 = ($c2 & 0x0f) << 2;
$c2 = ord($input[$i++]);
$c1 |= $c2 >> 6;
$output .= $itoa64[$c1];
$output .= $itoa64[$c2 & 0x3f];
} while (1);
return $output;
}
function HashPassword($password)
{
$random = '';
if (CRYPT_BLOWFISH == 1 && !$this->portable_hashes) {
$random = $this->get_random_bytes(16);
$hash =
crypt($password, $this->gensalt_blowfish($random));
if (strlen($hash) == 60)
return $hash;
}
if (CRYPT_EXT_DES == 1 && !$this->portable_hashes) {
if (strlen($random) < 3)
$random = $this->get_random_bytes(3);
$hash =
crypt($password, $this->gensalt_extended($random));
if (strlen($hash) == 20)
return $hash;
}
if (strlen($random) < 6)
$random = $this->get_random_bytes(6);
$hash =
$this->crypt_private($password,
$this->gensalt_private($random));
if (strlen($hash) == 34)
return $hash;
# Returning '*' on error is safe here, but would _not_ be safe
# in a crypt(3)-like function used _both_ for generating new
# hashes and for validating passwords against existing hashes.
return '*';
}
function CheckPassword($password, $stored_hash)
{
$hash = $this->crypt_private($password, $stored_hash);
if ($hash[0] == '*')
$hash = crypt($password, $stored_hash);
return $hash == $stored_hash;
}
}
?>
Затем, когда вы хотите подтвердить пароль:
Отдельный файл php:
$res = $this->_checkPassword($password, $res['User']['password']);
private function _checkPassword($password, $hash) {
$wp_hasher = new WpPasswordHash(8, true);
$hashed_password = $wp_hasher->CheckPassword($password, $hash);
return $hashed_password;
}
Для шифрования:
private function _encryptPwd($password) {
$wp_hasher = new WpPasswordHash(8, true);
$hashed_password = $wp_hasher->HashPassword($password);
return $hashed_password;
}
Я надеюсь, что вы понимаете логику моего кода.