CINXE.COM
PEP 506 – Adding A Secrets Module To The Standard Library | peps.python.org
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" content="light dark"> <title>PEP 506 – Adding A Secrets Module To The Standard Library | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0506/"> <link rel="stylesheet" href="../_static/style.css" type="text/css"> <link rel="stylesheet" href="../_static/mq.css" type="text/css"> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light"> <link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark"> <link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss"> <meta property="og:title" content='PEP 506 – Adding A Secrets Module To The Standard Library | peps.python.org'> <meta property="og:description" content="This PEP proposes the addition of a module for common security-related functions such as generating tokens to the Python standard library."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0506/"> <meta property="og:site_name" content="Python Enhancement Proposals (PEPs)"> <meta property="og:image" content="https://peps.python.org/_static/og-image.png"> <meta property="og:image:alt" content="Python PEPs"> <meta property="og:image:width" content="200"> <meta property="og:image:height" content="200"> <meta name="description" content="This PEP proposes the addition of a module for common security-related functions such as generating tokens to the Python standard library."> <meta name="theme-color" content="#3776ab"> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all"> <title>Following system colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="9"></circle> <path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path> </svg> </symbol> <symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all"> <title>Selected dark colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path> </svg> </symbol> <symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all"> <title>Selected light colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="5"></circle> <line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> <line x1="1" y1="12" x2="3" y2="12"></line> <line x1="21" y1="12" x2="23" y2="12"></line> <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> </svg> </symbol> </svg> <script> document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto" </script> <section id="pep-page-section"> <header> <h1>Python Enhancement Proposals</h1> <ul class="breadcrumbs"> <li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li> <li><a href="../pep-0000/">PEP Index</a> » </li> <li>PEP 506</li> </ul> <button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())"> <svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg> <span class="visually-hidden">Toggle light / dark / auto colour theme</span> </button> </header> <article> <section id="pep-content"> <h1 class="page-title">PEP 506 – Adding A Secrets Module To The Standard Library</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Steven D’Aprano <steve at pearwood.info></dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd> <dt class="field-even">Created<span class="colon">:</span></dt> <dd class="field-even">19-Sep-2015</dd> <dt class="field-odd">Python-Version<span class="colon">:</span></dt> <dd class="field-odd">3.6</dd> <dt class="field-even">Post-History<span class="colon">:</span></dt> <dd class="field-even"><p></p></dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#definitions">Definitions</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#proposal">Proposal</a></li> <li><a class="reference internal" href="#api-and-implementation">API and Implementation</a><ul> <li><a class="reference internal" href="#default-arguments">Default arguments</a></li> <li><a class="reference internal" href="#naming-conventions">Naming conventions</a></li> </ul> </li> <li><a class="reference internal" href="#alternatives">Alternatives</a></li> <li><a class="reference internal" href="#comparison-to-other-languages">Comparison To Other Languages</a></li> <li><a class="reference internal" href="#what-should-be-the-name-of-the-module">What Should Be The Name Of The Module?</a></li> <li><a class="reference internal" href="#frequently-asked-questions">Frequently Asked Questions</a></li> <li><a class="reference internal" href="#references">References</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> </details></section> <section id="abstract"> <h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2> <p>This PEP proposes the addition of a module for common security-related functions such as generating tokens to the Python standard library.</p> </section> <section id="definitions"> <h2><a class="toc-backref" href="#definitions" role="doc-backlink">Definitions</a></h2> <p>Some common abbreviations used in this proposal:</p> <ul> <li>PRNG:<p>Pseudo Random Number Generator. A deterministic algorithm used to produce random-looking numbers with certain desirable statistical properties.</p> </li> <li>CSPRNG:<p>Cryptographically Strong Pseudo Random Number Generator. An algorithm used to produce random-looking numbers which are resistant to prediction.</p> </li> <li>MT:<p>Mersenne Twister. An extensively studied PRNG which is currently used by the <code class="docutils literal notranslate"><span class="pre">random</span></code> module as the default.</p> </li> </ul> </section> <section id="rationale"> <h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2> <p>This proposal is motivated by concerns that Python’s standard library makes it too easy for developers to inadvertently make serious security errors. Theo de Raadt, the founder of OpenBSD, contacted Guido van Rossum and expressed some concern <a class="footnote-reference brackets" href="#id38" id="id1">[1]</a> about the use of MT for generating sensitive information such as passwords, secure tokens, session keys and similar.</p> <p>Although the documentation for the <code class="docutils literal notranslate"><span class="pre">random</span></code> module explicitly states that the default is not suitable for security purposes <a class="footnote-reference brackets" href="#id39" id="id2">[2]</a>, it is strongly believed that this warning may be missed, ignored or misunderstood by many Python developers. In particular:</p> <ul class="simple"> <li>developers may not have read the documentation and consequently not seen the warning;</li> <li>they may not realise that their specific use of the module has security implications; or</li> <li>not realising that there could be a problem, they have copied code (or learned techniques) from websites which don’t offer best practises.</li> </ul> <p>The first <a class="footnote-reference brackets" href="#id40" id="id3">[3]</a> hit when searching for “python how to generate passwords” on Google is a tutorial that uses the default functions from the <code class="docutils literal notranslate"><span class="pre">random</span></code> module <a class="footnote-reference brackets" href="#id41" id="id4">[4]</a>. Although it is not intended for use in web applications, it is likely that similar techniques find themselves used in that situation. The second hit is to a StackOverflow question about generating passwords <a class="footnote-reference brackets" href="#id42" id="id5">[5]</a>. Most of the answers given, including the accepted one, use the default functions. When one user warned that the default could be easily compromised, they were told “I think you worry too much.” <a class="footnote-reference brackets" href="#id43" id="id6">[6]</a></p> <p>This strongly suggests that the existing <code class="docutils literal notranslate"><span class="pre">random</span></code> module is an attractive nuisance when it comes to generating (for example) passwords or secure tokens.</p> <p>Additional motivation (of a more philosophical bent) can be found in the post which first proposed this idea <a class="footnote-reference brackets" href="#id44" id="id7">[7]</a>.</p> </section> <section id="proposal"> <h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2> <p>Alternative proposals have focused on the default PRNG in the <code class="docutils literal notranslate"><span class="pre">random</span></code> module, with the aim of providing “secure by default” cryptographically strong primitives that developers can build upon without thinking about security. (See Alternatives below.) This proposes a different approach:</p> <ul class="simple"> <li>The standard library already provides cryptographically strong primitives, but many users don’t know they exist or when to use them.</li> <li>Instead of requiring crypto-naive users to write secure code, the standard library should include a set of ready-to-use “batteries” for the most common needs, such as generating secure tokens. This code will both directly satisfy a need (“How do I generate a password reset token?”), and act as an example of acceptable practises which developers can learn from <a class="footnote-reference brackets" href="#id45" id="id8">[8]</a>.</li> </ul> <p>To do this, this PEP proposes that we add a new module to the standard library, with the suggested name <code class="docutils literal notranslate"><span class="pre">secrets</span></code>. This module will contain a set of ready-to-use functions for common activities with security implications, together with some lower-level primitives.</p> <p>The suggestion is that <code class="docutils literal notranslate"><span class="pre">secrets</span></code> becomes the go-to module for dealing with anything which should remain secret (passwords, tokens, etc.) while the <code class="docutils literal notranslate"><span class="pre">random</span></code> module remains backward-compatible.</p> </section> <section id="api-and-implementation"> <h2><a class="toc-backref" href="#api-and-implementation" role="doc-backlink">API and Implementation</a></h2> <p>This PEP proposes the following functions for the <code class="docutils literal notranslate"><span class="pre">secrets</span></code> module:</p> <ul class="simple"> <li>Functions for generating tokens suitable for use in (e.g.) password recovery, as session keys, etc., in the following formats:<ul> <li>as bytes, <code class="docutils literal notranslate"><span class="pre">secrets.token_bytes</span></code>;</li> <li>as text, using hexadecimal digits, <code class="docutils literal notranslate"><span class="pre">secrets.token_hex</span></code>;</li> <li>as text, using URL-safe base-64 encoding, <code class="docutils literal notranslate"><span class="pre">secrets.token_urlsafe</span></code>.</li> </ul> </li> <li>A limited interface to the system CSPRNG, using either <code class="docutils literal notranslate"><span class="pre">os.urandom</span></code> directly or <code class="docutils literal notranslate"><span class="pre">random.SystemRandom</span></code>. Unlike the <code class="docutils literal notranslate"><span class="pre">random</span></code> module, this does not need to provide methods for seeding, getting or setting the state, or any non-uniform distributions. It should provide the following:<ul> <li>A function for choosing items from a sequence, <code class="docutils literal notranslate"><span class="pre">secrets.choice</span></code>.</li> <li>A function for generating a given number of random bits and/or bytes as an integer, <code class="docutils literal notranslate"><span class="pre">secrets.randbits</span></code>.</li> <li>A function for returning a random integer in the half-open range 0 to the given upper limit, <code class="docutils literal notranslate"><span class="pre">secrets.randbelow</span></code> <a class="footnote-reference brackets" href="#id46" id="id9">[9]</a>.</li> </ul> </li> <li>A function for comparing text or bytes digests for equality while being resistant to timing attacks, <code class="docutils literal notranslate"><span class="pre">secrets.compare_digest</span></code>.</li> </ul> <p>The consensus appears to be that there is no need to add a new CSPRNG to the <code class="docutils literal notranslate"><span class="pre">random</span></code> module to support these uses, <code class="docutils literal notranslate"><span class="pre">SystemRandom</span></code> will be sufficient.</p> <p>Some illustrative implementations have been given by Alyssa (Nick) Coghlan <a class="footnote-reference brackets" href="#id47" id="id10">[10]</a> and a minimalist API by Tim Peters <a class="footnote-reference brackets" href="#id48" id="id11">[11]</a>. This idea has also been discussed on the issue tracker for the “cryptography” module <a class="footnote-reference brackets" href="#id49" id="id12">[12]</a>. The following pseudo-code should be taken as the starting point for the real implementation:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">random</span><span class="w"> </span><span class="kn">import</span> <span class="n">SystemRandom</span> <span class="kn">from</span><span class="w"> </span><span class="nn">hmac</span><span class="w"> </span><span class="kn">import</span> <span class="n">compare_digest</span> <span class="n">_sysrand</span> <span class="o">=</span> <span class="n">SystemRandom</span><span class="p">()</span> <span class="n">randbits</span> <span class="o">=</span> <span class="n">_sysrand</span><span class="o">.</span><span class="n">getrandbits</span> <span class="n">choice</span> <span class="o">=</span> <span class="n">_sysrand</span><span class="o">.</span><span class="n">choice</span> <span class="k">def</span><span class="w"> </span><span class="nf">randbelow</span><span class="p">(</span><span class="n">exclusive_upper_bound</span><span class="p">):</span> <span class="k">return</span> <span class="n">_sysrand</span><span class="o">.</span><span class="n">_randbelow</span><span class="p">(</span><span class="n">exclusive_upper_bound</span><span class="p">)</span> <span class="n">DEFAULT_ENTROPY</span> <span class="o">=</span> <span class="mi">32</span> <span class="c1"># bytes</span> <span class="k">def</span><span class="w"> </span><span class="nf">token_bytes</span><span class="p">(</span><span class="n">nbytes</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="k">if</span> <span class="n">nbytes</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="n">nbytes</span> <span class="o">=</span> <span class="n">DEFAULT_ENTROPY</span> <span class="k">return</span> <span class="n">os</span><span class="o">.</span><span class="n">urandom</span><span class="p">(</span><span class="n">nbytes</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">token_hex</span><span class="p">(</span><span class="n">nbytes</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="k">return</span> <span class="n">binascii</span><span class="o">.</span><span class="n">hexlify</span><span class="p">(</span><span class="n">token_bytes</span><span class="p">(</span><span class="n">nbytes</span><span class="p">))</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">'ascii'</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">token_urlsafe</span><span class="p">(</span><span class="n">nbytes</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="n">tok</span> <span class="o">=</span> <span class="n">token_bytes</span><span class="p">(</span><span class="n">nbytes</span><span class="p">)</span> <span class="k">return</span> <span class="n">base64</span><span class="o">.</span><span class="n">urlsafe_b64encode</span><span class="p">(</span><span class="n">tok</span><span class="p">)</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="sa">b</span><span class="s1">'='</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">'ascii'</span><span class="p">)</span> </pre></div> </div> <p>The <code class="docutils literal notranslate"><span class="pre">secrets</span></code> module itself will be pure Python, and other Python implementations can easily make use of it unchanged, or adapt it as necessary. An implementation can be found on BitBucket <a class="footnote-reference brackets" href="#id50" id="id13">[13]</a>.</p> <section id="default-arguments"> <h3><a class="toc-backref" href="#default-arguments" role="doc-backlink">Default arguments</a></h3> <p>One difficult question is “How many bytes should my token be?”. We can help with this question by providing a default amount of entropy for the “token_*” functions. If the <code class="docutils literal notranslate"><span class="pre">nbytes</span></code> argument is None or not given, the default entropy will be used. This default value should be large enough to be expected to be secure for medium-security uses, but is expected to change in the future, possibly even in a maintenance release <a class="footnote-reference brackets" href="#id51" id="id14">[14]</a>.</p> </section> <section id="naming-conventions"> <h3><a class="toc-backref" href="#naming-conventions" role="doc-backlink">Naming conventions</a></h3> <p>One question is the naming conventions used in the module <a class="footnote-reference brackets" href="#id52" id="id15">[15]</a>, whether to use C-like naming conventions such as “randrange” or more Pythonic names such as “random_range”.</p> <p>Functions which are simply bound methods of the private <code class="docutils literal notranslate"><span class="pre">SystemRandom</span></code> instance (e.g. <code class="docutils literal notranslate"><span class="pre">randrange</span></code>), or a thin wrapper around such, should keep the familiar names. Those which are something new (such as the various <code class="docutils literal notranslate"><span class="pre">token_*</span></code> functions) will use more Pythonic names.</p> </section> </section> <section id="alternatives"> <h2><a class="toc-backref" href="#alternatives" role="doc-backlink">Alternatives</a></h2> <p>One alternative is to change the default PRNG provided by the <code class="docutils literal notranslate"><span class="pre">random</span></code> module <a class="footnote-reference brackets" href="#id53" id="id16">[16]</a>. This received considerable scepticism and outright opposition:</p> <ul class="simple"> <li>There is fear that a CSPRNG may be slower than the current PRNG (which in the case of MT is already quite slow).</li> <li>Some applications (such as scientific simulations, and replaying gameplay) require the ability to seed the PRNG into a known state, which a CSPRNG lacks by design.</li> <li>Another major use of the <code class="docutils literal notranslate"><span class="pre">random</span></code> module is for simple “guess a number” games written by beginners, and many people are loath to make any change to the <code class="docutils literal notranslate"><span class="pre">random</span></code> module which may make that harder.</li> <li>Although there is no proposal to remove MT from the <code class="docutils literal notranslate"><span class="pre">random</span></code> module, there was considerable hostility to the idea of having to opt-in to a non-CSPRNG or any backwards-incompatible changes.</li> <li>Demonstrated attacks against MT are typically against PHP applications. It is believed that PHP’s version of MT is a significantly softer target than Python’s version, due to a poor seeding technique <a class="footnote-reference brackets" href="#id54" id="id17">[17]</a>. Consequently, without a proven attack against Python applications, many people object to a backwards-incompatible change.</li> </ul> <p>Alyssa Coghlan made an <a class="pep reference internal" href="../pep-0504/" title="PEP 504 – Using the System RNG by default">earlier suggestion</a> for a globally configurable PRNG which uses the system CSPRNG by default, but has since withdrawn it in favour of this proposal.</p> </section> <section id="comparison-to-other-languages"> <h2><a class="toc-backref" href="#comparison-to-other-languages" role="doc-backlink">Comparison To Other Languages</a></h2> <ul> <li>PHP<p>PHP includes a function <code class="docutils literal notranslate"><span class="pre">uniqid</span></code> <a class="footnote-reference brackets" href="#id55" id="id18">[18]</a> which by default returns a thirteen character string based on the current time in microseconds. Translated into Python syntax, it has the following signature:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">uniqid</span><span class="p">(</span><span class="n">prefix</span><span class="o">=</span><span class="s1">''</span><span class="p">,</span> <span class="n">more_entropy</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span><span class="o">-></span><span class="nb">str</span> </pre></div> </div> <p>The PHP documentation warns that this function is not suitable for security purposes. Nevertheless, various mature, well-known PHP applications use it for that purpose (citation needed).</p> <p>PHP 5.3 and better also includes a function <code class="docutils literal notranslate"><span class="pre">openssl_random_pseudo_bytes</span></code> <a class="footnote-reference brackets" href="#id56" id="id19">[19]</a>. Translated into Python syntax, it has roughly the following signature:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">openssl_random_pseudo_bytes</span><span class="p">(</span><span class="n">length</span><span class="p">:</span><span class="nb">int</span><span class="p">)</span><span class="o">-></span><span class="n">Tuple</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">bool</span><span class="p">]</span> </pre></div> </div> <p>This function returns a pseudo-random string of bytes of the given length, and a boolean flag giving whether the string is considered cryptographically strong. The PHP manual suggests that returning anything but True should be rare except for old or broken platforms.</p> </li> <li>JavaScript<p>Based on a rather cursory search <a class="footnote-reference brackets" href="#id57" id="id20">[20]</a>, there do not appear to be any well-known standard functions for producing strong random values in JavaScript. <code class="docutils literal notranslate"><span class="pre">Math.random</span></code> is often used, despite serious weaknesses making it unsuitable for cryptographic purposes <a class="footnote-reference brackets" href="#id58" id="id21">[21]</a>. In recent years the majority of browsers have gained support for <code class="docutils literal notranslate"><span class="pre">window.crypto.getRandomValues</span></code> <a class="footnote-reference brackets" href="#id59" id="id22">[22]</a>.</p> <p>Node.js offers a rich cryptographic module, <code class="docutils literal notranslate"><span class="pre">crypto</span></code> <a class="footnote-reference brackets" href="#id60" id="id23">[23]</a>, most of which is beyond the scope of this PEP. It does include a single function for generating random bytes, <code class="docutils literal notranslate"><span class="pre">crypto.randomBytes</span></code>.</p> </li> <li>Ruby<p>The Ruby standard library includes a module <code class="docutils literal notranslate"><span class="pre">SecureRandom</span></code> <a class="footnote-reference brackets" href="#id61" id="id24">[24]</a> which includes the following methods:</p> <ul class="simple"> <li>base64 - returns a Base64 encoded random string.</li> <li>hex - returns a random hexadecimal string.</li> <li>random_bytes - returns a random byte string.</li> <li>random_number - depending on the argument, returns either a random integer in the range(0, n), or a random float between 0.0 and 1.0.</li> <li>urlsafe_base64 - returns a random URL-safe Base64 encoded string.</li> <li>uuid - return a version 4 random Universally Unique IDentifier.</li> </ul> </li> </ul> </section> <section id="what-should-be-the-name-of-the-module"> <h2><a class="toc-backref" href="#what-should-be-the-name-of-the-module" role="doc-backlink">What Should Be The Name Of The Module?</a></h2> <p>There was a proposal to add a “random.safe” submodule, quoting the Zen of Python “Namespaces are one honking great idea” koan. However, the author of the Zen, Tim Peters, has come out against this idea <a class="footnote-reference brackets" href="#id62" id="id25">[25]</a>, and recommends a top-level module.</p> <p>In discussion on the python-ideas mailing list so far, the name “secrets” has received some approval, and no strong opposition.</p> <p>There is already an existing third-party module with the same name <a class="footnote-reference brackets" href="#id63" id="id26">[26]</a>, but it appears to be unused and abandoned.</p> </section> <section id="frequently-asked-questions"> <h2><a class="toc-backref" href="#frequently-asked-questions" role="doc-backlink">Frequently Asked Questions</a></h2> <ul> <li>Q: Is this a real problem? Surely MT is random enough that nobody can predict its output.<p>A: The consensus among security professionals is that MT is not safe in security contexts. It is not difficult to reconstruct the internal state of MT <a class="footnote-reference brackets" href="#id64" id="id27">[27]</a> <a class="footnote-reference brackets" href="#id65" id="id28">[28]</a> and so predict all past and future values. There are a number of known, practical attacks on systems using MT for randomness <a class="footnote-reference brackets" href="#id66" id="id29">[29]</a>.</p> </li> <li>Q: Attacks on PHP are one thing, but are there any known attacks on Python software?<p>A: Yes. There have been vulnerabilities in Zope and Plone at the very least. Hanno Schlichting commented <a class="footnote-reference brackets" href="#id67" id="id30">[30]</a>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="s2">"In the context of Plone and Zope a practical attack was</span> <span class="n">demonstrated</span><span class="p">,</span> <span class="n">but</span> <span class="n">I</span> <span class="n">can</span><span class="s1">'t find any good non-broken links about</span> <span class="n">this</span> <span class="n">anymore</span><span class="o">.</span> <span class="n">IIRC</span> <span class="n">Plone</span> <span class="n">generated</span> <span class="n">a</span> <span class="n">random</span> <span class="n">number</span> <span class="ow">and</span> <span class="n">exposed</span> <span class="n">this</span> <span class="n">on</span> <span class="n">each</span> <span class="n">error</span> <span class="n">page</span> <span class="n">along</span> <span class="n">the</span> <span class="n">lines</span> <span class="n">of</span> <span class="s1">'Sorry, you encountered</span> <span class="n">an</span> <span class="n">error</span><span class="p">,</span> <span class="n">your</span> <span class="n">problem</span> <span class="n">has</span> <span class="n">been</span> <span class="n">filed</span> <span class="k">as</span> <span class="o"><</span><span class="n">random</span> <span class="n">number</span><span class="o">></span><span class="p">,</span> <span class="n">please</span> <span class="n">include</span> <span class="n">this</span> <span class="n">when</span> <span class="n">you</span> <span class="n">contact</span> <span class="n">us</span><span class="s1">'. This allowed anyone to do large</span> <span class="n">numbers</span> <span class="n">of</span> <span class="n">requests</span> <span class="n">to</span> <span class="n">this</span> <span class="n">page</span> <span class="ow">and</span> <span class="n">get</span> <span class="n">enough</span> <span class="n">random</span> <span class="n">values</span> <span class="n">to</span> <span class="n">reconstruct</span> <span class="n">the</span> <span class="n">MT</span> <span class="n">state</span><span class="o">.</span> <span class="n">A</span> <span class="n">couple</span> <span class="n">of</span> <span class="n">security</span> <span class="n">related</span> <span class="n">modules</span> <span class="n">used</span> <span class="n">random</span> <span class="n">instead</span> <span class="n">of</span> <span class="n">system</span> <span class="n">random</span> <span class="p">(</span><span class="n">cookie</span> <span class="n">session</span> <span class="n">ids</span><span class="p">,</span> <span class="n">password</span> <span class="n">reset</span> <span class="n">links</span><span class="p">,</span> <span class="n">auth</span> <span class="n">token</span><span class="p">),</span> <span class="n">so</span> <span class="n">the</span> <span class="n">attacker</span> <span class="n">could</span> <span class="k">break</span> <span class="nb">all</span> <span class="n">of</span> <span class="n">those</span><span class="o">.</span><span class="s2">"</span> </pre></div> </div> <p>Christian Heimes reported this issue to the Zope security team in 2012 <a class="footnote-reference brackets" href="#id68" id="id31">[31]</a>, there are at least two related CVE vulnerabilities <a class="footnote-reference brackets" href="#id69" id="id32">[32]</a>, and at least one work-around for this issue in Django <a class="footnote-reference brackets" href="#id70" id="id33">[33]</a>.</p> </li> <li>Q: Is this an alternative to specialist cryptographic software such as SSL?<p>A: No. This is a “batteries included” solution, not a full-featured “nuclear reactor”. It is intended to mitigate against some basic security errors, not be a solution to all security-related issues. To quote Alyssa Coghlan referring to her earlier proposal <a class="footnote-reference brackets" href="#id71" id="id34">[34]</a>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="s2">"...folks really are better off learning to use things like</span> <span class="n">cryptography</span><span class="o">.</span><span class="n">io</span> <span class="k">for</span> <span class="n">security</span> <span class="n">sensitive</span> <span class="n">software</span><span class="p">,</span> <span class="n">so</span> <span class="n">this</span> <span class="n">change</span> <span class="ow">is</span> <span class="n">just</span> <span class="n">about</span> <span class="n">harm</span> <span class="n">mitigation</span> <span class="n">given</span> <span class="n">that</span> <span class="n">it</span><span class="s1">'s inevitable that a</span> <span class="n">non</span><span class="o">-</span><span class="n">trivial</span> <span class="n">proportion</span> <span class="n">of</span> <span class="n">the</span> <span class="n">millions</span> <span class="n">of</span> <span class="n">current</span> <span class="ow">and</span> <span class="n">future</span> <span class="n">Python</span> <span class="n">developers</span> <span class="n">won</span><span class="s1">'t do that."</span> </pre></div> </div> </li> <li>Q: What about a password generator?<p>A: The consensus is that the requirements for password generators are too variable for it to be a good match for the standard library <a class="footnote-reference brackets" href="#id72" id="id35">[35]</a>. No password generator will be included in the initial release of the module, instead it will be given in the documentation as a recipe (à la the recipes in the <code class="docutils literal notranslate"><span class="pre">itertools</span></code> module) <a class="footnote-reference brackets" href="#id73" id="id36">[36]</a>.</p> </li> <li>Q: Will <code class="docutils literal notranslate"><span class="pre">secrets</span></code> use /dev/random (which blocks) or /dev/urandom (which doesn’t block) on Linux? What about other platforms?<p>A: <code class="docutils literal notranslate"><span class="pre">secrets</span></code> will be based on <code class="docutils literal notranslate"><span class="pre">os.urandom</span></code> and <code class="docutils literal notranslate"><span class="pre">random.SystemRandom</span></code>, which are interfaces to your operating system’s best source of cryptographic randomness. On Linux, that may be <code class="docutils literal notranslate"><span class="pre">/dev/urandom</span></code> <a class="footnote-reference brackets" href="#id74" id="id37">[37]</a>, on Windows it may be <code class="docutils literal notranslate"><span class="pre">CryptGenRandom()</span></code>, but see the documentation and/or source code for the detailed implementation details.</p> </li> </ul> </section> <section id="references"> <h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2> <aside class="footnote-list brackets"> <aside class="footnote brackets" id="id38" role="doc-footnote"> <dt class="label" id="id38">[<a href="#id1">1</a>]</dt> <dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/035820.html">https://mail.python.org/pipermail/python-ideas/2015-September/035820.html</a></aside> <aside class="footnote brackets" id="id39" role="doc-footnote"> <dt class="label" id="id39">[<a href="#id2">2</a>]</dt> <dd><a class="reference external" href="https://docs.python.org/3/library/random.html">https://docs.python.org/3/library/random.html</a></aside> <aside class="footnote brackets" id="id40" role="doc-footnote"> <dt class="label" id="id40">[<a href="#id3">3</a>]</dt> <dd>As of the date of writing. Also, as Google search terms may be automatically customised for the user without their knowledge, some readers may see different results.</aside> <aside class="footnote brackets" id="id41" role="doc-footnote"> <dt class="label" id="id41">[<a href="#id4">4</a>]</dt> <dd><a class="reference external" href="http://interactivepython.org/runestone/static/everyday/2013/01/3_password.html">http://interactivepython.org/runestone/static/everyday/2013/01/3_password.html</a></aside> <aside class="footnote brackets" id="id42" role="doc-footnote"> <dt class="label" id="id42">[<a href="#id5">5</a>]</dt> <dd><a class="reference external" href="http://stackoverflow.com/questions/3854692/generate-password-in-python">http://stackoverflow.com/questions/3854692/generate-password-in-python</a></aside> <aside class="footnote brackets" id="id43" role="doc-footnote"> <dt class="label" id="id43">[<a href="#id6">6</a>]</dt> <dd><a class="reference external" href="http://stackoverflow.com/questions/3854692/generate-password-in-python/3854766#3854766">http://stackoverflow.com/questions/3854692/generate-password-in-python/3854766#3854766</a></aside> <aside class="footnote brackets" id="id44" role="doc-footnote"> <dt class="label" id="id44">[<a href="#id7">7</a>]</dt> <dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/036238.html">https://mail.python.org/pipermail/python-ideas/2015-September/036238.html</a></aside> <aside class="footnote brackets" id="id45" role="doc-footnote"> <dt class="label" id="id45">[<a href="#id8">8</a>]</dt> <dd>At least those who are motivated to read the source code and documentation.</aside> <aside class="footnote brackets" id="id46" role="doc-footnote"> <dt class="label" id="id46">[<a href="#id9">9</a>]</dt> <dd>After considerable discussion, Guido ruled that the module need only provide <code class="docutils literal notranslate"><span class="pre">randbelow</span></code>, and not similar functions <code class="docutils literal notranslate"><span class="pre">randrange</span></code> or <code class="docutils literal notranslate"><span class="pre">randint</span></code>. <a class="reference external" href="http://code.activestate.com/lists/python-dev/138375/">http://code.activestate.com/lists/python-dev/138375/</a></aside> <aside class="footnote brackets" id="id47" role="doc-footnote"> <dt class="label" id="id47">[<a href="#id10">10</a>]</dt> <dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/036271.html">https://mail.python.org/pipermail/python-ideas/2015-September/036271.html</a></aside> <aside class="footnote brackets" id="id48" role="doc-footnote"> <dt class="label" id="id48">[<a href="#id11">11</a>]</dt> <dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/036350.html">https://mail.python.org/pipermail/python-ideas/2015-September/036350.html</a></aside> <aside class="footnote brackets" id="id49" role="doc-footnote"> <dt class="label" id="id49">[<a href="#id12">12</a>]</dt> <dd><a class="reference external" href="https://github.com/pyca/cryptography/issues/2347">https://github.com/pyca/cryptography/issues/2347</a></aside> <aside class="footnote brackets" id="id50" role="doc-footnote"> <dt class="label" id="id50">[<a href="#id13">13</a>]</dt> <dd><a class="reference external" href="https://bitbucket.org/sdaprano/secrets">https://bitbucket.org/sdaprano/secrets</a></aside> <aside class="footnote brackets" id="id51" role="doc-footnote"> <dt class="label" id="id51">[<a href="#id14">14</a>]</dt> <dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/036517.html">https://mail.python.org/pipermail/python-ideas/2015-September/036517.html</a> <a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/036515.html">https://mail.python.org/pipermail/python-ideas/2015-September/036515.html</a></aside> <aside class="footnote brackets" id="id52" role="doc-footnote"> <dt class="label" id="id52">[<a href="#id15">15</a>]</dt> <dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/036474.html">https://mail.python.org/pipermail/python-ideas/2015-September/036474.html</a></aside> <aside class="footnote brackets" id="id53" role="doc-footnote"> <dt class="label" id="id53">[<a href="#id16">16</a>]</dt> <dd>Link needed.</aside> <aside class="footnote brackets" id="id54" role="doc-footnote"> <dt class="label" id="id54">[<a href="#id17">17</a>]</dt> <dd>By default PHP seeds the MT PRNG with the time (citation needed), which is exploitable by attackers, while Python seeds the PRNG with output from the system CSPRNG, which is believed to be much harder to exploit.</aside> <aside class="footnote brackets" id="id55" role="doc-footnote"> <dt class="label" id="id55">[<a href="#id18">18</a>]</dt> <dd><a class="reference external" href="http://php.net/manual/en/function.uniqid.php">http://php.net/manual/en/function.uniqid.php</a></aside> <aside class="footnote brackets" id="id56" role="doc-footnote"> <dt class="label" id="id56">[<a href="#id19">19</a>]</dt> <dd><a class="reference external" href="http://php.net/manual/en/function.openssl-random-pseudo-bytes.php">http://php.net/manual/en/function.openssl-random-pseudo-bytes.php</a></aside> <aside class="footnote brackets" id="id57" role="doc-footnote"> <dt class="label" id="id57">[<a href="#id20">20</a>]</dt> <dd>Volunteers and patches are welcome.</aside> <aside class="footnote brackets" id="id58" role="doc-footnote"> <dt class="label" id="id58">[<a href="#id21">21</a>]</dt> <dd><a class="reference external" href="http://ifsec.blogspot.fr/2012/05/cross-domain-mathrandom-prediction.html">http://ifsec.blogspot.fr/2012/05/cross-domain-mathrandom-prediction.html</a></aside> <aside class="footnote brackets" id="id59" role="doc-footnote"> <dt class="label" id="id59">[<a href="#id22">22</a>]</dt> <dd><a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues">https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues</a></aside> <aside class="footnote brackets" id="id60" role="doc-footnote"> <dt class="label" id="id60">[<a href="#id23">23</a>]</dt> <dd><a class="reference external" href="https://nodejs.org/api/crypto.html">https://nodejs.org/api/crypto.html</a></aside> <aside class="footnote brackets" id="id61" role="doc-footnote"> <dt class="label" id="id61">[<a href="#id24">24</a>]</dt> <dd><a class="reference external" href="http://ruby-doc.org/stdlib-2.1.2/libdoc/securerandom/rdoc/SecureRandom.html">http://ruby-doc.org/stdlib-2.1.2/libdoc/securerandom/rdoc/SecureRandom.html</a></aside> <aside class="footnote brackets" id="id62" role="doc-footnote"> <dt class="label" id="id62">[<a href="#id25">25</a>]</dt> <dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/036254.html">https://mail.python.org/pipermail/python-ideas/2015-September/036254.html</a></aside> <aside class="footnote brackets" id="id63" role="doc-footnote"> <dt class="label" id="id63">[<a href="#id26">26</a>]</dt> <dd><a class="reference external" href="https://pypi.python.org/pypi/secrets">https://pypi.python.org/pypi/secrets</a></aside> <aside class="footnote brackets" id="id64" role="doc-footnote"> <dt class="label" id="id64">[<a href="#id27">27</a>]</dt> <dd><a class="reference external" href="https://jazzy.id.au/2010/09/22/cracking_random_number_generators_part_3.html">https://jazzy.id.au/2010/09/22/cracking_random_number_generators_part_3.html</a></aside> <aside class="footnote brackets" id="id65" role="doc-footnote"> <dt class="label" id="id65">[<a href="#id28">28</a>]</dt> <dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/036077.html">https://mail.python.org/pipermail/python-ideas/2015-September/036077.html</a></aside> <aside class="footnote brackets" id="id66" role="doc-footnote"> <dt class="label" id="id66">[<a href="#id29">29</a>]</dt> <dd><a class="reference external" href="https://media.blackhat.com/bh-us-12/Briefings/Argyros/BH_US_12_Argyros_PRNG_WP.pdf">https://media.blackhat.com/bh-us-12/Briefings/Argyros/BH_US_12_Argyros_PRNG_WP.pdf</a></aside> <aside class="footnote brackets" id="id67" role="doc-footnote"> <dt class="label" id="id67">[<a href="#id30">30</a>]</dt> <dd>Personal communication, 2016-08-24.</aside> <aside class="footnote brackets" id="id68" role="doc-footnote"> <dt class="label" id="id68">[<a href="#id31">31</a>]</dt> <dd><a class="reference external" href="https://bugs.launchpad.net/zope2/+bug/1071067">https://bugs.launchpad.net/zope2/+bug/1071067</a></aside> <aside class="footnote brackets" id="id69" role="doc-footnote"> <dt class="label" id="id69">[<a href="#id32">32</a>]</dt> <dd><a class="reference external" href="http://www.cvedetails.com/cve/CVE-2012-5508/">http://www.cvedetails.com/cve/CVE-2012-5508/</a> <a class="reference external" href="http://www.cvedetails.com/cve/CVE-2012-6661/">http://www.cvedetails.com/cve/CVE-2012-6661/</a></aside> <aside class="footnote brackets" id="id70" role="doc-footnote"> <dt class="label" id="id70">[<a href="#id33">33</a>]</dt> <dd><a class="reference external" href="https://github.com/django/django/commit/1525874238fd705ec17a066291935a9316bd3044">https://github.com/django/django/commit/1525874238fd705ec17a066291935a9316bd3044</a></aside> <aside class="footnote brackets" id="id71" role="doc-footnote"> <dt class="label" id="id71">[<a href="#id34">34</a>]</dt> <dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/036157.html">https://mail.python.org/pipermail/python-ideas/2015-September/036157.html</a></aside> <aside class="footnote brackets" id="id72" role="doc-footnote"> <dt class="label" id="id72">[<a href="#id35">35</a>]</dt> <dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/036476.html">https://mail.python.org/pipermail/python-ideas/2015-September/036476.html</a> <a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/036478.html">https://mail.python.org/pipermail/python-ideas/2015-September/036478.html</a></aside> <aside class="footnote brackets" id="id73" role="doc-footnote"> <dt class="label" id="id73">[<a href="#id36">36</a>]</dt> <dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/036488.html">https://mail.python.org/pipermail/python-ideas/2015-September/036488.html</a></aside> <aside class="footnote brackets" id="id74" role="doc-footnote"> <dt class="label" id="id74">[<a href="#id37">37</a>]</dt> <dd><a class="reference external" href="http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/">http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/</a> <a class="reference external" href="http://www.2uo.de/myths-about-urandom/">http://www.2uo.de/myths-about-urandom/</a></aside> </aside> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document has been placed in the public domain.</p> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0506.rst">https://github.com/python/peps/blob/main/peps/pep-0506.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0506.rst">2025-02-01 08:59:27 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#definitions">Definitions</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#proposal">Proposal</a></li> <li><a class="reference internal" href="#api-and-implementation">API and Implementation</a><ul> <li><a class="reference internal" href="#default-arguments">Default arguments</a></li> <li><a class="reference internal" href="#naming-conventions">Naming conventions</a></li> </ul> </li> <li><a class="reference internal" href="#alternatives">Alternatives</a></li> <li><a class="reference internal" href="#comparison-to-other-languages">Comparison To Other Languages</a></li> <li><a class="reference internal" href="#what-should-be-the-name-of-the-module">What Should Be The Name Of The Module?</a></li> <li><a class="reference internal" href="#frequently-asked-questions">Frequently Asked Questions</a></li> <li><a class="reference internal" href="#references">References</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> <br> <a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0506.rst">Page Source (GitHub)</a> </nav> </section> <script src="../_static/colour_scheme.js"></script> <script src="../_static/wrap_tables.js"></script> <script src="../_static/sticky_banner.js"></script> </body> </html>