Модуль шифрования Python - как правильно использовать соли?

Во-первых, контекст: я пытаюсь создать инструмент командной строки (Linux), который требуется логин. Аккаунты в этом инструменте не имеют ничего общего с учетные записи системного уровня - это не касается / etc / passwd.

Я планирую хранить учетные записи пользователей в текстовом файле, используя тот же формат (примерно), что и / etc / passwd.

Несмотря на то, что файлы паролей системного уровня не использовались, использование crypt казалось рекомендуется использовать, а не хранить пароли в открытый текст. (Хотя шифрование, безусловно, лучше, чем хранение паролей в открытый текст, я открыт для других способов сделать это.)

Мои знания о крипте основаны на следующем: https://docs.python.org/2/library/crypt.html

Документация, кажется, требует чего-то невозможного: «это рекомендуется использовать полный зашифрованный пароль в качестве соли при проверке для пароля ".

Хм? Если я создаю зашифрованный пароль (например, при создании пользователя запись) как я могу использовать зашифрованный пароль в качестве соли? Это еще не существует. (Я предполагаю, что вы должны использовать ту же соль для создания и проверки пароля.)

Я пробовал использовать пароль в виде обычного текста в качестве соли. Это делает работает, но есть две проблемы; одно легко преодолевается, а одно серьезное:

1) Первые две буквы пароля в виде открытого текста включены в зашифрованный пароль. Вы можете исправить это, не записывая первые два символы в файл:

user_record = '%s:%s:%s' % (user_name, crypted_pw[2:], user_type)

2) Используя пароль в виде открытого текста в качестве соли, вы, кажется, уменьшение количества энтропии в системе. Возможно я непонимание назначения соли.

Лучшая практика, которую я смог вывести, - это использовать первые два символы из имени пользователя в качестве соли. Было бы это уместно, или есть что-то, что я пропустил, что делает это плохим ходом?

Насколько я понимаю, соль такова, что она предотвращает предварительное вычисление пароля. хеши из словаря. Я мог бы использовать стандартную соль для всех пароли (например, мои инициалы "JS"), но это, похоже, не так бремя для злоумышленника, чем использование двух символов из имени пользователя каждого пользователя.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
9
0
14 648
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Вы неправильно понимаете документацию; в нем говорится, что, поскольку длина соли может варьироваться в зависимости от базовой реализации crypt (), вы должны предоставить весь зашифрованный пароль как значение соли при проверке паролей. То есть вместо того, чтобы отбирать первые два символа, чтобы они были солью, просто добавьте все это.

Ваша идея о том, что начальная соль будет основана на имени пользователя, кажется правильной.

Ответ принят как подходящий

Для использования модуля crypt:

ГЕНЕРИРУЯ зашифрованный пароль, вы предоставляете соль. С таким же успехом может быть случайным увеличение устойчивости к брутфорсу, если оно соответствует перечисленным условиям. При ПРОВЕРКЕ пароля вы должны предоставить значение из getpwname, если вы работаете в системе, которая поддерживает большие размеры соли и не генерирует ее самостоятельно.

Общие комментарии:

Если это не имеет ничего общего с фактическим входом в систему, ничто не мешает вам использовать более сильный метод, чем crypt. Вы можете случайным образом сгенерировать N символов соли для каждого пользователя, которые будут объединены с паролем пользователя в хэше SHA-1.

string_to_hash = user.stored_salt + entered_password
successful_login = (sha1(string_to_hash) == user.stored_password_hash)

ОБНОВЛЕНИЕ: хотя это гораздо более безопасно для радужных таблиц, вышеупомянутый метод все еще имеет криптографические недостатки. Правильное применение алгоритма HMAC может еще больше повысить вашу безопасность, но это выходит за рамки моей компетенции.

предпочитайте PBKDF2 для сохранения паролей: примените соль с HMAC и повторите

orip 01.12.2008 22:10

