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

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

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


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

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

35.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 символов. Это самый слабый метод.

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

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

crypt.methods

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

35.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()).

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

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

35.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")