Skip to content

Commit b2871fa

Browse files
author
Steven D'Aprano
committed
Documentation for secrets.py
1 parent 9e92355 commit b2871fa

3 files changed

Lines changed: 202 additions & 1 deletion

File tree

Doc/library/crypto.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ Here's an overview:
1616

1717
hashlib.rst
1818
hmac.rst
19+
secrets.rst

Doc/library/random.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ from sources provided by the operating system.
4646
.. warning::
4747

4848
The pseudo-random generators of this module should not be used for
49-
security purposes.
49+
security purposes. For security or cryptographic uses, see the
50+
:mod:`secrets` module.
5051

5152

5253
Bookkeeping functions:

Doc/library/secrets.rst

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
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
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+
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,
109+
it is believed that 64 bytes (512 bits) of randomness is sufficient for
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``,
132+
in such a way as to redice the risk of
133+
`timing attacks <http://codahale.com/a-lesson-in-timing-attacks/>`_ .
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
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
155+
`not store passwords in a recoverable format <http://cwe.mitre.org/data/definitions/257.html>`_ ,
156+
whether plain text or encrypted. They should always be salted and
157+
hashed using a cryptographically-strong one-way (irreversible) hash
158+
function.
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
168+
alphabet = string.ascii_letters + string.digits
169+
while True:
170+
password = ''.join(choice(alphabet) for i in range(10))
171+
if (any(c.islower() for c in password)
172+
and any(c.isupper() for c in password)
173+
and sum(c.isdigit() for c in password) >= 3):
174+
break
175+
176+
177+
Generate an `XKCD-style passphrase <http://xkcd.com/936/>`_ :
178+
179+
.. testcode::
180+
181+
# On standard Linux systems, use a convenient dictionary file.
182+
# Other platforms may need to provide their own word-list.
183+
with open('/usr/share/dict/words') as f:
184+
words = [word.strip() for word in f]
185+
password = ' '.join(choice(words) for i in range(4))
186+
187+
188+
Generate a hard-to-guess temporary URL containing a security token
189+
suitable for password recovery applications:
190+
191+
.. testcode::
192+
193+
url = 'https://mydomain.com/reset=' + token_urlsafe()
194+
195+
196+
197+
..
198+
# This modeline must appear within the last ten lines of the file.
199+
kate: indent-width 3; remove-trailing-space on; replace-tabs on; encoding utf-8;

0 commit comments

Comments
 (0)