Во-первых, контекст: я пытаюсь создать инструмент командной строки (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"), но это, похоже, не так бремя для злоумышленника, чем использование двух символов из имени пользователя каждого пользователя.






Вы неправильно понимаете документацию; в нем говорится, что, поскольку длина соли может варьироваться в зависимости от базовой реализации 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 может еще больше повысить вашу безопасность, но это выходит за рамки моей компетенции.
Вот несколько общих советов по использованию паролей:
У не стал бы соль является функцией пароля. Злоумышленник должен будет создать радужную таблицу для мгновенного поиска паролей в базе данных, но сделать это нужно будет только один раз. Если вы выберете случайное 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 $ взломана.
Используйте 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.
предпочитайте PBKDF2 для сохранения паролей: примените соль с HMAC и повторите