Документация Python неофициальный перевод
Содержание страницы

34.5. crypt – Функция для проверки паролей Unixcrypt – Function to check Unix passwords

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

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

34.5.1. Методы хешированияHashing Methods

Новое в версии 3.3.

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

crypt.METHOD_SHA512

Метод Modular Crypt Format с 16-символьной солью и 86-символьным хешем. Это самый надёжный метод.

crypt.METHOD_SHA256

Ещё один метод Modular Crypt Format с 16-символьной солью и 43-символьным хешем.

crypt.METHOD_MD5

Ещё один метод Modular Crypt Format с 8-символьной солью и 22-символьным хешем.

crypt.METHOD_CRYPT

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

34.5.2. Атрибуты модуляModule Attributes

Новое в версии 3.3.

crypt.methods

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

34.5.3. Функции модуляModule Functions

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

crypt.crypt(word, salt=None)

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

Обычно проверка пароля выполняется путём передачи открытого пароля в качестве word и полного результата предыдущего вызова 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)

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

Возвращается строка: для crypt.METHOD_CRYPT длиной 2 символа, или 19 символов, начиная с $digit$ и 16 случайных символов из множества [./a-zA-Z0-9]. Такая строка подходит для передачи в качестве аргумента salt в функцию crypt().

Новое в версии 3.3.

34.5.4. ПримерыExamples

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