515 lines
39 KiB
HTML
515 lines
39 KiB
HTML
|
||
<!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 504 – Using the System RNG by default | peps.python.org</title>
|
||
<link rel="shortcut icon" href="../_static/py.png">
|
||
<link rel="canonical" href="https://peps.python.org/pep-0504/">
|
||
<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 504 – Using the System RNG by default | peps.python.org'>
|
||
<meta property="og:description" content="Python currently defaults to using the deterministic Mersenne Twister random number generator for the module level APIs in the random module, requiring users to know that when they’re performing “security sensitive” work, they should instead switch to u...">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://peps.python.org/pep-0504/">
|
||
<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="Python currently defaults to using the deterministic Mersenne Twister random number generator for the module level APIs in the random module, requiring users to know that when they’re performing “security sensitive” work, they should instead switch to u...">
|
||
<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 504</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 504 – Using the System RNG by default</h1>
|
||
<dl class="rfc2822 field-list simple">
|
||
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
||
<dd class="field-odd">Alyssa Coghlan <ncoghlan at gmail.com></dd>
|
||
<dt class="field-even">Status<span class="colon">:</span></dt>
|
||
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</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">15-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">15-Sep-2015</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="#pep-withdrawal">PEP Withdrawal</a></li>
|
||
<li><a class="reference internal" href="#proposal">Proposal</a><ul>
|
||
<li><a class="reference internal" href="#warning-on-implicit-opt-in">Warning on implicit opt-in</a></li>
|
||
<li><a class="reference internal" href="#performance-impact">Performance impact</a></li>
|
||
<li><a class="reference internal" href="#documentation-changes">Documentation changes</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a></li>
|
||
<li><a class="reference internal" href="#discussion">Discussion</a><ul>
|
||
<li><a class="reference internal" href="#why-ensure-repeatable-over-ensure-deterministic">Why “ensure_repeatable” over “ensure_deterministic”?</a></li>
|
||
<li><a class="reference internal" href="#only-changing-the-default-for-python-3-6">Only changing the default for Python 3.6+</a></li>
|
||
<li><a class="reference internal" href="#keeping-the-module-level-functions">Keeping the module level functions</a></li>
|
||
<li><a class="reference internal" href="#warning-when-implicitly-opting-in-to-the-deterministic-rng">Warning when implicitly opting in to the deterministic RNG</a></li>
|
||
<li><a class="reference internal" href="#avoiding-the-introduction-of-a-userspace-csprng">Avoiding the introduction of a userspace CSPRNG</a></li>
|
||
<li><a class="reference internal" href="#isn-t-the-deterministic-prng-secure-enough">Isn’t the deterministic PRNG “secure enough”?</a></li>
|
||
<li><a class="reference internal" href="#security-fatigue-in-the-python-ecosystem">Security fatigue in the Python ecosystem</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</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>Python currently defaults to using the deterministic Mersenne Twister random
|
||
number generator for the module level APIs in the <code class="docutils literal notranslate"><span class="pre">random</span></code> module, requiring
|
||
users to know that when they’re performing “security sensitive” work, they
|
||
should instead switch to using the cryptographically secure <code class="docutils literal notranslate"><span class="pre">os.urandom</span></code> or
|
||
<code class="docutils literal notranslate"><span class="pre">random.SystemRandom</span></code> interfaces or a third party library like
|
||
<code class="docutils literal notranslate"><span class="pre">cryptography</span></code>.</p>
|
||
<p>Unfortunately, this approach has resulted in a situation where developers that
|
||
aren’t aware that they’re doing security sensitive work use the default module
|
||
level APIs, and thus expose their users to unnecessary risks.</p>
|
||
<p>This isn’t an acute problem, but it is a chronic one, and the often long
|
||
delays between the introduction of security flaws and their exploitation means
|
||
that it is difficult for developers to naturally learn from experience.</p>
|
||
<p>In order to provide an eventually pervasive solution to the problem, this PEP
|
||
proposes that Python switch to using the system random number generator by
|
||
default in Python 3.6, and require developers to opt-in to using the
|
||
deterministic random number generator process wide either by using a new
|
||
<code class="docutils literal notranslate"><span class="pre">random.ensure_repeatable()</span></code> API, or by explicitly creating their own
|
||
<code class="docutils literal notranslate"><span class="pre">random.Random()</span></code> instance.</p>
|
||
<p>To minimise the impact on existing code, module level APIs that require
|
||
determinism will implicitly switch to the deterministic PRNG.</p>
|
||
</section>
|
||
<section id="pep-withdrawal">
|
||
<h2><a class="toc-backref" href="#pep-withdrawal" role="doc-backlink">PEP Withdrawal</a></h2>
|
||
<p>During discussion of this PEP, Steven D’Aprano proposed the simpler alternative
|
||
of offering a standardised <code class="docutils literal notranslate"><span class="pre">secrets</span></code> module that provides “one obvious way”
|
||
to handle security sensitive tasks like generating default passwords and other
|
||
tokens.</p>
|
||
<p>Steven’s proposal has the desired effect of aligning the easy way to generate
|
||
such tokens and the right way to generate them, without introducing any
|
||
compatibility risks for the existing <code class="docutils literal notranslate"><span class="pre">random</span></code> module API, so this PEP has
|
||
been withdrawn in favour of further work on refining Steven’s proposal as
|
||
<a class="pep reference internal" href="../pep-0506/" title="PEP 506 – Adding A Secrets Module To The Standard Library">PEP 506</a>.</p>
|
||
</section>
|
||
<section id="proposal">
|
||
<h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2>
|
||
<p>Currently, it is never correct to use the module level functions in the
|
||
<code class="docutils literal notranslate"><span class="pre">random</span></code> module for security sensitive applications. This PEP proposes to
|
||
change that admonition in Python 3.6+ to instead be that it is not correct to
|
||
use the module level functions in the <code class="docutils literal notranslate"><span class="pre">random</span></code> module for security sensitive
|
||
applications if <code class="docutils literal notranslate"><span class="pre">random.ensure_repeatable()</span></code> is ever called (directly or
|
||
indirectly) in that process.</p>
|
||
<p>To achieve this, rather than being bound methods of a <code class="docutils literal notranslate"><span class="pre">random.Random</span></code>
|
||
instance as they are today, the module level callables in <code class="docutils literal notranslate"><span class="pre">random</span></code> would
|
||
change to be functions that delegate to the corresponding method of the
|
||
existing <code class="docutils literal notranslate"><span class="pre">random._inst</span></code> module attribute.</p>
|
||
<p>By default, this attribute will be bound to a <code class="docutils literal notranslate"><span class="pre">random.SystemRandom</span></code> instance.</p>
|
||
<p>A new <code class="docutils literal notranslate"><span class="pre">random.ensure_repeatable()</span></code> API will then rebind the <code class="docutils literal notranslate"><span class="pre">random._inst</span></code>
|
||
attribute to a <code class="docutils literal notranslate"><span class="pre">system.Random</span></code> instance, restoring the same module level
|
||
API behaviour as existed in previous Python versions (aside from the
|
||
additional level of indirection):</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">ensure_repeatable</span><span class="p">():</span>
|
||
<span class="w"> </span><span class="sd">"""Switch to using random.Random() for the module level APIs</span>
|
||
|
||
<span class="sd"> This switches the default RNG instance from the cryptographically</span>
|
||
<span class="sd"> secure random.SystemRandom() to the deterministic random.Random(),</span>
|
||
<span class="sd"> enabling the seed(), getstate() and setstate() operations. This means</span>
|
||
<span class="sd"> a particular random scenario can be replayed later by providing the</span>
|
||
<span class="sd"> same seed value or restoring a previously saved state.</span>
|
||
|
||
<span class="sd"> NOTE: Libraries implementing security sensitive operations should</span>
|
||
<span class="sd"> always explicitly use random.SystemRandom() or os.urandom in order to</span>
|
||
<span class="sd"> correctly handle applications that call this function.</span>
|
||
<span class="sd"> """</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">_inst</span><span class="p">,</span> <span class="n">Random</span><span class="p">):</span>
|
||
<span class="n">_inst</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">Random</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>To minimise the impact on existing code, calling any of the following module
|
||
level functions will implicitly call <code class="docutils literal notranslate"><span class="pre">random.ensure_repeatable()</span></code>:</p>
|
||
<ul class="simple">
|
||
<li><code class="docutils literal notranslate"><span class="pre">random.seed</span></code></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">random.getstate</span></code></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">random.setstate</span></code></li>
|
||
</ul>
|
||
<p>There are no changes proposed to the <code class="docutils literal notranslate"><span class="pre">random.Random</span></code> or
|
||
<code class="docutils literal notranslate"><span class="pre">random.SystemRandom</span></code> class APIs - applications that explicitly instantiate
|
||
their own random number generators will be entirely unaffected by this
|
||
proposal.</p>
|
||
<section id="warning-on-implicit-opt-in">
|
||
<h3><a class="toc-backref" href="#warning-on-implicit-opt-in" role="doc-backlink">Warning on implicit opt-in</a></h3>
|
||
<p>In Python 3.6, implicitly opting in to the use of the deterministic PRNG will
|
||
emit a deprecation warning using the following check:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">_inst</span><span class="p">,</span> <span class="n">Random</span><span class="p">):</span>
|
||
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="ne">DeprecationWarning</span><span class="p">,</span>
|
||
<span class="s2">"Implicitly ensuring repeatability. "</span>
|
||
<span class="s2">"See help(random.ensure_repeatable) for details"</span><span class="p">)</span>
|
||
<span class="n">ensure_repeatable</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The specific wording of the warning should have a suitable answer added to
|
||
Stack Overflow as was done for the custom error message that was added for
|
||
missing parentheses in a call to print <a class="footnote-reference brackets" href="#print" id="id1">[10]</a>.</p>
|
||
<p>In the first Python 3 release after Python 2.7 switches to security fix only
|
||
mode, the deprecation warning will be upgraded to a RuntimeWarning so it is
|
||
visible by default.</p>
|
||
<p>This PEP does <em>not</em> propose ever removing the ability to ensure the default RNG
|
||
used process wide is a deterministic PRNG that will produce the same series of
|
||
outputs given a specific seed. That capability is widely used in modelling
|
||
and simulation scenarios, and requiring that <code class="docutils literal notranslate"><span class="pre">ensure_repeatable()</span></code> be called
|
||
either directly or indirectly is a sufficient enhancement to address the cases
|
||
where the module level random API is used for security sensitive tasks in web
|
||
applications without due consideration for the potential security implications
|
||
of using a deterministic PRNG.</p>
|
||
</section>
|
||
<section id="performance-impact">
|
||
<h3><a class="toc-backref" href="#performance-impact" role="doc-backlink">Performance impact</a></h3>
|
||
<p>Due to the large performance difference between <code class="docutils literal notranslate"><span class="pre">random.Random</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">random.SystemRandom</span></code>, applications ported to Python 3.6 will encounter a
|
||
significant performance regression in cases where:</p>
|
||
<ul class="simple">
|
||
<li>the application is using the module level random API</li>
|
||
<li>cryptographic quality randomness isn’t needed</li>
|
||
<li>the application doesn’t already implicitly opt back in to the deterministic
|
||
PRNG by calling <code class="docutils literal notranslate"><span class="pre">random.seed</span></code>, <code class="docutils literal notranslate"><span class="pre">random.getstate</span></code>, or <code class="docutils literal notranslate"><span class="pre">random.setstate</span></code></li>
|
||
<li>the application isn’t updated to explicitly call <code class="docutils literal notranslate"><span class="pre">random.ensure_repeatable</span></code></li>
|
||
</ul>
|
||
<p>This would be noted in the Porting section of the Python 3.6 What’s New guide,
|
||
with the recommendation to include the following code in the <code class="docutils literal notranslate"><span class="pre">__main__</span></code>
|
||
module of affected applications:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">random</span><span class="p">,</span> <span class="s2">"ensure_repeatable"</span><span class="p">):</span>
|
||
<span class="n">random</span><span class="o">.</span><span class="n">ensure_repeatable</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Applications that do need cryptographic quality randomness should be using the
|
||
system random number generator regardless of speed considerations, so in those
|
||
cases the change proposed in this PEP will fix a previously latent security
|
||
defect.</p>
|
||
</section>
|
||
<section id="documentation-changes">
|
||
<h3><a class="toc-backref" href="#documentation-changes" role="doc-backlink">Documentation changes</a></h3>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">random</span></code> module documentation would be updated to move the documentation
|
||
of the <code class="docutils literal notranslate"><span class="pre">seed</span></code>, <code class="docutils literal notranslate"><span class="pre">getstate</span></code> and <code class="docutils literal notranslate"><span class="pre">setstate</span></code> interfaces later in the module,
|
||
along with the documentation of the new <code class="docutils literal notranslate"><span class="pre">ensure_repeatable</span></code> function and the
|
||
associated security warning.</p>
|
||
<p>That section of the module documentation would also gain a discussion of the
|
||
respective use cases for the deterministic PRNG enabled by
|
||
<code class="docutils literal notranslate"><span class="pre">ensure_repeatable</span></code> (games, modelling & simulation, software testing) and the
|
||
system RNG that is used by default (cryptography, security token generation).
|
||
This discussion will also recommend the use of third party security libraries
|
||
for the latter task.</p>
|
||
</section>
|
||
</section>
|
||
<section id="rationale">
|
||
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
|
||
<p>Writing secure software under deadline and budget pressures is a hard problem.
|
||
This is reflected in regular notifications of data breaches involving personally
|
||
identifiable information <a class="footnote-reference brackets" href="#breaches" id="id2">[1]</a>, as well as with failures to take
|
||
security considerations into account when new systems, like motor vehicles
|
||
<a class="footnote-reference brackets" href="#uconnect" id="id3">[2]</a>, are connected to the internet. It’s also the case that a lot of
|
||
the programming advice readily available on the internet [#search] simply
|
||
doesn’t take the mathematical arcana of computer security into account.
|
||
Compounding these issues is the fact that defenders have to cover <em>all</em> of
|
||
their potential vulnerabilities, as a single mistake can make it possible to
|
||
subvert other defences <a class="footnote-reference brackets" href="#bcrypt" id="id4">[11]</a>.</p>
|
||
<p>One of the factors that contributes to making this last aspect particularly
|
||
difficult is APIs where using them inappropriately creates a <em>silent</em> security
|
||
failure - one where the only way to find out that what you’re doing is
|
||
incorrect is for someone reviewing your code to say “that’s a potential
|
||
security problem”, or for a system you’re responsible for to be compromised
|
||
through such an oversight (and you’re not only still responsible for that
|
||
system when it is compromised, but your intrusion detection and auditing
|
||
mechanisms are good enough for you to be able to figure out after the event
|
||
how the compromise took place).</p>
|
||
<p>This kind of situation is a significant contributor to “security fatigue”,
|
||
where developers (often rightly <a class="footnote-reference brackets" href="#owasptopten" id="id5">[9]</a>) feel that security engineers
|
||
spend all their time saying “don’t do that the easy way, it creates a
|
||
security vulnerability”.</p>
|
||
<p>As the designers of one of the world’s most popular languages <a class="footnote-reference brackets" href="#ieeetopten" id="id6">[8]</a>,
|
||
we can help reduce that problem by making the easy way the right way (or at
|
||
least the “not wrong” way) in more circumstances, so developers and security
|
||
engineers can spend more time worrying about mitigating actually interesting
|
||
threats, and less time fighting with default language behaviours.</p>
|
||
</section>
|
||
<section id="discussion">
|
||
<h2><a class="toc-backref" href="#discussion" role="doc-backlink">Discussion</a></h2>
|
||
<section id="why-ensure-repeatable-over-ensure-deterministic">
|
||
<h3><a class="toc-backref" href="#why-ensure-repeatable-over-ensure-deterministic" role="doc-backlink">Why “ensure_repeatable” over “ensure_deterministic”?</a></h3>
|
||
<p>This is a case where the meaning of a word as specialist jargon conflicts with
|
||
the typical meaning of the word, even though it’s <em>technically</em> the same.</p>
|
||
<p>From a technical perspective, a “deterministic RNG” means that given knowledge
|
||
of the algorithm and the current state, you can reliably compute arbitrary
|
||
future states.</p>
|
||
<p>The problem is that “deterministic” on its own doesn’t convey those qualifiers,
|
||
so it’s likely to instead be interpreted as “predictable” or “not random” by
|
||
folks that are familiar with the conventional meaning, but aren’t familiar with
|
||
the additional qualifiers on the technical meaning.</p>
|
||
<p>A second problem with “deterministic” as a description for the traditional RNG
|
||
is that it doesn’t really tell you what you can <em>do</em> with the traditional RNG
|
||
that you can’t do with the system one.</p>
|
||
<p>“ensure_repeatable” aims to address both of those problems, as its common
|
||
meaning accurately describes the main reason for preferring the deterministic
|
||
PRNG over the system RNG: ensuring you can repeat the same series of outputs
|
||
by providing the same seed value, or by restoring a previously saved PRNG state.</p>
|
||
</section>
|
||
<section id="only-changing-the-default-for-python-3-6">
|
||
<h3><a class="toc-backref" href="#only-changing-the-default-for-python-3-6" role="doc-backlink">Only changing the default for Python 3.6+</a></h3>
|
||
<p>Some other recent security changes, such as upgrading the capabilities of the
|
||
<code class="docutils literal notranslate"><span class="pre">ssl</span></code> module and switching to properly verifying HTTPS certificates by
|
||
default, have been considered critical enough to justify backporting the
|
||
change to all currently supported versions of Python.</p>
|
||
<p>The difference in this case is one of degree - the additional benefits from
|
||
rolling out this particular change a couple of years earlier than will
|
||
otherwise be the case aren’t sufficient to justify either the additional effort
|
||
or the stability risks involved in making such an intrusive change in a
|
||
maintenance release.</p>
|
||
</section>
|
||
<section id="keeping-the-module-level-functions">
|
||
<h3><a class="toc-backref" href="#keeping-the-module-level-functions" role="doc-backlink">Keeping the module level functions</a></h3>
|
||
<p>In additional to general backwards compatibility considerations, Python is
|
||
widely used for educational purposes, and we specifically don’t want to
|
||
invalidate the wide array of educational material that assumes the availability
|
||
of the current <code class="docutils literal notranslate"><span class="pre">random</span></code> module API. Accordingly, this proposal ensures that
|
||
most of the public API can continue to be used not only without modification,
|
||
but without generating any new warnings.</p>
|
||
</section>
|
||
<section id="warning-when-implicitly-opting-in-to-the-deterministic-rng">
|
||
<h3><a class="toc-backref" href="#warning-when-implicitly-opting-in-to-the-deterministic-rng" role="doc-backlink">Warning when implicitly opting in to the deterministic RNG</a></h3>
|
||
<p>It’s necessary to implicitly opt in to the deterministic PRNG as Python is
|
||
widely used for modelling and simulation purposes where this is the right
|
||
thing to do, and in many cases, these software models won’t have a dedicated
|
||
maintenance team tasked with ensuring they keep working on the latest versions
|
||
of Python.</p>
|
||
<p>Unfortunately, explicitly calling <code class="docutils literal notranslate"><span class="pre">random.seed</span></code> with data from <code class="docutils literal notranslate"><span class="pre">os.urandom</span></code>
|
||
is also a mistake that appears in a number of the flawed “how to generate a
|
||
security token in Python” guides readily available online.</p>
|
||
<p>Using first DeprecationWarning, and then eventually a RuntimeWarning, to
|
||
advise against implicitly switching to the deterministic PRNG aims to
|
||
nudge future users that need a cryptographically secure RNG away from
|
||
calling <code class="docutils literal notranslate"><span class="pre">random.seed()</span></code> and those that genuinely need a deterministic
|
||
generator towards explicitly calling <code class="docutils literal notranslate"><span class="pre">random.ensure_repeatable()</span></code>.</p>
|
||
</section>
|
||
<section id="avoiding-the-introduction-of-a-userspace-csprng">
|
||
<h3><a class="toc-backref" href="#avoiding-the-introduction-of-a-userspace-csprng" role="doc-backlink">Avoiding the introduction of a userspace CSPRNG</a></h3>
|
||
<p>The original discussion of this proposal on python-ideas[#csprng]_ suggested
|
||
introducing a cryptographically secure pseudo-random number generator and using
|
||
that by default, rather than defaulting to the relatively slow system random
|
||
number generator.</p>
|
||
<p>The problem <a class="footnote-reference brackets" href="#nocsprng" id="id7">[7]</a> with this approach is that it introduces an additional
|
||
point of failure in security sensitive situations, for the sake of applications
|
||
where the random number generation may not even be on a critical performance
|
||
path.</p>
|
||
<p>Applications that do need cryptographic quality randomness should be using the
|
||
system random number generator regardless of speed considerations, so in those
|
||
cases.</p>
|
||
</section>
|
||
<section id="isn-t-the-deterministic-prng-secure-enough">
|
||
<h3><a class="toc-backref" href="#isn-t-the-deterministic-prng-secure-enough" role="doc-backlink">Isn’t the deterministic PRNG “secure enough”?</a></h3>
|
||
<p>In a word, “No” - that’s why there’s a warning in the module documentation
|
||
that says not to use it for security sensitive purposes. While we’re not
|
||
currently aware of any studies of Python’s random number generator specifically,
|
||
studies of PHP’s random number generator <a class="footnote-reference brackets" href="#php" id="id8">[3]</a> have demonstrated the ability
|
||
to use weaknesses in that subsystem to facilitate a practical attack on
|
||
password recovery tokens in popular PHP web applications.</p>
|
||
<p>However, one of the rules of secure software development is that “attacks only
|
||
get better, never worse”, so it may be that by the time Python 3.6 is released
|
||
we will actually see a practical attack on Python’s deterministic PRNG publicly
|
||
documented.</p>
|
||
</section>
|
||
<section id="security-fatigue-in-the-python-ecosystem">
|
||
<h3><a class="toc-backref" href="#security-fatigue-in-the-python-ecosystem" role="doc-backlink">Security fatigue in the Python ecosystem</a></h3>
|
||
<p>Over the past few years, the computing industry as a whole has been
|
||
making a concerted effort to upgrade the shared network infrastructure we all
|
||
depend on to a “secure by default” stance. As one of the most widely used
|
||
programming languages for network service development (including the OpenStack
|
||
Infrastructure-as-a-Service platform) and for systems administration
|
||
on Linux systems in general, a fair share of that burden has fallen on the
|
||
Python ecosystem, which is understandably frustrating for Pythonistas using
|
||
Python in other contexts where these issues aren’t of as great a concern.</p>
|
||
<p>This consideration is one of the primary factors driving the substantial
|
||
backwards compatibility improvements in this proposal relative to the initial
|
||
draft concept posted to python-ideas <a class="footnote-reference brackets" href="#draft" id="id9">[6]</a>.</p>
|
||
</section>
|
||
</section>
|
||
<section id="acknowledgements">
|
||
<h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2>
|
||
<ul class="simple">
|
||
<li>Theo de Raadt, for making the suggestion to Guido van Rossum that we
|
||
seriously consider defaulting to a cryptographically secure random number
|
||
generator</li>
|
||
<li>Serhiy Storchaka, Terry Reedy, Petr Viktorin, and anyone else in the
|
||
python-ideas threads that suggested the approach of transparently switching
|
||
to the <code class="docutils literal notranslate"><span class="pre">random.Random</span></code> implementation when any of the functions that only
|
||
make sense for a deterministic RNG are called</li>
|
||
<li>Nathaniel Smith for providing the reference on practical attacks against
|
||
PHP’s random number generator when used to generate password reset tokens</li>
|
||
<li>Donald Stufft for pursuing additional discussions with network security
|
||
experts that suggested the introduction of a userspace CSPRNG would mean
|
||
additional complexity for insufficient gain relative to just using the
|
||
system RNG directly</li>
|
||
<li>Paul Moore for eloquently making the case for the current level of security
|
||
fatigue in the Python ecosystem</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="breaches" role="doc-footnote">
|
||
<dt class="label" id="breaches">[<a href="#id2">1</a>]</dt>
|
||
<dd>Visualization of data breaches involving more than 30k records (each)
|
||
(<a class="reference external" href="http://www.informationisbeautiful.net/visualizations/worlds-biggest-data-breaches-hacks/">http://www.informationisbeautiful.net/visualizations/worlds-biggest-data-breaches-hacks/</a>)</aside>
|
||
<aside class="footnote brackets" id="uconnect" role="doc-footnote">
|
||
<dt class="label" id="uconnect">[<a href="#id3">2</a>]</dt>
|
||
<dd>Remote UConnect hack for Jeep Cherokee
|
||
(<a class="reference external" href="http://www.wired.com/2015/07/hackers-remotely-kill-jeep-highway/">http://www.wired.com/2015/07/hackers-remotely-kill-jeep-highway/</a>)</aside>
|
||
<aside class="footnote brackets" id="php" role="doc-footnote">
|
||
<dt class="label" id="php">[<a href="#id8">3</a>]</dt>
|
||
<dd>PRNG based attack against password reset tokens in PHP applications
|
||
(<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="search" role="doc-footnote">
|
||
<dt class="label" id="search">[4]</dt>
|
||
<dd>Search link for “python password generator”
|
||
(<a class="reference external" href="https://www.google.com.au/search?q=python+password+generator">https://www.google.com.au/search?q=python+password+generator</a>)</aside>
|
||
<aside class="footnote brackets" id="csprng" role="doc-footnote">
|
||
<dt class="label" id="csprng">[5]</dt>
|
||
<dd>python-ideas thread discussing using a userspace CSPRNG
|
||
(<a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/035886.html">https://mail.python.org/pipermail/python-ideas/2015-September/035886.html</a>)</aside>
|
||
<aside class="footnote brackets" id="draft" role="doc-footnote">
|
||
<dt class="label" id="draft">[<a href="#id9">6</a>]</dt>
|
||
<dd>Initial draft concept that eventually became this PEP
|
||
(<a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/036095.html">https://mail.python.org/pipermail/python-ideas/2015-September/036095.html</a>)</aside>
|
||
<aside class="footnote brackets" id="nocsprng" role="doc-footnote">
|
||
<dt class="label" id="nocsprng">[<a href="#id7">7</a>]</dt>
|
||
<dd>Safely generating random numbers
|
||
(<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>)</aside>
|
||
<aside class="footnote brackets" id="ieeetopten" role="doc-footnote">
|
||
<dt class="label" id="ieeetopten">[<a href="#id6">8</a>]</dt>
|
||
<dd>IEEE Spectrum 2015 Top Ten Programming Languages
|
||
(<a class="reference external" href="http://spectrum.ieee.org/computing/software/the-2015-top-ten-programming-languages">http://spectrum.ieee.org/computing/software/the-2015-top-ten-programming-languages</a>)</aside>
|
||
<aside class="footnote brackets" id="owasptopten" role="doc-footnote">
|
||
<dt class="label" id="owasptopten">[<a href="#id5">9</a>]</dt>
|
||
<dd>OWASP Top Ten Web Security Issues for 2013
|
||
(<a class="reference external" href="https://www.owasp.org/index.php/OWASP_Top_Ten_Project#tab=OWASP_Top_10_for_2013">https://www.owasp.org/index.php/OWASP_Top_Ten_Project#tab=OWASP_Top_10_for_2013</a>)</aside>
|
||
<aside class="footnote brackets" id="print" role="doc-footnote">
|
||
<dt class="label" id="print">[<a href="#id1">10</a>]</dt>
|
||
<dd>Stack Overflow answer for missing parentheses in call to print
|
||
(<a class="reference external" href="http://stackoverflow.com/questions/25445439/what-does-syntaxerror-missing-parentheses-in-call-to-print-mean-in-python/25445440#25445440">http://stackoverflow.com/questions/25445439/what-does-syntaxerror-missing-parentheses-in-call-to-print-mean-in-python/25445440#25445440</a>)</aside>
|
||
<aside class="footnote brackets" id="bcrypt" role="doc-footnote">
|
||
<dt class="label" id="bcrypt">[<a href="#id4">11</a>]</dt>
|
||
<dd>Bypassing bcrypt through an insecure data cache
|
||
(<a class="reference external" href="http://arstechnica.com/security/2015/09/once-seen-as-bulletproof-11-million-ashley-madison-passwords-already-cracked/">http://arstechnica.com/security/2015/09/once-seen-as-bulletproof-11-million-ashley-madison-passwords-already-cracked/</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-0504.rst">https://github.com/python/peps/blob/main/peps/pep-0504.rst</a></p>
|
||
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0504.rst">2023-10-11 12:05:51 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="#pep-withdrawal">PEP Withdrawal</a></li>
|
||
<li><a class="reference internal" href="#proposal">Proposal</a><ul>
|
||
<li><a class="reference internal" href="#warning-on-implicit-opt-in">Warning on implicit opt-in</a></li>
|
||
<li><a class="reference internal" href="#performance-impact">Performance impact</a></li>
|
||
<li><a class="reference internal" href="#documentation-changes">Documentation changes</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a></li>
|
||
<li><a class="reference internal" href="#discussion">Discussion</a><ul>
|
||
<li><a class="reference internal" href="#why-ensure-repeatable-over-ensure-deterministic">Why “ensure_repeatable” over “ensure_deterministic”?</a></li>
|
||
<li><a class="reference internal" href="#only-changing-the-default-for-python-3-6">Only changing the default for Python 3.6+</a></li>
|
||
<li><a class="reference internal" href="#keeping-the-module-level-functions">Keeping the module level functions</a></li>
|
||
<li><a class="reference internal" href="#warning-when-implicitly-opting-in-to-the-deterministic-rng">Warning when implicitly opting in to the deterministic RNG</a></li>
|
||
<li><a class="reference internal" href="#avoiding-the-introduction-of-a-userspace-csprng">Avoiding the introduction of a userspace CSPRNG</a></li>
|
||
<li><a class="reference internal" href="#isn-t-the-deterministic-prng-secure-enough">Isn’t the deterministic PRNG “secure enough”?</a></li>
|
||
<li><a class="reference internal" href="#security-fatigue-in-the-python-ecosystem">Security fatigue in the Python ecosystem</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</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-0504.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> |