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

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

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


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

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

См.также

PEP 506

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

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

class secrets.SystemRandom

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

secrets.choice(sequence)

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

secrets.randbelow(n)

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

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, если строки a и b равны, иначе False, используя «constant-time compare» для снижения риска 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()
Вернуться на верх