CINXE.COM
PEP 247 – API for Cryptographic Hash Functions | peps.python.org
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" content="light dark"> <title>PEP 247 – API for Cryptographic Hash Functions | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0247/"> <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 247 – API for Cryptographic Hash Functions | peps.python.org'> <meta property="og:description" content="There are several different modules available that implement cryptographic hashing algorithms such as MD5 or SHA. This document specifies a standard API for such algorithms, to make it easier to switch between different implementations."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0247/"> <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="There are several different modules available that implement cryptographic hashing algorithms such as MD5 or SHA. This document specifies a standard API for such algorithms, to make it easier to switch between different implementations."> <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 247</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 247 – API for Cryptographic Hash Functions</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">A.M. Kuchling <amk at amk.ca></dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd> <dt class="field-even">Created<span class="colon">:</span></dt> <dd class="field-even">23-Mar-2001</dd> <dt class="field-odd">Post-History<span class="colon">:</span></dt> <dd class="field-odd">20-Sep-2001</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="#specification">Specification</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#changes">Changes</a></li> <li><a class="reference internal" href="#acknowledgements">Acknowledgements</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>There are several different modules available that implement cryptographic hashing algorithms such as MD5 or SHA. This document specifies a standard API for such algorithms, to make it easier to switch between different implementations.</p> </section> <section id="specification"> <h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2> <p>All hashing modules should present the same interface. Additional methods or variables can be added, but those described in this document should always be present.</p> <p>Hash function modules define one function:</p> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">new([string])</span>            <span class="pre">(unkeyed</span> <span class="pre">hashes)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">new([key]</span> <span class="pre">,</span> <span class="pre">[string])</span>    <span class="pre">(keyed</span> <span class="pre">hashes)</span></code></div> </div> <blockquote> <div>Create a new hashing object and return it. The first form is for hashes that are unkeyed, such as MD5 or SHA. For keyed hashes such as HMAC, <em>key</em> is a required parameter containing a string giving the key to use. In both cases, the optional <em>string</em> parameter, if supplied, will be immediately hashed into the object’s starting state, as if <code class="docutils literal notranslate"><span class="pre">obj.update(string)</span></code> was called.<p>After creating a hashing object, arbitrary strings can be fed into the object using its <code class="docutils literal notranslate"><span class="pre">update()</span></code> method, and the hash value can be obtained at any time by calling the object’s <code class="docutils literal notranslate"><span class="pre">digest()</span></code> method.</p> <p>Arbitrary additional keyword arguments can be added to this function, but if they’re not supplied, sensible default values should be used. For example, <code class="docutils literal notranslate"><span class="pre">rounds</span></code> and <code class="docutils literal notranslate"><span class="pre">digest_size</span></code> keywords could be added for a hash function which supports a variable number of rounds and several different output sizes, and they should default to values believed to be secure.</p> </div></blockquote> <p>Hash function modules define one variable:</p> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">digest_size</span></code></div> </div> <blockquote> <div>An integer value; the size of the digest produced by the hashing objects created by this module, measured in bytes. You could also obtain this value by creating a sample object and accessing its <code class="docutils literal notranslate"><span class="pre">digest_size</span></code> attribute, but it can be convenient to have this value available from the module. Hashes with a variable output size will set this variable to <code class="docutils literal notranslate"><span class="pre">None</span></code>.</div></blockquote> <p>Hashing objects require a single attribute:</p> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">digest_size</span></code></div> </div> <blockquote> <div>This attribute is identical to the module-level <code class="docutils literal notranslate"><span class="pre">digest_size</span></code> variable, measuring the size of the digest produced by the hashing object, measured in bytes. If the hash has a variable output size, this output size must be chosen when the hashing object is created, and this attribute must contain the selected size. Therefore, <code class="docutils literal notranslate"><span class="pre">None</span></code> is <em>not</em> a legal value for this attribute.</div></blockquote> <p>Hashing objects require the following methods:</p> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">copy()</span></code></div> </div> <blockquote> <div>Return a separate copy of this hashing object. An update to this copy won’t affect the original object.</div></blockquote> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">digest()</span></code></div> </div> <blockquote> <div>Return the hash value of this hashing object as a string containing 8-bit data. The object is not altered in any way by this function; you can continue updating the object after calling this function.</div></blockquote> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">hexdigest()</span></code></div> </div> <blockquote> <div>Return the hash value of this hashing object as a string containing hexadecimal digits. Lowercase letters should be used for the digits <code class="docutils literal notranslate"><span class="pre">a</span></code> through <code class="docutils literal notranslate"><span class="pre">f</span></code>. Like the <code class="docutils literal notranslate"><span class="pre">.digest()</span></code> method, this method mustn’t alter the object.</div></blockquote> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">update(string)</span></code></div> </div> <blockquote> <div>Hash <em>string</em> into the current state of the hashing object. <code class="docutils literal notranslate"><span class="pre">update()</span></code> can be called any number of times during a hashing object’s lifetime.</div></blockquote> <p>Hashing modules can define additional module-level functions or object methods and still be compliant with this specification.</p> <p>Here’s an example, using a module named <code class="docutils literal notranslate"><span class="pre">MD5</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span><span class="w"> </span><span class="nn">Crypto.Hash</span><span class="w"> </span><span class="kn">import</span> <span class="n">MD5</span> <span class="gp">>>> </span><span class="n">m</span> <span class="o">=</span> <span class="n">MD5</span><span class="o">.</span><span class="n">new</span><span class="p">()</span> <span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">digest_size</span> <span class="go">16</span> <span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="s1">'abc'</span><span class="p">)</span> <span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">digest</span><span class="p">()</span> <span class="go">'\x90\x01P\x98<\xd2O\xb0\xd6\x96?}(\xe1\x7fr'</span> <span class="gp">>>> </span><span class="n">m</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span> <span class="go">'900150983cd24fb0d6963f7d28e17f72'</span> <span class="gp">>>> </span><span class="n">MD5</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'abc'</span><span class="p">)</span><span class="o">.</span><span class="n">digest</span><span class="p">()</span> <span class="go">'\x90\x01P\x98<\xd2O\xb0\xd6\x96?}(\xe1\x7fr'</span> </pre></div> </div> </section> <section id="rationale"> <h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2> <p>The digest size is measured in bytes, not bits, even though hash algorithm sizes are usually quoted in bits; MD5 is a 128-bit algorithm and not a 16-byte one, for example. This is because, in the sample code I looked at, the length in bytes is often needed (to seek ahead or behind in a file; to compute the length of an output string) while the length in bits is rarely used. Therefore, the burden will fall on the few people actually needing the size in bits, who will have to multiply <code class="docutils literal notranslate"><span class="pre">digest_size</span></code> by 8.</p> <p>It’s been suggested that the <code class="docutils literal notranslate"><span class="pre">update()</span></code> method would be better named <code class="docutils literal notranslate"><span class="pre">append()</span></code>. However, that method is really causing the current state of the hashing object to be updated, and <code class="docutils literal notranslate"><span class="pre">update()</span></code> is already used by the md5 and sha modules included with Python, so it seems simplest to leave the name <code class="docutils literal notranslate"><span class="pre">update()</span></code> alone.</p> <p>The order of the constructor’s arguments for keyed hashes was a sticky issue. It wasn’t clear whether the <em>key</em> should come first or second. It’s a required parameter, and the usual convention is to place required parameters first, but that also means that the <em>string</em> parameter moves from the first position to the second. It would be possible to get confused and pass a single argument to a keyed hash, thinking that you’re passing an initial string to an unkeyed hash, but it doesn’t seem worth making the interface for keyed hashes more obscure to avoid this potential error.</p> </section> <section id="changes"> <h2><a class="toc-backref" href="#changes" role="doc-backlink">Changes</a></h2> <p>2001-09-17: Renamed <code class="docutils literal notranslate"><span class="pre">clear()</span></code> to <code class="docutils literal notranslate"><span class="pre">reset()</span></code>; added <code class="docutils literal notranslate"><span class="pre">digest_size</span></code> attribute to objects; added <code class="docutils literal notranslate"><span class="pre">.hexdigest()</span></code> method.</p> <p>2001-09-20: Removed <code class="docutils literal notranslate"><span class="pre">reset()</span></code> method completely.</p> <p>2001-09-28: Set <code class="docutils literal notranslate"><span class="pre">digest_size</span></code> to <code class="docutils literal notranslate"><span class="pre">None</span></code> for variable-size hashes.</p> </section> <section id="acknowledgements"> <h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2> <p>Thanks to Aahz, Andrew Archibald, Rich Salz, Itamar Shtull-Trauring, and the readers of the python-crypto list for their comments on this PEP.</p> </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-0247.rst">https://github.com/python/peps/blob/main/peps/pep-0247.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0247.rst">2025-02-01 08:59:27 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#specification">Specification</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#changes">Changes</a></li> <li><a class="reference internal" href="#acknowledgements">Acknowledgements</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-0247.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>