Добавить password_hash() в php с базой данных txt flatfile

Я пытаюсь понять, как работает функция password_hash().

У меня есть этот ультра-упрощенный php-логин (совершенно небезопасный, просто предназначенный для изучения) с четырьмя выбранными мной паролями.

<?php

$data = file_get_contents('pass.txt');

if($_POST['pass']) {
    $line = explode("\n", $data);
    for($i = 0; $i<count($line); $i++) {
        $item = explode("#", $line[$i]);
        if($_POST['pass'] == $item[0]) {
            echo "Welcome! You're logged in!";
        }
    }
}

else { echo '<form method="POST" action="">
            <input type="password" name="pass">
            <input type="submit">
            <form>';
}

?>

и этот pass.txt, где хранятся пароли (база данных .txt flatfile):

passone
passtwo
passthree
passfour

Можно ли добавить функцию password_hash() в мой код?

Я предполагаю, что php должен иметь возможность перезаписывать базу данных для этой цели, так как эта функция перезаписывает пароли каждый раз, когда вы входите в систему.

Спасибо, ребята ХХХ


person Kathlyn    schedule 17.09.2015    source источник
comment
В чем конкретно вы сомневаетесь? Если вы хешируете пароли, вы будете хранить такие вещи, как $2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a вместо пароля. Вот и все, примерно.   -  person Álvaro González    schedule 17.09.2015
comment
Да, но разве не предполагается менять каждый логин? Должен ли php переписать текстовый файл? Я не знаю, как это написать :'(   -  person Kathlyn    schedule 17.09.2015
comment
используйте предсказуемую соль, например, имя пользователя или что-то в этом роде. Тогда хеш будет последовательным, что позволит вам сравнить.   -  person DevDonkey    schedule 17.09.2015
comment
@DevDonkey НЕТ! Нет нет нет. Соли должны быть случайными. password_hash создает случайную соль. Не ниспровергайте это, в нем отсутствует соль. Вам просто нужно использовать password_verify вместо ==.   -  person deceze♦    schedule 17.09.2015
comment
@deceze ааа, я не знал, что такая магия существует! прохладно :)   -  person DevDonkey    schedule 17.09.2015


Ответы (2)


да.

о, и вы должны использовать isset, иначе вы можете получить ошибки PHP. и вы должны сломаться; после нахождения правильного пароля остальное - просто пустая трата процессора.

сначала для создания вашего pass.txt:

<?php
$passes=array(
'passone','passtwo','passthree'
);
foreach($passes as &$pass){
$pass=password_hash($pass,PASSWORD_DEFAULT);
}
file_put_contents("pass.txt",implode("\n",$passes));

тогда делай лайк

<?php

$data = file_get_contents('pass.txt');

if(array_key_exists('pass',$_POST)){
    $lines = explode("\n", $data);
    for($i = 0; $i<count($lines); $i++) {
        if(password_verify($_POST['pass'],$lines[$i])) {
            echo "Welcome! You're logged in!";
            break;
        }
    }
}

else { echo '<form method="POST" action="">
            <input type="password" name="pass">
            <input type="submit">
            <form>';
}
  • слово предупреждения, хотя. лично мне не нравится password_hash, потому что его нелегко интегрировать с приложениями, написанными на других языках (в моем случае на c++), структура хэша четко не определена (насколько я знаю), за исключением чтения исходного кода интерпретатора php. код..
