| :mod:`!secrets` --- Generate secure random numbers for managing secrets | |
| ======================================================================= | |
| .. module:: secrets | |
| :synopsis: Generate secure random numbers for managing secrets. | |
| .. versionadded:: 3.6 | |
| .. testsetup:: | |
| from secrets import * | |
| __name__ = '<doctest>' | |
| **Source code:** :source:`Lib/secrets.py` | |
| ------------- | |
| The :mod:`!secrets` module is used for generating cryptographically strong | |
| random numbers suitable for managing data such as passwords, account | |
| authentication, security tokens, and related secrets. | |
| In particular, :mod:`!secrets` should be used in preference to the | |
| default pseudo-random number generator in the :mod:`random` module, which | |
| is designed for modelling and simulation, not security or cryptography. | |
| .. seealso:: | |
| :pep:`506` | |
| Random numbers | |
| -------------- | |
| The :mod:`!secrets` module provides access to the most secure source of | |
| randomness that your operating system provides. | |
| .. class:: SystemRandom | |
| A class for generating random numbers using the highest-quality | |
| sources provided by the operating system. See | |
| :class:`random.SystemRandom` for additional details. | |
| .. function:: choice(seq) | |
| Return a randomly chosen element from a non-empty sequence. | |
| .. function:: randbelow(exclusive_upper_bound) | |
| Return a random int in the range [0, *exclusive_upper_bound*). | |
| .. function:: randbits(k) | |
| Return a non-negative int with *k* random bits. | |
| Generating tokens | |
| ----------------- | |
| The :mod:`!secrets` module provides functions for generating secure | |
| tokens, suitable for applications such as password resets, | |
| hard-to-guess URLs, and similar. | |
| .. function:: token_bytes(nbytes=None) | |
| Return a random byte string containing *nbytes* number of bytes. | |
| If *nbytes* is not specified or ``None``, :const:`DEFAULT_ENTROPY` | |
| is used instead. | |
| .. doctest:: | |
| >>> token_bytes(16) # doctest: +SKIP | |
| b'\xebr\x17D*t\xae\xd4\xe3S\xb6\xe2\xebP1\x8b' | |
| .. function:: token_hex(nbytes=None) | |
| Return a random text string, in hexadecimal. The string has *nbytes* | |
| random bytes, each byte converted to two hex digits. | |
| If *nbytes* is not specified or ``None``, :const:`DEFAULT_ENTROPY` | |
| is used instead. | |
| .. doctest:: | |
| >>> token_hex(16) # doctest: +SKIP | |
| 'f9bf78b9a18ce6d46a0cd2b0b86df9da' | |
| .. function:: token_urlsafe(nbytes=None) | |
| Return a random URL-safe text string, containing *nbytes* random | |
| bytes. The text is Base64 encoded, so on average each byte results | |
| in approximately 1.3 characters. | |
| If *nbytes* is not specified or ``None``, :const:`DEFAULT_ENTROPY` | |
| is used instead. | |
| .. doctest:: | |
| >>> token_urlsafe(16) # doctest: +SKIP | |
| 'Drmhze6EPcv0fN_81Bj-nA' | |
| How many bytes should tokens use? | |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| To be secure against | |
| `brute-force attacks <https://en.wikipedia.org/wiki/Brute-force_attack>`_, | |
| tokens need to have sufficient randomness. Unfortunately, what is | |
| considered sufficient will necessarily increase as computers get more | |
| powerful and able to make more guesses in a shorter period. As of 2015, | |
| it is believed that 32 bytes (256 bits) of randomness is sufficient for | |
| the typical use-case expected for the :mod:`!secrets` module. | |
| For those who want to manage their own token length, you can explicitly | |
| specify how much randomness is used for tokens by giving an :class:`int` | |
| argument to the various ``token_*`` functions. That argument is taken | |
| as the number of bytes of randomness to use. | |
| Otherwise, if no argument is provided, or if the argument is ``None``, | |
| the ``token_*`` functions use :const:`DEFAULT_ENTROPY` instead. | |
| .. data:: DEFAULT_ENTROPY | |
| Default number of bytes of randomness used by the ``token_*`` functions. | |
| The exact value is subject to change at any time, including during | |
| maintenance releases. | |
| Other functions | |
| --------------- | |
| .. function:: compare_digest(a, b) | |
| Return ``True`` if strings or | |
| :term:`bytes-like objects <bytes-like object>` | |
| *a* and *b* are equal, otherwise ``False``, | |
| using a "constant-time compare" to reduce the risk of | |
| `timing attacks <https://web.archive.org/web/20250815071532/https://codahale.com/a-lesson-in-timing-attacks/>`__. | |
| See :func:`hmac.compare_digest` for additional details. | |
| Recipes and best practices | |
| -------------------------- | |
| This section shows recipes and best practices for using :mod:`!secrets` | |
| to manage a basic level of security. | |
| Generate an eight-character alphanumeric password: | |
| .. testcode:: | |
| import string | |
| import secrets | |
| alphabet = string.ascii_letters + string.digits | |
| password = ''.join(secrets.choice(alphabet) for i in range(8)) | |
| .. note:: | |
| Applications should not | |
| :cwe:`store passwords in a recoverable format <257>`, | |
| whether plain text or encrypted. They should be salted and hashed | |
| using a cryptographically strong one-way (irreversible) hash function. | |
| Generate a ten-character alphanumeric password with at least one | |
| lowercase character, at least one uppercase character, and at least | |
| three digits: | |
| .. testcode:: | |
| 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 | |
| Generate an `XKCD-style passphrase <https://xkcd.com/936/>`_: | |
| .. testcode:: | |
| 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)) | |
| Generate a hard-to-guess temporary URL containing a security token | |
| suitable for password recovery applications: | |
| .. testcode:: | |
| import secrets | |
| url = 'https://example.com/reset=' + secrets.token_urlsafe() | |
| .. | |
| # This modeline must appear within the last ten lines of the file. | |
| kate: indent-width 3; remove-trailing-space on; replace-tabs on; encoding utf-8; |