<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang=""> <head> <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>django.contrib.auth.hashers — Django 1.11.20 documentation</title> <link rel="stylesheet" href="../../../../_static/default.css" type="text/css" /> <link rel="stylesheet" href="../../../../_static/pygments.css" type="text/css" /> <script type="text/javascript" id="documentation_options" data-url_root="../../../../" src="../../../../_static/documentation_options.js"></script> <script type="text/javascript" src="../../../../_static/jquery.js"></script> <script type="text/javascript" src="../../../../_static/underscore.js"></script> <script type="text/javascript" src="../../../../_static/doctools.js"></script> <script type="text/javascript" src="../../../../_static/language_data.js"></script> <link rel="index" title="Index" href="../../../../genindex.html" /> <link rel="search" title="Search" href="../../../../search.html" /> <script type="text/javascript" src="../../../../templatebuiltins.js"></script> <script type="text/javascript"> (function($) { if (!django_template_builtins) { // templatebuiltins.js missing, do nothing. return; } $(document).ready(function() { // Hyperlink Django template tags and filters var base = "../../../../ref/templates/builtins.html"; if (base == "#") { // Special case for builtins.html itself base = ""; } // Tags are keywords, class '.k' $("div.highlight\\-html\\+django span.k").each(function(i, elem) { var tagname = $(elem).text(); if ($.inArray(tagname, django_template_builtins.ttags) != -1) { var fragment = tagname.replace(/_/, '-'); $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>"); } }); // Filters are functions, class '.nf' $("div.highlight\\-html\\+django span.nf").each(function(i, elem) { var filtername = $(elem).text(); if ($.inArray(filtername, django_template_builtins.tfilters) != -1) { var fragment = filtername.replace(/_/, '-'); $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>"); } }); }); })(jQuery); </script> </head><body> <div class="document"> <div id="custom-doc" class="yui-t6"> <div id="hd"> <h1><a href="../../../../index.html">Django 1.11.20 documentation</a></h1> <div id="global-nav"> <a title="Home page" href="../../../../index.html">Home</a> | <a title="Table of contents" href="../../../../contents.html">Table of contents</a> | <a title="Global index" href="../../../../genindex.html">Index</a> | <a title="Module index" href="../../../../py-modindex.html">Modules</a> </div> <div class="nav"> <a href="../../../index.html" title="Module code" accesskey="U">up</a></div> </div> <div id="bd"> <div id="yui-main"> <div class="yui-b"> <div class="yui-g" id="_modules-django-contrib-auth-hashers"> <h1>Source code for django.contrib.auth.hashers</h1><div class="highlight"><pre> <span></span><span class="kn">from</span> <span class="nn">__future__</span> <span class="k">import</span> <span class="n">unicode_literals</span> <span class="kn">import</span> <span class="nn">base64</span> <span class="kn">import</span> <span class="nn">binascii</span> <span class="kn">import</span> <span class="nn">hashlib</span> <span class="kn">import</span> <span class="nn">importlib</span> <span class="kn">import</span> <span class="nn">warnings</span> <span class="kn">from</span> <span class="nn">collections</span> <span class="k">import</span> <span class="n">OrderedDict</span> <span class="kn">from</span> <span class="nn">django.conf</span> <span class="k">import</span> <span class="n">settings</span> <span class="kn">from</span> <span class="nn">django.core.exceptions</span> <span class="k">import</span> <span class="n">ImproperlyConfigured</span> <span class="kn">from</span> <span class="nn">django.core.signals</span> <span class="k">import</span> <span class="n">setting_changed</span> <span class="kn">from</span> <span class="nn">django.dispatch</span> <span class="k">import</span> <span class="n">receiver</span> <span class="kn">from</span> <span class="nn">django.utils</span> <span class="k">import</span> <span class="n">lru_cache</span> <span class="kn">from</span> <span class="nn">django.utils.crypto</span> <span class="k">import</span> <span class="p">(</span> <span class="n">constant_time_compare</span><span class="p">,</span> <span class="n">get_random_string</span><span class="p">,</span> <span class="n">pbkdf2</span><span class="p">,</span> <span class="p">)</span> <span class="kn">from</span> <span class="nn">django.utils.encoding</span> <span class="k">import</span> <span class="n">force_bytes</span><span class="p">,</span> <span class="n">force_str</span><span class="p">,</span> <span class="n">force_text</span> <span class="kn">from</span> <span class="nn">django.utils.module_loading</span> <span class="k">import</span> <span class="n">import_string</span> <span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="k">import</span> <span class="n">ugettext_noop</span> <span class="k">as</span> <span class="n">_</span> <span class="n">UNUSABLE_PASSWORD_PREFIX</span> <span class="o">=</span> <span class="s1">'!'</span> <span class="c1"># This will never be a valid encoded hash</span> <span class="n">UNUSABLE_PASSWORD_SUFFIX_LENGTH</span> <span class="o">=</span> <span class="mi">40</span> <span class="c1"># number of random chars to add after UNUSABLE_PASSWORD_PREFIX</span> <div class="viewcode-block" id="is_password_usable"><a class="viewcode-back" href="../../../../topics/auth/passwords.html#django.contrib.auth.hashers.is_password_usable">[docs]</a><span class="k">def</span> <span class="nf">is_password_usable</span><span class="p">(</span><span class="n">encoded</span><span class="p">):</span> <span class="k">if</span> <span class="n">encoded</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">encoded</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">UNUSABLE_PASSWORD_PREFIX</span><span class="p">):</span> <span class="k">return</span> <span class="kc">False</span> <span class="k">try</span><span class="p">:</span> <span class="n">identify_hasher</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">return</span> <span class="kc">False</span> <span class="k">return</span> <span class="kc">True</span></div> <div class="viewcode-block" id="check_password"><a class="viewcode-back" href="../../../../topics/auth/passwords.html#django.contrib.auth.hashers.check_password">[docs]</a><span class="k">def</span> <span class="nf">check_password</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">,</span> <span class="n">setter</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">preferred</span><span class="o">=</span><span class="s1">'default'</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Returns a boolean of whether the raw password matches the three</span> <span class="sd"> part encoded digest.</span> <span class="sd"> If setter is specified, it'll be called when you need to</span> <span class="sd"> regenerate the password.</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">password</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">is_password_usable</span><span class="p">(</span><span class="n">encoded</span><span class="p">):</span> <span class="k">return</span> <span class="kc">False</span> <span class="n">preferred</span> <span class="o">=</span> <span class="n">get_hasher</span><span class="p">(</span><span class="n">preferred</span><span class="p">)</span> <span class="n">hasher</span> <span class="o">=</span> <span class="n">identify_hasher</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span> <span class="n">hasher_changed</span> <span class="o">=</span> <span class="n">hasher</span><span class="o">.</span><span class="n">algorithm</span> <span class="o">!=</span> <span class="n">preferred</span><span class="o">.</span><span class="n">algorithm</span> <span class="n">must_update</span> <span class="o">=</span> <span class="n">hasher_changed</span> <span class="ow">or</span> <span class="n">preferred</span><span class="o">.</span><span class="n">must_update</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span> <span class="n">is_correct</span> <span class="o">=</span> <span class="n">hasher</span><span class="o">.</span><span class="n">verify</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">)</span> <span class="c1"># If the hasher didn't change (we don't protect against enumeration if it</span> <span class="c1"># does) and the password should get updated, try to close the timing gap</span> <span class="c1"># between the work factor of the current encoded password and the default</span> <span class="c1"># work factor.</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">is_correct</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">hasher_changed</span> <span class="ow">and</span> <span class="n">must_update</span><span class="p">:</span> <span class="n">hasher</span><span class="o">.</span><span class="n">harden_runtime</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">)</span> <span class="k">if</span> <span class="n">setter</span> <span class="ow">and</span> <span class="n">is_correct</span> <span class="ow">and</span> <span class="n">must_update</span><span class="p">:</span> <span class="n">setter</span><span class="p">(</span><span class="n">password</span><span class="p">)</span> <span class="k">return</span> <span class="n">is_correct</span></div> <div class="viewcode-block" id="make_password"><a class="viewcode-back" href="../../../../topics/auth/passwords.html#django.contrib.auth.hashers.make_password">[docs]</a><span class="k">def</span> <span class="nf">make_password</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">hasher</span><span class="o">=</span><span class="s1">'default'</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Turn a plain-text password into a hash for database storage</span> <span class="sd"> Same as encode() but generates a new random salt.</span> <span class="sd"> If password is None then a concatenation of</span> <span class="sd"> UNUSABLE_PASSWORD_PREFIX and a random string will be returned</span> <span class="sd"> which disallows logins. Additional random string reduces chances</span> <span class="sd"> of gaining access to staff or superuser accounts.</span> <span class="sd"> See ticket #20079 for more info.</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">password</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="k">return</span> <span class="n">UNUSABLE_PASSWORD_PREFIX</span> <span class="o">+</span> <span class="n">get_random_string</span><span class="p">(</span><span class="n">UNUSABLE_PASSWORD_SUFFIX_LENGTH</span><span class="p">)</span> <span class="n">hasher</span> <span class="o">=</span> <span class="n">get_hasher</span><span class="p">(</span><span class="n">hasher</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">salt</span><span class="p">:</span> <span class="n">salt</span> <span class="o">=</span> <span class="n">hasher</span><span class="o">.</span><span class="n">salt</span><span class="p">()</span> <span class="k">return</span> <span class="n">hasher</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">)</span></div> <span class="nd">@lru_cache</span><span class="o">.</span><span class="n">lru_cache</span><span class="p">()</span> <span class="k">def</span> <span class="nf">get_hashers</span><span class="p">():</span> <span class="n">hashers</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">hasher_path</span> <span class="ow">in</span> <span class="n">settings</span><span class="o">.</span><span class="n">PASSWORD_HASHERS</span><span class="p">:</span> <span class="n">hasher_cls</span> <span class="o">=</span> <span class="n">import_string</span><span class="p">(</span><span class="n">hasher_path</span><span class="p">)</span> <span class="n">hasher</span> <span class="o">=</span> <span class="n">hasher_cls</span><span class="p">()</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">hasher</span><span class="p">,</span> <span class="s1">'algorithm'</span><span class="p">):</span> <span class="k">raise</span> <span class="n">ImproperlyConfigured</span><span class="p">(</span><span class="s2">"hasher doesn't specify an "</span> <span class="s2">"algorithm name: </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="n">hasher_path</span><span class="p">)</span> <span class="n">hashers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">hasher</span><span class="p">)</span> <span class="k">return</span> <span class="n">hashers</span> <span class="nd">@lru_cache</span><span class="o">.</span><span class="n">lru_cache</span><span class="p">()</span> <span class="k">def</span> <span class="nf">get_hashers_by_algorithm</span><span class="p">():</span> <span class="k">return</span> <span class="p">{</span><span class="n">hasher</span><span class="o">.</span><span class="n">algorithm</span><span class="p">:</span> <span class="n">hasher</span> <span class="k">for</span> <span class="n">hasher</span> <span class="ow">in</span> <span class="n">get_hashers</span><span class="p">()}</span> <span class="nd">@receiver</span><span class="p">(</span><span class="n">setting_changed</span><span class="p">)</span> <span class="k">def</span> <span class="nf">reset_hashers</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">):</span> <span class="k">if</span> <span class="n">kwargs</span><span class="p">[</span><span class="s1">'setting'</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'PASSWORD_HASHERS'</span><span class="p">:</span> <span class="n">get_hashers</span><span class="o">.</span><span class="n">cache_clear</span><span class="p">()</span> <span class="n">get_hashers_by_algorithm</span><span class="o">.</span><span class="n">cache_clear</span><span class="p">()</span> <span class="k">def</span> <span class="nf">get_hasher</span><span class="p">(</span><span class="n">algorithm</span><span class="o">=</span><span class="s1">'default'</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Returns an instance of a loaded password hasher.</span> <span class="sd"> If algorithm is 'default', the default hasher will be returned.</span> <span class="sd"> This function will also lazy import hashers specified in your</span> <span class="sd"> settings file if needed.</span> <span class="sd"> """</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">algorithm</span><span class="p">,</span> <span class="s1">'algorithm'</span><span class="p">):</span> <span class="k">return</span> <span class="n">algorithm</span> <span class="k">elif</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="s1">'default'</span><span class="p">:</span> <span class="k">return</span> <span class="n">get_hashers</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="k">else</span><span class="p">:</span> <span class="n">hashers</span> <span class="o">=</span> <span class="n">get_hashers_by_algorithm</span><span class="p">()</span> <span class="k">try</span><span class="p">:</span> <span class="k">return</span> <span class="n">hashers</span><span class="p">[</span><span class="n">algorithm</span><span class="p">]</span> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Unknown password hashing algorithm '</span><span class="si">%s</span><span class="s2">'. "</span> <span class="s2">"Did you specify it in the PASSWORD_HASHERS "</span> <span class="s2">"setting?"</span> <span class="o">%</span> <span class="n">algorithm</span><span class="p">)</span> <span class="k">def</span> <span class="nf">identify_hasher</span><span class="p">(</span><span class="n">encoded</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Returns an instance of a loaded password hasher.</span> <span class="sd"> Identifies hasher algorithm by examining encoded hash, and calls</span> <span class="sd"> get_hasher() to return hasher. Raises ValueError if</span> <span class="sd"> algorithm cannot be identified, or if hasher is not loaded.</span> <span class="sd"> """</span> <span class="c1"># Ancient versions of Django created plain MD5 passwords and accepted</span> <span class="c1"># MD5 passwords with an empty salt.</span> <span class="k">if</span> <span class="p">((</span><span class="nb">len</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span> <span class="o">==</span> <span class="mi">32</span> <span class="ow">and</span> <span class="s1">'$'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">encoded</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span> <span class="o">==</span> <span class="mi">37</span> <span class="ow">and</span> <span class="n">encoded</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">'md5$$'</span><span class="p">))):</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="s1">'unsalted_md5'</span> <span class="c1"># Ancient versions of Django accepted SHA1 passwords with an empty salt.</span> <span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span> <span class="o">==</span> <span class="mi">46</span> <span class="ow">and</span> <span class="n">encoded</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">'sha1$$'</span><span class="p">):</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="s1">'unsalted_sha1'</span> <span class="k">else</span><span class="p">:</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">1</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="k">return</span> <span class="n">get_hasher</span><span class="p">(</span><span class="n">algorithm</span><span class="p">)</span> <span class="k">def</span> <span class="nf">mask_hash</span><span class="p">(</span><span class="nb">hash</span><span class="p">,</span> <span class="n">show</span><span class="o">=</span><span class="mi">6</span><span class="p">,</span> <span class="n">char</span><span class="o">=</span><span class="s2">"*"</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Returns the given hash, with only the first ``show`` number shown. The</span> <span class="sd"> rest are masked with ``char`` for security reasons.</span> <span class="sd"> """</span> <span class="n">masked</span> <span class="o">=</span> <span class="nb">hash</span><span class="p">[:</span><span class="n">show</span><span class="p">]</span> <span class="n">masked</span> <span class="o">+=</span> <span class="n">char</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="nb">hash</span><span class="p">[</span><span class="n">show</span><span class="p">:])</span> <span class="k">return</span> <span class="n">masked</span> <span class="k">class</span> <span class="nc">BasePasswordHasher</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Abstract base class for password hashers</span> <span class="sd"> When creating your own hasher, you need to override algorithm,</span> <span class="sd"> verify(), encode() and safe_summary().</span> <span class="sd"> PasswordHasher objects are immutable.</span> <span class="sd"> """</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="kc">None</span> <span class="n">library</span> <span class="o">=</span> <span class="kc">None</span> <span class="k">def</span> <span class="nf">_load_library</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">library</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">library</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">)):</span> <span class="n">name</span><span class="p">,</span> <span class="n">mod_path</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">library</span> <span class="k">else</span><span class="p">:</span> <span class="n">mod_path</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">library</span> <span class="k">try</span><span class="p">:</span> <span class="n">module</span> <span class="o">=</span> <span class="n">importlib</span><span class="o">.</span><span class="n">import_module</span><span class="p">(</span><span class="n">mod_path</span><span class="p">)</span> <span class="k">except</span> <span class="ne">ImportError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Couldn't load </span><span class="si">%r</span><span class="s2"> algorithm library: </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="n">e</span><span class="p">))</span> <span class="k">return</span> <span class="n">module</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Hasher </span><span class="si">%r</span><span class="s2"> doesn't specify a library attribute"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">)</span> <span class="k">def</span> <span class="nf">salt</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Generates a cryptographically secure nonce salt in ASCII</span> <span class="sd"> """</span> <span class="k">return</span> <span class="n">get_random_string</span><span class="p">()</span> <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Checks if the given password is correct</span> <span class="sd"> """</span> <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s1">'subclasses of BasePasswordHasher must provide a verify() method'</span><span class="p">)</span> <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Creates an encoded database value</span> <span class="sd"> The result is normally formatted as "algorithm$salt$hash" and</span> <span class="sd"> must be fewer than 128 characters.</span> <span class="sd"> """</span> <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s1">'subclasses of BasePasswordHasher must provide an encode() method'</span><span class="p">)</span> <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Returns a summary of safe values</span> <span class="sd"> The result is a dictionary and will be used where the password field</span> <span class="sd"> must be displayed to construct a safe representation of the password.</span> <span class="sd"> """</span> <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s1">'subclasses of BasePasswordHasher must provide a safe_summary() method'</span><span class="p">)</span> <span class="k">def</span> <span class="nf">must_update</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="k">return</span> <span class="kc">False</span> <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Bridge the runtime gap between the work factor supplied in `encoded`</span> <span class="sd"> and the work factor suggested by this hasher.</span> <span class="sd"> Taking PBKDF2 as an example, if `encoded` contains 20000 iterations and</span> <span class="sd"> `self.iterations` is 30000, this method should run password through</span> <span class="sd"> another 10000 iterations of PBKDF2. Similar approaches should exist</span> <span class="sd"> for any hasher that has a work factor. If not, this method should be</span> <span class="sd"> defined as a no-op to silence the warning.</span> <span class="sd"> """</span> <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s1">'subclasses of BasePasswordHasher should provide a harden_runtime() method'</span><span class="p">)</span> <span class="k">class</span> <span class="nc">PBKDF2PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Secure password hashing using the PBKDF2 algorithm (recommended)</span> <span class="sd"> Configured to use PBKDF2 + HMAC + SHA256.</span> <span class="sd"> The result is a 64 byte binary string. Iterations may be changed</span> <span class="sd"> safely but you must rename the algorithm if you change SHA256.</span> <span class="sd"> """</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">"pbkdf2_sha256"</span> <span class="n">iterations</span> <span class="o">=</span> <span class="mi">36000</span> <span class="n">digest</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha256</span> <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">iterations</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="k">assert</span> <span class="n">password</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">assert</span> <span class="n">salt</span> <span class="ow">and</span> <span class="s1">'$'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">salt</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">iterations</span><span class="p">:</span> <span class="n">iterations</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">iterations</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">pbkdf2</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">iterations</span><span class="p">,</span> <span class="n">digest</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">digest</span><span class="p">)</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">base64</span><span class="o">.</span><span class="n">b64encode</span><span class="p">(</span><span class="nb">hash</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="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">return</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">$</span><span class="si">%d</span><span class="s2">$</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">,</span> <span class="n">iterations</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span><span class="p">)</span> <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">iterations</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="n">encoded_2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">iterations</span><span class="p">))</span> <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">encoded_2</span><span class="p">)</span> <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">iterations</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'algorithm'</span><span class="p">),</span> <span class="n">algorithm</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'iterations'</span><span class="p">),</span> <span class="n">iterations</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'salt'</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">salt</span><span class="p">)),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'hash'</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="nb">hash</span><span class="p">)),</span> <span class="p">])</span> <span class="k">def</span> <span class="nf">must_update</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">iterations</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">iterations</span><span class="p">)</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">iterations</span> <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">iterations</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="n">extra_iterations</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">iterations</span> <span class="o">-</span> <span class="nb">int</span><span class="p">(</span><span class="n">iterations</span><span class="p">)</span> <span class="k">if</span> <span class="n">extra_iterations</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">extra_iterations</span><span class="p">)</span> <span class="k">class</span> <span class="nc">PBKDF2SHA1PasswordHasher</span><span class="p">(</span><span class="n">PBKDF2PasswordHasher</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Alternate PBKDF2 hasher which uses SHA1, the default PRF</span> <span class="sd"> recommended by PKCS #5. This is compatible with other</span> <span class="sd"> implementations of PBKDF2, such as openssl's</span> <span class="sd"> PKCS5_PBKDF2_HMAC_SHA1().</span> <span class="sd"> """</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">"pbkdf2_sha1"</span> <span class="n">digest</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha1</span> <span class="k">class</span> <span class="nc">Argon2PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Secure password hashing using the argon2 algorithm.</span> <span class="sd"> This is the winner of the Password Hashing Competition 2013-2015</span> <span class="sd"> (https://password-hashing.net). It requires the argon2-cffi library which</span> <span class="sd"> depends on native C code and might cause portability issues.</span> <span class="sd"> """</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="s1">'argon2'</span> <span class="n">library</span> <span class="o">=</span> <span class="s1">'argon2'</span> <span class="n">time_cost</span> <span class="o">=</span> <span class="mi">2</span> <span class="n">memory_cost</span> <span class="o">=</span> <span class="mi">512</span> <span class="n">parallelism</span> <span class="o">=</span> <span class="mi">2</span> <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span> <span class="n">argon2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span> <span class="n">data</span> <span class="o">=</span> <span class="n">argon2</span><span class="o">.</span><span class="n">low_level</span><span class="o">.</span><span class="n">hash_secret</span><span class="p">(</span> <span class="n">force_bytes</span><span class="p">(</span><span class="n">password</span><span class="p">),</span> <span class="n">force_bytes</span><span class="p">(</span><span class="n">salt</span><span class="p">),</span> <span class="n">time_cost</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">time_cost</span><span class="p">,</span> <span class="n">memory_cost</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">memory_cost</span><span class="p">,</span> <span class="n">parallelism</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">parallelism</span><span class="p">,</span> <span class="n">hash_len</span><span class="o">=</span><span class="n">argon2</span><span class="o">.</span><span class="n">DEFAULT_HASH_LENGTH</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="n">argon2</span><span class="o">.</span><span class="n">low_level</span><span class="o">.</span><span class="n">Type</span><span class="o">.</span><span class="n">I</span><span class="p">,</span> <span class="p">)</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="o">+</span> <span class="n">data</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="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">argon2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">rest</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="k">try</span><span class="p">:</span> <span class="k">return</span> <span class="n">argon2</span><span class="o">.</span><span class="n">low_level</span><span class="o">.</span><span class="n">verify_secret</span><span class="p">(</span> <span class="n">force_bytes</span><span class="p">(</span><span class="s1">'$'</span> <span class="o">+</span> <span class="n">rest</span><span class="p">),</span> <span class="n">force_bytes</span><span class="p">(</span><span class="n">password</span><span class="p">),</span> <span class="nb">type</span><span class="o">=</span><span class="n">argon2</span><span class="o">.</span><span class="n">low_level</span><span class="o">.</span><span class="n">Type</span><span class="o">.</span><span class="n">I</span><span class="p">,</span> <span class="p">)</span> <span class="k">except</span> <span class="n">argon2</span><span class="o">.</span><span class="n">exceptions</span><span class="o">.</span><span class="n">VerificationError</span><span class="p">:</span> <span class="k">return</span> <span class="kc">False</span> <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="p">(</span><span class="n">algorithm</span><span class="p">,</span> <span class="n">variety</span><span class="p">,</span> <span class="n">version</span><span class="p">,</span> <span class="n">time_cost</span><span class="p">,</span> <span class="n">memory_cost</span><span class="p">,</span> <span class="n">parallelism</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_decode</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span> <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'algorithm'</span><span class="p">),</span> <span class="n">algorithm</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'variety'</span><span class="p">),</span> <span class="n">variety</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'version'</span><span class="p">),</span> <span class="n">version</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'memory cost'</span><span class="p">),</span> <span class="n">memory_cost</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'time cost'</span><span class="p">),</span> <span class="n">time_cost</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'parallelism'</span><span class="p">),</span> <span class="n">parallelism</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'salt'</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">salt</span><span class="p">)),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'hash'</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">data</span><span class="p">)),</span> <span class="p">])</span> <span class="k">def</span> <span class="nf">must_update</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="p">(</span><span class="n">algorithm</span><span class="p">,</span> <span class="n">variety</span><span class="p">,</span> <span class="n">version</span><span class="p">,</span> <span class="n">time_cost</span><span class="p">,</span> <span class="n">memory_cost</span><span class="p">,</span> <span class="n">parallelism</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_decode</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span> <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="n">argon2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span> <span class="k">return</span> <span class="p">(</span> <span class="n">argon2</span><span class="o">.</span><span class="n">low_level</span><span class="o">.</span><span class="n">ARGON2_VERSION</span> <span class="o">!=</span> <span class="n">version</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">time_cost</span> <span class="o">!=</span> <span class="n">time_cost</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory_cost</span> <span class="o">!=</span> <span class="n">memory_cost</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">parallelism</span> <span class="o">!=</span> <span class="n">parallelism</span> <span class="p">)</span> <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="c1"># The runtime for Argon2 is too complicated to implement a sensible</span> <span class="c1"># hardening algorithm.</span> <span class="k">pass</span> <span class="k">def</span> <span class="nf">_decode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Split an encoded hash and return: (</span> <span class="sd"> algorithm, variety, version, time_cost, memory_cost,</span> <span class="sd"> parallelism, salt, data,</span> <span class="sd"> ).</span> <span class="sd"> """</span> <span class="n">bits</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">)</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">bits</span><span class="p">)</span> <span class="o">==</span> <span class="mi">5</span><span class="p">:</span> <span class="c1"># Argon2 < 1.3</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">variety</span><span class="p">,</span> <span class="n">raw_params</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">bits</span> <span class="n">version</span> <span class="o">=</span> <span class="mh">0x10</span> <span class="k">else</span><span class="p">:</span> <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">bits</span><span class="p">)</span> <span class="o">==</span> <span class="mi">6</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">variety</span><span class="p">,</span> <span class="n">raw_version</span><span class="p">,</span> <span class="n">raw_params</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">bits</span> <span class="k">assert</span> <span class="n">raw_version</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">'v='</span><span class="p">)</span> <span class="n">version</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">raw_version</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="s1">'v='</span><span class="p">):])</span> <span class="n">params</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">bit</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'='</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">for</span> <span class="n">bit</span> <span class="ow">in</span> <span class="n">raw_params</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">','</span><span class="p">))</span> <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">params</span><span class="p">)</span> <span class="o">==</span> <span class="mi">3</span> <span class="ow">and</span> <span class="nb">all</span><span class="p">(</span><span class="n">x</span> <span class="ow">in</span> <span class="n">params</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'t'</span><span class="p">,</span> <span class="s1">'m'</span><span class="p">,</span> <span class="s1">'p'</span><span class="p">))</span> <span class="n">time_cost</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">params</span><span class="p">[</span><span class="s1">'t'</span><span class="p">])</span> <span class="n">memory_cost</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">params</span><span class="p">[</span><span class="s1">'m'</span><span class="p">])</span> <span class="n">parallelism</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">params</span><span class="p">[</span><span class="s1">'p'</span><span class="p">])</span> <span class="k">return</span> <span class="p">(</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">variety</span><span class="p">,</span> <span class="n">version</span><span class="p">,</span> <span class="n">time_cost</span><span class="p">,</span> <span class="n">memory_cost</span><span class="p">,</span> <span class="n">parallelism</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="p">)</span> <span class="k">class</span> <span class="nc">BCryptSHA256PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Secure password hashing using the bcrypt algorithm (recommended)</span> <span class="sd"> This is considered by many to be the most secure algorithm but you</span> <span class="sd"> must first install the bcrypt library. Please be warned that</span> <span class="sd"> this library depends on native C code and might cause portability</span> <span class="sd"> issues.</span> <span class="sd"> """</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">"bcrypt_sha256"</span> <span class="n">digest</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha256</span> <span class="n">library</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"bcrypt"</span><span class="p">,</span> <span class="s2">"bcrypt"</span><span class="p">)</span> <span class="n">rounds</span> <span class="o">=</span> <span class="mi">12</span> <span class="k">def</span> <span class="nf">salt</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">bcrypt</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span> <span class="k">return</span> <span class="n">bcrypt</span><span class="o">.</span><span class="n">gensalt</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rounds</span><span class="p">)</span> <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span> <span class="n">bcrypt</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span> <span class="c1"># Hash the password prior to using bcrypt to prevent password</span> <span class="c1"># truncation as described in #20138.</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">digest</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># Use binascii.hexlify() because a hex encoded bytestring is</span> <span class="c1"># Unicode on Python 3.</span> <span class="n">password</span> <span class="o">=</span> <span class="n">binascii</span><span class="o">.</span><span class="n">hexlify</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">digest</span><span class="p">(</span><span class="n">force_bytes</span><span class="p">(</span><span class="n">password</span><span class="p">))</span><span class="o">.</span><span class="n">digest</span><span class="p">())</span> <span class="k">else</span><span class="p">:</span> <span class="n">password</span> <span class="o">=</span> <span class="n">force_bytes</span><span class="p">(</span><span class="n">password</span><span class="p">)</span> <span class="n">data</span> <span class="o">=</span> <span class="n">bcrypt</span><span class="o">.</span><span class="n">hashpw</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">)</span> <span class="k">return</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">,</span> <span class="n">force_text</span><span class="p">(</span><span class="n">data</span><span class="p">))</span> <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="n">encoded_2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">force_bytes</span><span class="p">(</span><span class="n">data</span><span class="p">))</span> <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">encoded_2</span><span class="p">)</span> <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">empty</span><span class="p">,</span> <span class="n">algostr</span><span class="p">,</span> <span class="n">work_factor</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span> <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="n">salt</span><span class="p">,</span> <span class="n">checksum</span> <span class="o">=</span> <span class="n">data</span><span class="p">[:</span><span class="mi">22</span><span class="p">],</span> <span class="n">data</span><span class="p">[</span><span class="mi">22</span><span class="p">:]</span> <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'algorithm'</span><span class="p">),</span> <span class="n">algorithm</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'work factor'</span><span class="p">),</span> <span class="n">work_factor</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'salt'</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">salt</span><span class="p">)),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'checksum'</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">checksum</span><span class="p">)),</span> <span class="p">])</span> <span class="k">def</span> <span class="nf">must_update</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">empty</span><span class="p">,</span> <span class="n">algostr</span><span class="p">,</span> <span class="n">rounds</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span> <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">rounds</span><span class="p">)</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rounds</span> <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">_</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="n">salt</span> <span class="o">=</span> <span class="n">data</span><span class="p">[:</span><span class="mi">29</span><span class="p">]</span> <span class="c1"># Length of the salt in bcrypt.</span> <span class="n">rounds</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">)[</span><span class="mi">2</span><span class="p">]</span> <span class="c1"># work factor is logarithmic, adding one doubles the load.</span> <span class="n">diff</span> <span class="o">=</span> <span class="mi">2</span><span class="o">**</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rounds</span> <span class="o">-</span> <span class="nb">int</span><span class="p">(</span><span class="n">rounds</span><span class="p">))</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">while</span> <span class="n">diff</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">force_bytes</span><span class="p">(</span><span class="n">salt</span><span class="p">))</span> <span class="n">diff</span> <span class="o">-=</span> <span class="mi">1</span> <span class="k">class</span> <span class="nc">BCryptPasswordHasher</span><span class="p">(</span><span class="n">BCryptSHA256PasswordHasher</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Secure password hashing using the bcrypt algorithm</span> <span class="sd"> This is considered by many to be the most secure algorithm but you</span> <span class="sd"> must first install the bcrypt library. Please be warned that</span> <span class="sd"> this library depends on native C code and might cause portability</span> <span class="sd"> issues.</span> <span class="sd"> This hasher does not first hash the password which means it is subject to</span> <span class="sd"> the 72 character bcrypt password truncation, most use cases should prefer</span> <span class="sd"> the BCryptSHA256PasswordHasher.</span> <span class="sd"> See: https://code.djangoproject.com/ticket/20138</span> <span class="sd"> """</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">"bcrypt"</span> <span class="n">digest</span> <span class="o">=</span> <span class="kc">None</span> <span class="k">class</span> <span class="nc">SHA1PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> The SHA1 password hashing algorithm (not recommended)</span> <span class="sd"> """</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">"sha1"</span> <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span> <span class="k">assert</span> <span class="n">password</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">assert</span> <span class="n">salt</span> <span class="ow">and</span> <span class="s1">'$'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">salt</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha1</span><span class="p">(</span><span class="n">force_bytes</span><span class="p">(</span><span class="n">salt</span> <span class="o">+</span> <span class="n">password</span><span class="p">))</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span> <span class="k">return</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span><span class="p">)</span> <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="n">encoded_2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">)</span> <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">encoded_2</span><span class="p">)</span> <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'algorithm'</span><span class="p">),</span> <span class="n">algorithm</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'salt'</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">salt</span><span class="p">,</span> <span class="n">show</span><span class="o">=</span><span class="mi">2</span><span class="p">)),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'hash'</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="nb">hash</span><span class="p">)),</span> <span class="p">])</span> <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="k">pass</span> <span class="k">class</span> <span class="nc">MD5PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> The Salted MD5 password hashing algorithm (not recommended)</span> <span class="sd"> """</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">"md5"</span> <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span> <span class="k">assert</span> <span class="n">password</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">assert</span> <span class="n">salt</span> <span class="ow">and</span> <span class="s1">'$'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">salt</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">(</span><span class="n">force_bytes</span><span class="p">(</span><span class="n">salt</span> <span class="o">+</span> <span class="n">password</span><span class="p">))</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span> <span class="k">return</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span><span class="p">)</span> <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="n">encoded_2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">)</span> <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">encoded_2</span><span class="p">)</span> <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'algorithm'</span><span class="p">),</span> <span class="n">algorithm</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'salt'</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">salt</span><span class="p">,</span> <span class="n">show</span><span class="o">=</span><span class="mi">2</span><span class="p">)),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'hash'</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="nb">hash</span><span class="p">)),</span> <span class="p">])</span> <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="k">pass</span> <span class="k">class</span> <span class="nc">UnsaltedSHA1PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Very insecure algorithm that you should *never* use; stores SHA1 hashes</span> <span class="sd"> with an empty salt.</span> <span class="sd"> This class is implemented because Django used to accept such password</span> <span class="sd"> hashes. Some older Django installs still have these values lingering</span> <span class="sd"> around so we need to handle and upgrade them properly.</span> <span class="sd"> """</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">"unsalted_sha1"</span> <span class="k">def</span> <span class="nf">salt</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="s1">''</span> <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span> <span class="k">assert</span> <span class="n">salt</span> <span class="o">==</span> <span class="s1">''</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha1</span><span class="p">(</span><span class="n">force_bytes</span><span class="p">(</span><span class="n">password</span><span class="p">))</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span> <span class="k">return</span> <span class="s1">'sha1$$</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="nb">hash</span> <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">encoded_2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span> <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">encoded_2</span><span class="p">)</span> <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="k">assert</span> <span class="n">encoded</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">'sha1$$'</span><span class="p">)</span> <span class="nb">hash</span> <span class="o">=</span> <span class="n">encoded</span><span class="p">[</span><span class="mi">6</span><span class="p">:]</span> <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'algorithm'</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'hash'</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="nb">hash</span><span class="p">)),</span> <span class="p">])</span> <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="k">pass</span> <span class="k">class</span> <span class="nc">UnsaltedMD5PasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Incredibly insecure algorithm that you should *never* use; stores unsalted</span> <span class="sd"> MD5 hashes without the algorithm prefix, also accepts MD5 hashes with an</span> <span class="sd"> empty salt.</span> <span class="sd"> This class is implemented because Django used to store passwords this way</span> <span class="sd"> and to accept such password hashes. Some older Django installs still have</span> <span class="sd"> these values lingering around so we need to handle and upgrade them</span> <span class="sd"> properly.</span> <span class="sd"> """</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">"unsalted_md5"</span> <span class="k">def</span> <span class="nf">salt</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="s1">''</span> <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span> <span class="k">assert</span> <span class="n">salt</span> <span class="o">==</span> <span class="s1">''</span> <span class="k">return</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">(</span><span class="n">force_bytes</span><span class="p">(</span><span class="n">password</span><span class="p">))</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span> <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span> <span class="o">==</span> <span class="mi">37</span> <span class="ow">and</span> <span class="n">encoded</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">'md5$$'</span><span class="p">):</span> <span class="n">encoded</span> <span class="o">=</span> <span class="n">encoded</span><span class="p">[</span><span class="mi">5</span><span class="p">:]</span> <span class="n">encoded_2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span> <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">encoded_2</span><span class="p">)</span> <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'algorithm'</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'hash'</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">encoded</span><span class="p">,</span> <span class="n">show</span><span class="o">=</span><span class="mi">3</span><span class="p">)),</span> <span class="p">])</span> <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="k">pass</span> <span class="k">class</span> <span class="nc">CryptPasswordHasher</span><span class="p">(</span><span class="n">BasePasswordHasher</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Password hashing using UNIX crypt (not recommended)</span> <span class="sd"> The crypt module is not supported on all platforms.</span> <span class="sd"> """</span> <span class="n">algorithm</span> <span class="o">=</span> <span class="s2">"crypt"</span> <span class="n">library</span> <span class="o">=</span> <span class="s2">"crypt"</span> <span class="k">def</span> <span class="nf">salt</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="n">get_random_string</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">salt</span><span class="p">):</span> <span class="n">crypt</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span> <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">salt</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="n">data</span> <span class="o">=</span> <span class="n">crypt</span><span class="o">.</span><span class="n">crypt</span><span class="p">(</span><span class="n">force_str</span><span class="p">(</span><span class="n">password</span><span class="p">),</span> <span class="n">salt</span><span class="p">)</span> <span class="k">assert</span> <span class="n">data</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="c1"># A platform like OpenBSD with a dummy crypt module.</span> <span class="c1"># we don't need to store the salt, but Django used to do this</span> <span class="k">return</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">$</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span> <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">crypt</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_library</span><span class="p">()</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="k">return</span> <span class="n">constant_time_compare</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">crypt</span><span class="o">.</span><span class="n">crypt</span><span class="p">(</span><span class="n">force_str</span><span class="p">(</span><span class="n">password</span><span class="p">),</span> <span class="n">data</span><span class="p">))</span> <span class="k">def</span> <span class="nf">safe_summary</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">encoded</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'$'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="k">assert</span> <span class="n">algorithm</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">algorithm</span> <span class="k">return</span> <span class="n">OrderedDict</span><span class="p">([</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'algorithm'</span><span class="p">),</span> <span class="n">algorithm</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'salt'</span><span class="p">),</span> <span class="n">salt</span><span class="p">),</span> <span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'hash'</span><span class="p">),</span> <span class="n">mask_hash</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">show</span><span class="o">=</span><span class="mi">3</span><span class="p">)),</span> <span class="p">])</span> <span class="k">def</span> <span class="nf">harden_runtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">encoded</span><span class="p">):</span> <span class="k">pass</span> </pre></div> </div> </div> </div> <div class="yui-b" id="sidebar"> <div class="sphinxsidebar" role="navigation" aria-label="main navigation"> <div class="sphinxsidebarwrapper"> <div id="searchbox" style="display: none" role="search"> <h3>Quick search</h3> <div class="searchformwrapper"> <form class="search" action="../../../../search.html" method="get"> <input type="text" name="q" /> <input type="submit" value="Go" /> <input type="hidden" name="check_keywords" value="yes" /> <input type="hidden" name="area" value="default" /> </form> </div> </div> <script type="text/javascript">$('#searchbox').show(0);</script> </div> </div> <h3>Last update:</h3> <p class="topless">Feb 11, 2019</p> </div> </div> <div id="ft"> <div class="nav"> <a href="../../../index.html" title="Module code" accesskey="U">up</a></div> </div> </div> <div class="clearer"></div> </div> </body> </html>