diff options
author | Steven D'Aprano <steve@pearwood.info> | 2016-04-17 01:42:33 +1000 |
---|---|---|
committer | Steven D'Aprano <steve@pearwood.info> | 2016-04-17 01:42:33 +1000 |
commit | b2871faa874c5a7abd7d9f77dfeb6082253a40be (patch) | |
tree | f34a627bdb986d652686ec516ba14ec38c8d95f7 /Doc/library/secrets.rst | |
parent | 9e9235511ec8e211683e6dfc5f02d86c773bb4ef (diff) | |
download | cpython-git-b2871faa874c5a7abd7d9f77dfeb6082253a40be.tar.gz |
Documentation for secrets.py
Diffstat (limited to 'Doc/library/secrets.rst')
-rw-r--r-- | Doc/library/secrets.rst | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/Doc/library/secrets.rst b/Doc/library/secrets.rst new file mode 100644 index 0000000000..cc214af309 --- /dev/null +++ b/Doc/library/secrets.rst @@ -0,0 +1,199 @@ +:mod:`secrets` --- Generate secure random numbers for managing secrets +====================================================================== + +.. module:: secrets + :synopsis: Generate secure random numbers for managing secrets. + +.. moduleauthor:: Steven D'Aprano <steve+python@pearwood.info> +.. sectionauthor:: Steven D'Aprano <steve+python@pearwood.info> +.. versionadded:: 3.6 + +.. testsetup:: + + from secrets import * + __name__ = '<doctest>' + +**Source code:** :source:`Lib/secrets.py` + +------------- + +The :mod:`secrets` module is used for generating cryptographically strong +random numbers suitable for managing data such as passwords, account +authentication, security tokens, and related secrets. + +In particularly, :mod:`secrets` should be used in preference to the +default pseudo-random number generator in the :mod:`random` module, which +is designed for modelling and simulation, not security or cryptography. + +.. seealso:: + + :pep:`506` + + +Random numbers +-------------- + +The :mod:`secrets` module provides access to the most secure source of +randomness that your operating system provides. + +.. class:: SystemRandom + + A class for generating random numbers using the highest-quality + sources provided by the operating system. See + :class:`random.SystemRandom` for additional details. + +.. function:: choice(sequence) + + Return a randomly-chosen element from a non-empty sequence. + +.. function:: randbelow(n) + + Return a random int in the range [0, *n*). + +.. function:: randbits(k) + + Return an int with *k* random bits. + + +Generating tokens +----------------- + +The :mod:`secrets` module provides functions for generating secure +tokens, suitable for applications such as password resets, +hard-to-guess URLs, and similar. + +.. function:: token_bytes([nbytes=None]) + + Return a random byte string containing *nbytes* number of bytes. + If *nbytes* is ``None`` or not supplied, a reasonable default is + used. + + .. doctest:: + + >>> token_bytes(16) #doctest:+SKIP + b'\xebr\x17D*t\xae\xd4\xe3S\xb6\xe2\xebP1\x8b' + + +.. function:: token_hex([nbytes=None]) + + Return a random text string, in hexadecimal. The string has *nbytes* + random bytes, each byte converted to two hex digits. If *nbytes* is + ``None`` or not supplied, a reasonable default is used. + + .. doctest:: + + >>> token_hex(16) #doctest:+SKIP + 'f9bf78b9a18ce6d46a0cd2b0b86df9da' + +.. function:: token_urlsafe([nbytes=None]) + + Return a random URL-safe text string, containing *nbytes* random + bytes. The text is Base64 encoded, so on average, each byte results + in approximately 1.3 characters. If *nbytes* is ``None`` or not + supplied, a reasonable default is used. + + .. doctest:: + + >>> token_urlsafe(16) #doctest:+SKIP + 'Drmhze6EPcv0fN_81Bj-nA' + + +How many bytes should tokens use? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To be secure against +`brute-force attacks <https://en.wikipedia.org/wiki/Brute-force_attack>`_, +tokens need to have sufficient randomness. Unfortunately, what is +considered sufficient will necessarily increase as computers get more +powerful and able to make more guesses in a shorter period. As of 2015, +it is believed that 64 bytes (512 bits) of randomness is sufficient for +the typical use-case expected for the :mod:`secrets` module. + +For those who want to manage their own token length, you can explicitly +specify how much randomness is used for tokens by giving an :class:`int` +argument to the various ``token_*`` functions. That argument is taken +as the number of bytes of randomness to use. + +Otherwise, if no argument is provided, or if the argument is ``None``, +the ``token_*`` functions will use a reasonable default instead. + +.. note:: + + That default is subject to change at any time, including during + maintenance releases. + + +Other functions +--------------- + +.. function:: compare_digest(a, b) + + Return ``True`` if strings *a* and *b* are equal, otherwise ``False``, + in such a way as to redice the risk of + `timing attacks <http://codahale.com/a-lesson-in-timing-attacks/>`_ . + See :func:`hmac.compare_digest` for additional details. + + +Recipes and best practices +-------------------------- + +This section shows recipes and best practices for using :mod:`secrets` +to manage a basic level of security. + +Generate an eight-character alphanumeric password: + +.. testcode:: + + import string + alphabet = string.ascii_letters + string.digits + password = ''.join(choice(alphabet) for i in range(8)) + + +.. note:: + + Applications should + `not store passwords in a recoverable format <http://cwe.mitre.org/data/definitions/257.html>`_ , + whether plain text or encrypted. They should always be salted and + hashed using a cryptographically-strong one-way (irreversible) hash + function. + + +Generate a ten-character alphanumeric password with at least one +lowercase character, at least one uppercase character, and at least +three digits: + +.. testcode:: + + import string + alphabet = string.ascii_letters + string.digits + while True: + password = ''.join(choice(alphabet) for i in range(10)) + if (any(c.islower() for c in password) + and any(c.isupper() for c in password) + and sum(c.isdigit() for c in password) >= 3): + break + + +Generate an `XKCD-style passphrase <http://xkcd.com/936/>`_ : + +.. testcode:: + + # On standard Linux systems, use a convenient dictionary file. + # Other platforms may need to provide their own word-list. + with open('/usr/share/dict/words') as f: + words = [word.strip() for word in f] + password = ' '.join(choice(words) for i in range(4)) + + +Generate a hard-to-guess temporary URL containing a security token +suitable for password recovery applications: + +.. testcode:: + + url = 'https://mydomain.com/reset=' + token_urlsafe() + + + +.. + # This modeline must appear within the last ten lines of the file. + kate: indent-width 3; remove-trailing-space on; replace-tabs on; encoding utf-8; |