secrets — Генерируйте безопасные случайные числа для управления секретами

Added in version 3.6.

Источник: Lib/secrets.py


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

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

См.также

PEP 506

Случайные числа

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

class secrets.SystemRandom

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

secrets.choice(seq)

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

secrets.randbelow(exclusive_upper_bound)

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

secrets.randbits(k)

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

Генерация токенов

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

secrets.token_bytes([nbytes=None])

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

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

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

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

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

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

Сколько байт должны занимать токены?

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

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

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

Примечание

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

Другие функции

secrets.compare_digest(a, b)

Возвращает True, если строки или bytes-like objects a и b равны, иначе False, используя «сравнение в постоянном времени» для снижения риска timing attacks. Дополнительные подробности см. в разделе hmac.compare_digest().

Рецепты и лучшие практики

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

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

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

Примечание

Приложения не должны иметь store passwords in a recoverable format, будь то открытый или зашифрованный текст. Их следует солить и хешировать с помощью криптографически сильной односторонней (необратимой) хеш-функции.

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

import string
import secrets
alphabet = string.ascii_letters + string.digits
while True:
    password = ''.join(secrets.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-style passphrase:

import secrets
# On standard Linux systems, use a convenient dictionary file.
# Other platforms may need to provide their own word-list.
with open('/usr/share/dict/words') as f:
    words = [word.strip() for word in f]
    password = ' '.join(secrets.choice(words) for i in range(4))

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

import secrets
url = 'https://example.com/reset=' + secrets.token_urlsafe()