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