Вот несколько общих советов по использованию паролей:

  1. Как правило, соли используются, чтобы сделать столы ранбоу слишком дорогостоящим для вычисления. Итак, вы должны добавить немного рандомизированной соли ко всем вашим хешам паролей и просто сохранить их в виде открытого текста рядом с хешированным значением пароля.
  2. Используйте HMAC - это хороший стандарт, и он более безопасен, чем объединение пароля и соли.
  3. Используйте SHA1: MD5 не работает. Если бы вы знали это, не обижайтесь, просто будьте внимательны. ;)

У не стал бы соль является функцией пароля. Злоумышленник должен будет создать радужную таблицу для мгновенного поиска паролей в базе данных, но сделать это нужно будет только один раз. Если вы выберете случайное 32-битное целое число, им придется сгенерировать 2 ^ 32 таблицы, что (в отличие от детерминированной соли) стоит слишком много памяти (и времени).

Crypt () Python - это оболочка для системной функции crypt (). На странице руководства Linux crypt ():

char *crypt(const char *key, const char *salt);

key is a user’s typed password.
salt is a two-character string chosen from the set [a–zA–Z0–9./]. 
This string is used to perturb the algorithm in one of 4096 
different ways.

Особое внимание уделяется «строке двухсимвольный». Теперь, если вы посмотрите на поведение crypt () в Python:

>>> crypt.crypt("Hello", "World")
'Wo5pEi/H5/mxU'
>>> crypt.crypt("Hello", "ABCDE")
'AB/uOsC7P93EI'

вы обнаруживаете, что первые два символа результата всегда совпадают с первыми двумя символами исходной соли, которые действительно образуют саму истинную двухсимвольную соль. То есть результат crypt () имеет вид 2char-salt + encrypted-pass. Следовательно, нет никакой разницы в результате, если вместо передачи двухсимвольной соли или исходной многосимвольной соли вы передадите весь зашифрованный пароль.

Примечание: набор [a–zA–Z0–9./] содержит 64 символа, а 64 * 64 = 4096. Вот как символы два соотносятся с «4096 по-разному».

Пароль или что-либо, полученное на его основе, никогда не следует использовать в качестве соли. Соль для конкретного пароля должна быть непредсказуемой.

Имя пользователя или его часть допустимы, но еще лучше были бы случайные байты из криптографического ГСЧ.

Для некоторой дополнительной силы вы можете заставить модуль crypt использовать md5, используя соль в формате.

$1$ABCDEFGH$

где ABCDEFGH - строка соли.

>>> p = crypt.crypt('password', '$1$s8Ty3/f$')
>>> p
Out: '$1$s8Ty3/f$0H/M0JswK9pl3X/e.n55G1'
>>> p == crypt.crypt('password', p)
Out: True

(обратите внимание, что это расширение crypt от GNU, см. "man crypt" в системе Linux). MD5 (а теперь даже SHA1) может быть «сломан», но они все еще относительно хороши для хэшей паролей, а md5 по-прежнему является стандартом для локальных паролей Linux.

Обратите внимание, что если ваша система позволяет это, вы даже можете: crypt.crypt("some_password","$5$some_salt") или crypt.crypt("some_password","$6$some_salt"), чтобы использовать sha-256 или sha-512, если вы не доверяете MD5. Также обратите внимание, что crypt использует несколько раундов DES / MD5 / SHA *, чтобы сделать его более безопасным, чем просто использование одного раунда. Таким образом, нарушение MD5 автоматически не означает, что крипта с $ 1 $ взломана.

M.D. 08.06.2012 04:39

Используйте PBKDF2, см. этот комментарий в другом потоке (включая реализацию Python).

Взгляните на статью Бьорна Эдстрема TrueCrypt объяснил. Он содержит легкое для понимания объяснение того, как работает truecrypt, и простую реализацию Python некоторых функций truecrypt включая управление паролями.

He's talking about the Python crypt() module, not about TrueCrypt in Python

crypt.crypt() по умолчанию в Python 2 не очень безопасен, и статья объясняет, как могут работать более безопасные альтернативы.

Он говорит о модуле Python crypt (), а не о TrueCrypt в Python.

Kitchi 26.01.2014 13:48

Другие вопросы по теме