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

15.3. secrets – Генерация безопасных случайных чисел для управления секретамиsecrets – Generate secure random numbers for managing secrets

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

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


Модуль secrets используется для генерации криптостойких случайных чисел, подходящих для управления такими данными, как пароли, аутентификация учётных записей, токены безопасности и связанные с ними секреты.

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

См. также

PEP 506

15.3.1. Случайные числаRandom numbers

Модуль secrets предоставляет доступ к самому безопасному источнику случайных данных, который есть в операционной системе.

class secrets.SystemRandom

Класс для генерации случайных чисел с использованием источников наивысшего качества, предоставляемых операционной системой. См. random.SystemRandom для получения дополнительных сведений.

secrets.choice(sequence)

Возвращает случайно выбранный элемент из непустой последовательности.

secrets.randbelow(n)

Возвращает случайное целое число в диапазоне [0, n).

secrets.randbits(k)

Возвращает целое число с k случайными битами.

15.3.2. Генерация токеновGenerating tokens

Модуль secrets предоставляет функции для генерации защищённых токенов, подходящих для таких задач, как сброс паролей, создание URL-адресов, которые сложно угадать, и аналогичных.

secrets.token_bytes([nbytes=None])

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

>>> token_bytes(16)  
b'\xebr\x17D*t\xae\xd4\xe3S\xb6\xe2\xebP1\x8b'
secrets.token_hex([nbytes=None])

Возвращает случайную текстовую строку в шестнадцатеричном формате. Строка содержит nbytes случайных байт, каждый байт преобразуется в две шестнадцатеричные цифры. Если nbytesNone или не указан, используется разумное значение по умолчанию.

>>> token_hex(16)  
'f9bf78b9a18ce6d46a0cd2b0b86df9da'
secrets.token_urlsafe([nbytes=None])

Возвращает случайную URL-безопасную текстовую строку, содержащую nbytes случайных байт. Текст кодируется в Base64, поэтому в среднем каждый байт даёт примерно 1.3 символа. Если nbytesNone или не указан, используется разумное значение по умолчанию.

>>> token_urlsafe(16)  
'Drmhze6EPcv0fN_81Bj-nA'

15.3.2.1. Сколько байтов должны использовать токены?How many bytes should tokens use?

Чтобы обеспечить защиту от атак методом перебора, токены должны обладать достаточной случайностью. К сожалению, то, что считается достаточным, со временем неизбежно возрастает, поскольку компьютеры становятся мощнее и способны перебирать больше вариантов за меньшее время. По состоянию на 2015 год считается, что 32 байта (256 бит) случайности достаточно для типичного варианта использования модуля secrets.

Для тех, кто хочет управлять длиной токенов самостоятельно, можно явно указать количество случайности, используемой для токенов, передав аргумент int различным функциям token_*. Этот аргумент интерпретируется как количество байтов случайности.

В противном случае, если аргумент не передан или равен None, функции token_* используют вместо него разумное значение по умолчанию.

Примечание

Это значение по умолчанию может измениться в любой момент, в том числе во время выпусков с исправлениями.

15.3.3. Другие функцииOther functions

secrets.compare_digest(a, b)

Возвращает True, если строки a и b равны, иначе False, таким образом, чтобы снизить риск атак по времени. См. hmac.compare_digest() для получения дополнительных сведений.

15.3.4. Рецепты и лучшие практикиRecipes and best practices

В этом разделе приведены рецепты и рекомендации по использованию secrets для обеспечения базового уровня безопасности.

Сгенерировать восьмисимвольный буквенно-цифровой пароль:

import string
alphabet = string.ascii_letters + string.digits
password = ''.join(choice(alphabet) for i in range(8))

Примечание

Приложения не должны хранить пароли в восстанавливаемом формате, будь то в открытом виде или зашифрованными. Их следует снабжать солью и хешировать с использованием криптостойкой односторонней (необратимой) хеш-функции.

Сгенерировать десятисимвольный буквенно-цифровой пароль, содержащий хотя бы одну строчную букву, хотя бы одну заглавную букву и хотя бы три цифры:

import string
alphabet = string.ascii_letters + string.digits
while True:
    password = ''.join(choice(alphabet) for i in range(10))
    if (any(c.islower() for c in password)
            and any(c.isupper() for c in password)
            and sum(c.isdigit() for c in password) >= 3):
        break

Сгенерировать кодовую фразу в стиле XKCD:

# В стандартных системах Linux используйте подходящий файл словаря.
# На других платформах может потребоваться предоставить собственный список слов.
with open('/usr/share/dict/words') as f:
    words = [word.strip() for word in f]
    password = ' '.join(choice(words) for i in range(4))

Сгенерировать труднопредсказуемый временный URL, содержащий защитный токен, подходящий для приложений восстановления пароля:

url = 'https://mydomain.com/reset=' + token_urlsafe()