> **Источник:** https://python-all.ru/3/library/secrets.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# `secrets` – Генерация защищённых случайных чисел для управления секретами

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

**Исходный код:** [Lib/secrets.py](https://python-all.ru/src/3.14/Lib/secrets.py)

---

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

В частности, `secrets` следует использовать вместо стандартного генератора псевдослучайных чисел из модуля [`random`](https://python-all.ru/3/library/random.html#module-random), который предназначен для моделирования и симуляции, а не для безопасности или криптографии.

> **См. также**
>
> [**PEP 506**](https://python-all.ru/3/library/secrets.html)

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

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

#### `class secrets.SystemRandom`

Класс для генерации случайных чисел с использованием источников наивысшего качества, предоставляемых операционной системой. См. [`random.SystemRandom`](https://python-all.ru/3/library/random.html#random.SystemRandom) для получения дополнительных сведений.

#### `secrets.choice(seq)`

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

#### `secrets.randbelow(exclusive_upper_bound)`

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

#### `secrets.randbits(k)`

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

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

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

#### `secrets.token_bytes(nbytes=None)`

Возвращает случайную строку байтов, содержащую *nbytes* байтов.

Если *nbytes* не указан или равен `None`, используется [`DEFAULT_ENTROPY`](https://python-all.ru/3/library/secrets.html#secrets.DEFAULT_ENTROPY).

```pycon
>>> token_bytes(16)
b'\xebr\x17D*t\xae\xd4\xe3S\xb6\xe2\xebP1\x8b'
```

#### `secrets.token_hex(nbytes=None)`

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

Если *nbytes* не указан или равен `None`, используется [`DEFAULT_ENTROPY`](https://python-all.ru/3/library/secrets.html#secrets.DEFAULT_ENTROPY).

```pycon
>>> token_hex(16)
'f9bf78b9a18ce6d46a0cd2b0b86df9da'
```

#### `secrets.token_urlsafe(nbytes=None)`

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

Если *nbytes* не указан или равен `None`, используется [`DEFAULT_ENTROPY`](https://python-all.ru/3/library/secrets.html#secrets.DEFAULT_ENTROPY).

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

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

Чтобы обеспечить защиту от [атак методом перебора](https://python-all.ru/3/library/secrets.html), токены должны обладать достаточной случайностью. К сожалению, то, что считается достаточным, со временем неизбежно возрастает, поскольку компьютеры становятся мощнее и способны перебирать больше вариантов за меньшее время. По состоянию на 2015 год считается, что 32 байта (256 бит) случайности достаточно для типичного варианта использования модуля `secrets`.

Для тех, кто хочет управлять длиной токенов самостоятельно, можно явно указать количество случайности, используемой для токенов, передав аргумент [`int`](https://python-all.ru/3/library/functions.html#int) различным функциям `token_*`. Этот аргумент интерпретируется как количество байтов случайности.

В противном случае, если аргумент не указан или равен `None`, функции `token_*` используют [`DEFAULT_ENTROPY`](https://python-all.ru/3/library/secrets.html#secrets.DEFAULT_ENTROPY).

#### `secrets.DEFAULT_ENTROPY`

Количество байтов случайности, используемое функциями `token_*` по умолчанию.

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

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

#### `secrets.compare_digest(a, b)`

Возвращает `True`, если строки или [байтоподобные объекты](https://python-all.ru/3/glossary.html#term-bytes-like-object) *a* и *b* равны, иначе `False`, используя «сравнение за постоянное время», чтобы снизить риск [атак по времени](https://python-all.ru/3/library/secrets.html). Подробнее см. [`hmac.compare_digest()`](https://python-all.ru/3/library/hmac.html#hmac.compare_digest).

## Рецепты и рекомендации

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

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

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

> **Примечание**
>
> Приложения не должны [**хранить пароли в восстанавливаемом формате**](https://python-all.ru/3/library/secrets.html), будь то в открытом виде или в зашифрованном. Они должны быть засолены и хешированы с использованием криптостойкой однонаправленной (необратимой) хеш-функции.

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

```python
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](https://python-all.ru/3/library/secrets.html):

```python
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, содержащий защитный токен, подходящий для приложений восстановления пароля:

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