1:mod:`secrets` --- Generate secure random numbers for managing secrets
2======================================================================
3
4.. module:: secrets
5   :synopsis: Generate secure random numbers for managing secrets.
6
7.. moduleauthor:: Steven D'Aprano <[email protected]>
8.. sectionauthor:: Steven D'Aprano <[email protected]>
9.. versionadded:: 3.6
10
11.. testsetup::
12
13   from secrets import *
14   __name__ = '<doctest>'
15
16**Source code:** :source:`Lib/secrets.py`
17
18-------------
19
20The :mod:`secrets` module is used for generating cryptographically strong
21random numbers suitable for managing data such as passwords, account
22authentication, security tokens, and related secrets.
23
24In particular, :mod:`secrets` should be used in preference to the
25default pseudo-random number generator in the :mod:`random` module, which
26is designed for modelling and simulation, not security or cryptography.
27
28.. seealso::
29
30   :pep:`506`
31
32
33Random numbers
34--------------
35
36The :mod:`secrets` module provides access to the most secure source of
37randomness that your operating system provides.
38
39.. class:: SystemRandom
40
41   A class for generating random numbers using the highest-quality
42   sources provided by the operating system.  See
43   :class:`random.SystemRandom` for additional details.
44
45.. function:: choice(sequence)
46
47   Return a randomly chosen element from a non-empty sequence.
48
49.. function:: randbelow(n)
50
51   Return a random int in the range [0, *n*).
52
53.. function:: randbits(k)
54
55   Return an int with *k* random bits.
56
57
58Generating tokens
59-----------------
60
61The :mod:`secrets` module provides functions for generating secure
62tokens, suitable for applications such as password resets,
63hard-to-guess URLs, and similar.
64
65.. function:: token_bytes([nbytes=None])
66
67   Return a random byte string containing *nbytes* number of bytes.
68   If *nbytes* is ``None`` or not supplied, a reasonable default is
69   used.
70
71   .. doctest::
72
73      >>> token_bytes(16)  #doctest:+SKIP
74      b'\xebr\x17D*t\xae\xd4\xe3S\xb6\xe2\xebP1\x8b'
75
76
77.. function:: token_hex([nbytes=None])
78
79   Return a random text string, in hexadecimal.  The string has *nbytes*
80   random bytes, each byte converted to two hex digits.  If *nbytes* is
81   ``None`` or not supplied, a reasonable default is used.
82
83   .. doctest::
84
85      >>> token_hex(16)  #doctest:+SKIP
86      'f9bf78b9a18ce6d46a0cd2b0b86df9da'
87
88.. function:: token_urlsafe([nbytes=None])
89
90   Return a random URL-safe text string, containing *nbytes* random
91   bytes.  The text is Base64 encoded, so on average each byte results
92   in approximately 1.3 characters.  If *nbytes* is ``None`` or not
93   supplied, a reasonable default is used.
94
95   .. doctest::
96
97      >>> token_urlsafe(16)  #doctest:+SKIP
98      'Drmhze6EPcv0fN_81Bj-nA'
99
100
101How many bytes should tokens use?
102^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
103
104To be secure against
105`brute-force attacks <https://en.wikipedia.org/wiki/Brute-force_attack>`_,
106tokens need to have sufficient randomness.  Unfortunately, what is
107considered sufficient will necessarily increase as computers get more
108powerful and able to make more guesses in a shorter period.  As of 2015,
109it is believed that 32 bytes (256 bits) of randomness is sufficient for
110the typical use-case expected for the :mod:`secrets` module.
111
112For those who want to manage their own token length, you can explicitly
113specify how much randomness is used for tokens by giving an :class:`int`
114argument to the various ``token_*`` functions.  That argument is taken
115as the number of bytes of randomness to use.
116
117Otherwise, if no argument is provided, or if the argument is ``None``,
118the ``token_*`` functions will use a reasonable default instead.
119
120.. note::
121
122   That default is subject to change at any time, including during
123   maintenance releases.
124
125
126Other functions
127---------------
128
129.. function:: compare_digest(a, b)
130
131   Return ``True`` if strings or
132   :term:`bytes-like objects <bytes-like object>`
133   *a* and *b* are equal, otherwise ``False``,
134   using a "constant-time compare" to reduce the risk of
135   `timing attacks <https://codahale.com/a-lesson-in-timing-attacks/>`_.
136   See :func:`hmac.compare_digest` for additional details.
137
138
139Recipes and best practices
140--------------------------
141
142This section shows recipes and best practices for using :mod:`secrets`
143to manage a basic level of security.
144
145Generate an eight-character alphanumeric password:
146
147.. testcode::
148
149   import string
150   import secrets
151   alphabet = string.ascii_letters + string.digits
152   password = ''.join(secrets.choice(alphabet) for i in range(8))
153
154
155.. note::
156
157   Applications should not
158   `store passwords in a recoverable format <https://cwe.mitre.org/data/definitions/257.html>`_,
159   whether plain text or encrypted.  They should be salted and hashed
160   using a cryptographically strong one-way (irreversible) hash function.
161
162
163Generate a ten-character alphanumeric password with at least one
164lowercase character, at least one uppercase character, and at least
165three digits:
166
167.. testcode::
168
169   import string
170   import secrets
171   alphabet = string.ascii_letters + string.digits
172   while True:
173       password = ''.join(secrets.choice(alphabet) for i in range(10))
174       if (any(c.islower() for c in password)
175               and any(c.isupper() for c in password)
176               and sum(c.isdigit() for c in password) >= 3):
177           break
178
179
180Generate an `XKCD-style passphrase <https://xkcd.com/936/>`_:
181
182.. testcode::
183
184   import secrets
185   # On standard Linux systems, use a convenient dictionary file.
186   # Other platforms may need to provide their own word-list.
187   with open('/usr/share/dict/words') as f:
188       words = [word.strip() for word in f]
189       password = ' '.join(secrets.choice(words) for i in range(4))
190
191
192Generate a hard-to-guess temporary URL containing a security token
193suitable for password recovery applications:
194
195.. testcode::
196
197   import secrets
198   url = 'https://example.com/reset=' + secrets.token_urlsafe()
199
200
201
202..
203   # This modeline must appear within the last ten lines of the file.
204   kate: indent-width 3; remove-trailing-space on; replace-tabs on; encoding utf-8;
205