person hanshenrik    schedule 17.09.2015
comment
Выглядит действительно хорошо, но следует ли тогда записывать пароли в файл php? (строка 3 вашего верхнего кода) - person Kathlyn; 17.09.2015
comment
откуда вы берете пароли, зависит от вас. возьмите их из текстового файла, из базы данных, из чего угодно. здесь я просто жестко закодировал их в файле php, да. вперед, используйте $passes=file(unencrypted_passwords.txt,FILE_IGNORE_NEW_LINES); ^^ - person hanshenrik; 17.09.2015
comment
Я пробую ваш код. Это здорово. Все ли правильно в коде, который создает пароли? Он записывает НЕЗАШИФРОВАННЫЕ пароли в базу данных. Разве он не должен писать хеш-коды и переписывать их снова и снова? - person Kathlyn; 17.09.2015
comment
wups, я нашел опечатку в коде, foreach($passess as &$pass) должен был быть foreach($passes as &$pass).. но пароли должны быть зашифрованы/хешированы в базе данных, да.. и я сам попробовал код, все хешируется в pass.txt, паролей в открытом виде нет.. - person hanshenrik; 17.09.2015
comment
Я поставлю вам галочку, это действительно отличное решение. В любом случае, должен быть способ избавиться от простых паролей в php, как только они будут записаны в базу данных. не так ли? - person Kathlyn; 17.09.2015
comment
@Kathlyn В этом и заключается смысл хэширования паролей, вы не хотите хранить настоящие пароли в открытом виде. Так что просто хэшируйте их один раз, и как только у вас будет текстовый файл, полный хешированных паролей, удалите оригиналы. - person deceze♦; 17.09.2015
comment
@deceze Если я удалю открытый текст, код не будет работать или, по крайней мере, перестанет перезаписывать пароли в базе данных. Ты знаешь, что я имею в виду? - person Kathlyn; 17.09.2015
comment
@hanshenrik, если я сгенерирую файл для хранения незашифрованных паролей ... разве это не небезопасно и не разрушит всю безопасность password_hash ()? - person Kathlyn; 17.09.2015
comment
@Kathlyn Опять же, вы не должны хешировать пароль каждый раз. Это разовая операция! Хешируйте пароль, сохраните хэш, выбросьте оригинал. Зачем вообще хешировать пароли? Потому что вы не хотите знать или хранить фактический пароль! - person deceze♦; 17.09.2015
comment
@deceze Хотя вы мастер в php по сравнению со мной, я думаю, что вы ошибаетесь в этом случае: зашифрованный пароль в базе данных автоматически меняется с течением времени (и продолжает кодировать один и тот же открытый текст). Зашифрованный пароль меняется, потому что эта функция раз за разом меняет алгоритм, и поэтому она так безопасна. Попробуйте приведенный выше код, и вы увидите... Если я сделаю по-вашему, он будет работать, но алгоритм останется тем же навсегда, и он не будет таким безопасным. - person Kathlyn; 17.09.2015
comment
@Kathlyn К сожалению, у вас неправильное понимание того, как работает хэширование паролей и для чего оно нужно. Вы хешируете пароли, потому что не хотите хранить пароли в виде открытого текста, но вам все равно нужен способ проверить заданный пароль. Хеширование пароля безопасно, потому что хэш — это односторонняя функция! Это небезопасно, потому что постоянно меняется, это безопасно, потому что вы не можете преобразовать хэш в открытый текст. Вам не нужно постоянно менять хэши, чтобы обеспечить безопасность. Чтобы постоянно менять хэши, вам нужно хранить открытый текстовый пароль. [продолжение] - person deceze♦; 17.09.2015
comment
@Kathlyn ... Хранение пароля в виде открытого текста, очевидно, в первую очередь сводит на нет использование хэширования пароля (вы не хотите хранить пароль в виде открытого текста). Как я уже сказал, я знаю, что знаю, о чем говорю: вы хэшируете пароль один раз, вы сохраняете только хэш (который не нужно менять), вы используете password_verify для проверки пароля по хешу. , период. - person deceze♦; 17.09.2015
comment
То есть вы имеете в виду, что password_hash — это то же самое, что и md5 или sha? Но с другим языком? - person Kathlyn; 17.09.2015
comment
Согласны ли вы со мной, что если вы используете приведенный выше код, код в базе данных будет постоянно меняться с различными шифровками паролей? - person Kathlyn; 17.09.2015
comment
@Kathlyn По сути, да, это та же идея, что и MD5 (хотя он использует более сильный алгоритм, чем MD5), но password_hash также добавляет случайную соль, которая необходима для предотвращения использования радужных таблиц (смотрите что вверх). Случайные соли необходимы для предотвращения методов, которые могут привести к обращению хэша (опять же, взгляните на взлом хэша методом грубой силы и радужные таблицы). - person deceze♦; 17.09.2015
comment
@Kathlyn Да, приведенный выше код каждый раз повторно хэширует пароли в какой-то другой хэш. И опять же, для этого вам нужно хранить пароли в открытом виде. И опять же, это смехотворно, потому что в первую очередь отсутствует смысл хеширования и хранения только хэшей. Безопасность хеширования пароля заключается не в самом процессе хеширования, а в том факте, что вы не храните открытый текстовый пароль, следовательно, вы не знаете открытый текстовый пароль, следовательно незашифрованный пароль не может быть случайно утек, что может поставить под угрозу вашу систему. - person deceze♦; 17.09.2015
comment
Давайте продолжим обсуждение в чате. - person Kathlyn; 17.09.2015

  1. Сделайте echo password_hash('passone') для каждого из ваших паролей, сохраните полученную длинную строку тарабарщины в текстовом файле.
  2. Вместо if ($_POST['pass'] == $item[0])
    вы делаете if (password_verify($_POST['pass'], $item[0])).

То есть вы используете password_verify для пароля в виде открытого текста и хешированного пароля из текстового файла. password_hash создает случайную соль в процессе хеширования. Эта случайная соль является частью возвращаемой абракадаброй строки! Вам нужно повторно использовать эту случайную соль во время сравнения. password_verify позаботится об этом за вас.

Это все, что нужно.

person deceze♦    schedule 17.09.2015
comment
Спасибо, кажется, вы меня понимаете, но сохраненный пароль меняется каждый раз, когда вы входите в систему, и при вашем подходе он не будет этого делать, поскольку он не изменяет базу данных плоских файлов. (не знаю, понятно ли объяснила) XXX - person Kathlyn; 17.09.2015
comment
Смотрите мое обновление. Вы только один раз хешируете первоначальный пароль, после чего используете password_verify. Вам не нужно постоянно что-то менять. - person deceze♦; 17.09.2015
comment
См. stackoverflow.com/a/16736254/476 для объяснения основного механизма. - person deceze♦; 17.09.2015
comment
Спасибо за ваш интерес! Ваш ответ был абсолютно замечательным, но другой лучше всего соответствовал моим намерениям. Может я не правильно сформулировал вопрос. Я тоже проголосовал за ваш ответ, так как думаю, что он тоже может быть полезен. Еще раз спасибо ххх - person Kathlyn; 17.09.2015