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

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


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

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

См.также

PEP 506

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

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

class secrets.SystemRandom

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

secrets.choice(sequence)

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

secrets.randbelow(n)

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

secrets.randbits(k)

Возвращает целое число со случайными 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'

Сколько байтов должны использовать токены

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

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

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

Примечание

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

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

secrets.compare_digest(a, b)

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

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

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

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

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

Примечание

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

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

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:

import secrets
# В стандартных системах Linux используйте удобный словарный файл.
# Другим платформам может потребоваться предоставить собственный список слов.
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://digitology.tech/reset=' + secrets.token_urlsafe()