Steven D'Aprano | b2871fa | 2016-04-17 01:42:33 +1000 | [diff] [blame] | 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 | |
| 20 | The :mod:`secrets` module is used for generating cryptographically strong |
| 21 | random numbers suitable for managing data such as passwords, account |
| 22 | authentication, security tokens, and related secrets. |
| 23 | |
| 24 | In particularly, :mod:`secrets` should be used in preference to the |
| 25 | default pseudo-random number generator in the :mod:`random` module, which |
| 26 | is designed for modelling and simulation, not security or cryptography. |
| 27 | |
| 28 | .. seealso:: |
| 29 | |
| 30 | :pep:`506` |
| 31 | |
| 32 | |
| 33 | Random numbers |
| 34 | -------------- |
| 35 | |
| 36 | The :mod:`secrets` module provides access to the most secure source of |
| 37 | randomness 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 | |
| 58 | Generating tokens |
| 59 | ----------------- |
| 60 | |
| 61 | The :mod:`secrets` module provides functions for generating secure |
| 62 | tokens, suitable for applications such as password resets, |
| 63 | hard-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 |
Steven D'Aprano | 151f5d5 | 2016-04-17 13:05:10 +1000 | [diff] [blame] | 91 | bytes. The text is Base64 encoded, so on average each byte results |
Steven D'Aprano | b2871fa | 2016-04-17 01:42:33 +1000 | [diff] [blame] | 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 | |
| 101 | How many bytes should tokens use? |
| 102 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 103 | |
| 104 | To be secure against |
| 105 | `brute-force attacks <https://en.wikipedia.org/wiki/Brute-force_attack>`_, |
| 106 | tokens need to have sufficient randomness. Unfortunately, what is |
| 107 | considered sufficient will necessarily increase as computers get more |
| 108 | powerful and able to make more guesses in a shorter period. As of 2015, |
Steven D'Aprano | 151f5d5 | 2016-04-17 13:05:10 +1000 | [diff] [blame] | 109 | it is believed that 32 bytes (256 bits) of randomness is sufficient for |
Steven D'Aprano | b2871fa | 2016-04-17 01:42:33 +1000 | [diff] [blame] | 110 | the typical use-case expected for the :mod:`secrets` module. |
| 111 | |
| 112 | For those who want to manage their own token length, you can explicitly |
| 113 | specify how much randomness is used for tokens by giving an :class:`int` |
| 114 | argument to the various ``token_*`` functions. That argument is taken |
| 115 | as the number of bytes of randomness to use. |
| 116 | |
| 117 | Otherwise, if no argument is provided, or if the argument is ``None``, |
| 118 | the ``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 | |
| 126 | Other functions |
| 127 | --------------- |
| 128 | |
| 129 | .. function:: compare_digest(a, b) |
| 130 | |
| 131 | Return ``True`` if strings *a* and *b* are equal, otherwise ``False``, |
Steven D'Aprano | 151f5d5 | 2016-04-17 13:05:10 +1000 | [diff] [blame] | 132 | in such a way as to reduce the risk of |
Sanyam Khurana | 1b4587a | 2017-12-06 22:09:33 +0530 | [diff] [blame] | 133 | `timing attacks <https://codahale.com/a-lesson-in-timing-attacks/>`_. |
Steven D'Aprano | b2871fa | 2016-04-17 01:42:33 +1000 | [diff] [blame] | 134 | See :func:`hmac.compare_digest` for additional details. |
| 135 | |
| 136 | |
| 137 | Recipes and best practices |
| 138 | -------------------------- |
| 139 | |
| 140 | This section shows recipes and best practices for using :mod:`secrets` |
| 141 | to manage a basic level of security. |
| 142 | |
| 143 | Generate an eight-character alphanumeric password: |
| 144 | |
| 145 | .. testcode:: |
| 146 | |
| 147 | import string |
Daniel Chimeno | cf8abcb | 2018-05-19 17:01:49 +0200 | [diff] [blame] | 148 | import secrets |
Steven D'Aprano | b2871fa | 2016-04-17 01:42:33 +1000 | [diff] [blame] | 149 | alphabet = string.ascii_letters + string.digits |
Daniel Chimeno | cf8abcb | 2018-05-19 17:01:49 +0200 | [diff] [blame] | 150 | password = ''.join(secrets.choice(alphabet) for i in range(8)) |
Steven D'Aprano | b2871fa | 2016-04-17 01:42:33 +1000 | [diff] [blame] | 151 | |
| 152 | |
| 153 | .. note:: |
| 154 | |
Steven D'Aprano | 151f5d5 | 2016-04-17 13:05:10 +1000 | [diff] [blame] | 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. |
Steven D'Aprano | b2871fa | 2016-04-17 01:42:33 +1000 | [diff] [blame] | 159 | |
| 160 | |
| 161 | Generate a ten-character alphanumeric password with at least one |
| 162 | lowercase character, at least one uppercase character, and at least |
| 163 | three digits: |
| 164 | |
| 165 | .. testcode:: |
| 166 | |
| 167 | import string |
Daniel Chimeno | cf8abcb | 2018-05-19 17:01:49 +0200 | [diff] [blame] | 168 | import secrets |
Steven D'Aprano | b2871fa | 2016-04-17 01:42:33 +1000 | [diff] [blame] | 169 | alphabet = string.ascii_letters + string.digits |
| 170 | while True: |
Daniel Chimeno | cf8abcb | 2018-05-19 17:01:49 +0200 | [diff] [blame] | 171 | password = ''.join(secrets.choice(alphabet) for i in range(10)) |
Steven D'Aprano | b2871fa | 2016-04-17 01:42:33 +1000 | [diff] [blame] | 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 | |
Sanyam Khurana | 1b4587a | 2017-12-06 22:09:33 +0530 | [diff] [blame] | 178 | Generate an `XKCD-style passphrase <https://xkcd.com/936/>`_: |
Steven D'Aprano | b2871fa | 2016-04-17 01:42:33 +1000 | [diff] [blame] | 179 | |
| 180 | .. testcode:: |
| 181 | |
Daniel Chimeno | cf8abcb | 2018-05-19 17:01:49 +0200 | [diff] [blame] | 182 | import secrets |
Steven D'Aprano | b2871fa | 2016-04-17 01:42:33 +1000 | [diff] [blame] | 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] |
Daniel Chimeno | cf8abcb | 2018-05-19 17:01:49 +0200 | [diff] [blame] | 187 | password = ' '.join(secrets.choice(words) for i in range(4)) |
Steven D'Aprano | b2871fa | 2016-04-17 01:42:33 +1000 | [diff] [blame] | 188 | |
| 189 | |
| 190 | Generate a hard-to-guess temporary URL containing a security token |
| 191 | suitable for password recovery applications: |
| 192 | |
| 193 | .. testcode:: |
| 194 | |
Daniel Chimeno | cf8abcb | 2018-05-19 17:01:49 +0200 | [diff] [blame] | 195 | import secrets |
| 196 | url = 'https://mydomain.com/reset=' + secrets.token_urlsafe() |
Steven D'Aprano | b2871fa | 2016-04-17 01:42:33 +1000 | [diff] [blame] | 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; |