crypt — Функция проверки Unix паролей

Исходный код: Lib/crypt.py


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

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

Availability: Unix. Недоступно на VxWorks.

Методы хеширования

Добавлено в версии 3.3.

Модуль crypt определяет список методов хэширования (не все методы доступны на всех платформах):

crypt.METHOD_SHA512

Модульный формат метода Crypt с 16 символами соли и 86 символьного хэша на основе хеш- функции SHA-512. Это самый стойкий метод.

crypt.METHOD_SHA256

Другой модульный формат метода Crypt с 16 символами соли и 43 символами хэша на основе функции хэширования SHA-256.

crypt.METHOD_BLOWFISH

Другой модульный формат Crypt метода с 22 символами соли и 31 символом хеша на основе шифра Blowfish.

Добавлено в версии 3.7.

crypt.METHOD_MD5

Другой модульный формат метода Crypt с 8 символами соли и 22 симолами хэша на основе хэш функции MD5.

crypt.METHOD_CRYPT

Традиционный метод с 2 символами соли и 13 символами хеша. Это самый слабый метод.

Атрибуты модуля

Добавлено в версии 3.3.

crypt.methods

Список доступных алгоритмов хеширования пароля в объекте crypt.METHOD_*. Этот список отсортирован от самых сильных до самых слабых.

Функции модуля

Модуль crypt определяет следующие функции:

crypt.crypt(word, salt=None)

word обычно будет паролем пользователя, как напечатан в приглашении или в графическом интерфейсе. Дополнительный salt - любой строка, как возвращённая из mksalt(), одного из crypt.METHOD_* значения (хотя не все могут быть доступными на всех платформах) или полный зашифрованный пароль включая соль, как возвращено этой функцией. Если salt не будет предоставлен, то будет использован самый сильный метод (возвращаемый methods()).

Проверка пароля обычно делается, передавая пароль обычного текста как слова и полные результаты предыдущего вызовы crypt(), которое должно совпасть с результатами этого вызова.

salt (случайная строка из 2 или 16 символов, возможно, с префиксом $digit$ для указания метода), которая будет использоваться для перемешивания алгоритма шифрования. Символы в salt должны быть в наборе [./a-zA-Z0-9], за исключением формата Modular Crypt Format, который содержит префиксы $digit$.

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

Поскольку несколько расширений crypt(3) допускают различные значения с различными размерами salt, рекомендуется использовать полностью зашифрованный пароль в качестве соли при проверке пароля.

Изменено в версии 3.3: crypt.METHOD_* принимает значения в дополнение к строкам для salt.

crypt.mksalt(method=None, *, rounds=None)

Возвращает произвольно сгенерированную соль указанного метода. Если method не задан, то будет использован самый сильный из доступных методов, возвращенный methods().

Возвращаемое значение является подходящей строкой для передачи в crypt() как аргумент salt.

rounds определяет количество округлений для METHOD_SHA256, METHOD_SHA512 и METHOD_BLOWFISH. Для METHOD_SHA256 и METHOD_SHA512 оно должно быть целым числом от 1000 до 999_999_999, по умолчанию - 5000. Для METHOD_BLOWFISH это должна быть степенью двух между 16 (2:sup:4) и 2_147_483_648 (2:sup:31), по умолчанию - 4096 (2:sup:12).

Добавлено в версии 3.3.

Изменено в версии 3.7: Добавлен параметр rounds.

Примеры

Простой пример, иллюстрирующий типичное использование (операция сравнения с постоянным временем необходима для ограничения подверженности атакам тайминга. hmac.compare_digest() подходит для этой цели):

import pwd
import crypt
import getpass
from hmac import compare_digest as compare_hash

def login():
    username = input('Python login: ')
    cryptedpasswd = pwd.getpwnam(username)[1]
    if cryptedpasswd:
        if cryptedpasswd == 'x' or cryptedpasswd == '*':
            raise ValueError('no support for shadow passwords')
        cleartext = getpass.getpass()
        return compare_hash(crypt.crypt(cleartext, cryptedpasswd), cryptedpasswd)
    else:
        return True

Создание хэша пароля с использованием самых сильных из доступных методов и сверить его с исходным:

import crypt
from hmac import compare_digest as compare_hash

hashed = crypt.crypt(plaintext)
if not compare_hash(hashed, crypt.crypt(plaintext, hashed)):
    raise ValueError("hashed version doesn't validate against original")