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 particularly, :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 alphabet = string.ascii_letters + string.digits 149 password = ''.join(choice(alphabet) for i in range(8)) 150 151 152.. note:: 153 154 Applications should not 155 `store passwords in a recoverable format <http://cwe.mitre.org/data/definitions/257.html>`_, 156 whether plain text or encrypted. They should be salted and hashed 157 using a cryptographically-strong one-way (irreversible) hash function. 158 159 160Generate a ten-character alphanumeric password with at least one 161lowercase character, at least one uppercase character, and at least 162three digits: 163 164.. testcode:: 165 166 import string 167 alphabet = string.ascii_letters + string.digits 168 while True: 169 password = ''.join(choice(alphabet) for i in range(10)) 170 if (any(c.islower() for c in password) 171 and any(c.isupper() for c in password) 172 and sum(c.isdigit() for c in password) >= 3): 173 break 174 175 176Generate an `XKCD-style passphrase <https://xkcd.com/936/>`_: 177 178.. testcode:: 179 180 # On standard Linux systems, use a convenient dictionary file. 181 # Other platforms may need to provide their own word-list. 182 with open('/usr/share/dict/words') as f: 183 words = [word.strip() for word in f] 184 password = ' '.join(choice(words) for i in range(4)) 185 186 187Generate a hard-to-guess temporary URL containing a security token 188suitable for password recovery applications: 189 190.. testcode:: 191 192 url = 'https://mydomain.com/reset=' + token_urlsafe() 193 194 195 196.. 197 # This modeline must appear within the last ten lines of the file. 198 kate: indent-width 3; remove-trailing-space on; replace-tabs on; encoding utf-8; 199