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 <steve+python@pearwood.info>
8.. sectionauthor:: Steven D'Aprano <steve+python@pearwood.info>
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 *a* and *b* are equal, otherwise ``False``,
132   in such a way as to reduce the risk of
133   `timing attacks <https://codahale.com/a-lesson-in-timing-attacks/>`_.
134   See :func:`hmac.compare_digest` for additional details.
135
136
137Recipes and best practices
138--------------------------
139
140This section shows recipes and best practices for using :mod:`secrets`
141to manage a basic level of security.
142
143Generate an eight-character alphanumeric password:
144
145.. testcode::
146
147   import string
148   import secrets
149   alphabet = string.ascii_letters + string.digits
150   password = ''.join(secrets.choice(alphabet) for i in range(8))
151
152
153.. note::
154
155   Applications should not
156   `store passwords in a recoverable format <http://cwe.mitre.org/data/definitions/257.html>`_,
157   whether plain text or encrypted.  They should be salted and hashed
158   using a cryptographically-strong one-way (irreversible) hash function.
159
160
161Generate a ten-character alphanumeric password with at least one
162lowercase character, at least one uppercase character, and at least
163three digits:
164
165.. testcode::
166
167   import string
168   import secrets
169   alphabet = string.ascii_letters + string.digits
170   while True:
171       password = ''.join(secrets.choice(alphabet) for i in range(10))
172       if (any(c.islower() for c in password)
173               and any(c.isupper() for c in password)
174               and sum(c.isdigit() for c in password) >= 3):
175           break
176
177
178Generate an `XKCD-style passphrase <https://xkcd.com/936/>`_:
179
180.. testcode::
181
182   import secrets
183   # On standard Linux systems, use a convenient dictionary file.
184   # Other platforms may need to provide their own word-list.
185   with open('/usr/share/dict/words') as f:
186       words = [word.strip() for word in f]
187       password = ' '.join(secrets.choice(words) for i in range(4))
188
189
190Generate a hard-to-guess temporary URL containing a security token
191suitable for password recovery applications:
192
193.. testcode::
194
195   import secrets
196   url = 'https://mydomain.com/reset=' + secrets.token_urlsafe()
197
198
199
200..
201   # This modeline must appear within the last ten lines of the file.
202   kate: indent-width 3; remove-trailing-space on; replace-tabs on; encoding utf-8;
203