Хранение пользователя и пароля в базе данных
Я создаю программное обеспечение с паролем пользователя+. После авторизации пользователь может получить доступ к некоторым полуобщинным службам, а также зашифровать некоторые файлы, к которым может обратиться только пользователь.
Пользователь должен быть сохранен как есть, без изменений, если это возможно. После авторизации пользователь и пароль хранятся в памяти до тех пор, пока программа работает (я тоже не знаю, хорошо ли это).
Вопрос в том, как сохранить эту комбинацию пользователя + пароль в потенциально незащищенной базе данных?
Я действительно не понимаю, что я должен раскрывать.
Скажем, я создаю расширенный ключ следующим образом:
salt = random 32 characters string (is it okay?)
key = hash(usr password + salt)
for 1 to 65000 do
key = hash(key + usr password + salt)
Должен ли я хранить [пользователь открытого текста], [расширенный ключ] и [соль] в базе данных?
Кроме того, что я должен использовать для шифрования (с AES или Blowfish) некоторых файлов с использованием нового пароля каждый раз?
Должен ли я генерировать новую соль и создавать новый расширенный ключ (пароль, сохраненный в памяти программы + соль)?
И в этом случае, если я храню зашифрованный файл в базе данных, возможно, я должен хранить соль.
База данных такая же, как и где я храню комбинацию пользователя + пароль.
Файл может быть дешифрован, только если кто-то может сгенерировать ключ, но он не знает пароль. Правильно?
Я использую Python с PyCrypto, но это не очень важно, общий пример просто замечательный.
Я прочитал несколько подобных вопросов, но они не очень явные.
Огромное спасибо!
Ответы
Ответ 1
Crypto трудно понять, хорошо, что вы задаете вопросы.
Хранение паролей:. Пароли должны быть хэшированы с использованием алгоритма растяжения ключа. Как правило, вы хотите использовать библиотеку, а не реализовывать ее самостоятельно. Ключевые алгоритмы растяжения предназначены для пережевывания процессорных циклов, поэтому приятно оценивать их с помощью хорошего кода C. Если вы находитесь в системе Linux с glibc
, вы можете использовать модуль crypt.crypt
(читайте man crypt
):
import crypt
encrypted = crypt.crypt(password, '$6$' + salt + '$')
Это возвращает строку ASCII, которую вы можете безопасно хранить в своей базе данных. ($6$
- расширение glibc, которое использует функцию растяжения ключа на основе SHA-512. Если у вас нет этого расширения, не используйте crypt.crypt
). (Редактирование: алгоритм очень похож на тот, который вы задавали в своем вопросе. Однако наилучшей практикой обычно является то, что библиотека может делать это, а не сворачивать ваши собственные.)
Шифрование файлов: Не делайте этого самостоятельно. Установите GnuPG (или scrypt, bcrypt, ncrypt, что у вас есть). Есть несколько вещей, которые могут легко ошибиться при разработке собственного способа шифрования файлов. Эти инструменты используют надлежащие функции деривации ключей, хэши аутентификации и режимы шифрования без какой-либо дополнительной настройки. Это не библиотеки Python, а исполняемые файлы, поэтому вам придется написать оболочку, которая использует модуль subprocess
.
Пароли в памяти: Нет. После того, как вы проверили пароль пользователя в базе данных паролей, конвертируйте пароль в ключ с помощью функции деривации ключа. Затем вы можете использовать ключ для разблокировки зашифрованных файлов, но вы больше не можете использовать его для возврата исходного пароля.
Ответ 2
Если для каждого пользователя используется другая соль, вы должны хранить его где-нибудь (в идеале в другом месте). Если вы используете одну соль для каждого пользователя, вы можете жестко установить ее в своем приложении, но ее можно считать менее безопасной.
Если вы не храните соль, вы не сможете сопоставить данный пароль с тем, который находится в вашей базе данных.
Цель соли состоит в том, чтобы сделать грубую силу или диктаторские атаки намного сложнее. Вот почему он более безопасен, если хранить отдельно, чтобы избежать того, у кого есть как хэш-пароли, так и соответствующие соли.