Salt in PBKDF2 - Python
<p>I'm just learning about securing password while developing using MySQL and Python, following <a href="http://www.cyberciti.biz/python-tutorials/securely-hash-passwords-in-python/" rel="nofollow">this tutorial</a>.</p>

<p>It's my understanding that the userpassword is stored at the database hashed, and the salt is stored along side unencrypted, so that we can grab the hashed password and the salt, and rehash using the salt the inputted password, then compare the two.</p>

<p>Though, when using PBKDF2 (via the <code>passlib.hash.sha256_crypt()</code> function) I can't set my own salt, only its size. So how can I rehash the password using the same salt so I can compare both?</p>

<p>The <a href="https://pythonhosted.org/passlib/password_hash_api.html" rel="nofollow">Passlib Password Hash interface</a> either lets you set the salt <em>size</em>, <em>or</em> the <code>salt</code> value itself. From the <a href="https://pythonhosted.org/passlib/lib/passlib.hash.pbkdf2_digest.html#passlib.hash.pbkdf2_sha256" rel="nofollow">documentation on <code>pbkdf2_sha256</code></a>:</p>

<blockquote>
  <ul>
  <li><p><code>salt</code> (<em>bytes</em>) Optional salt bytes. If specified, the length must be between 0-1024 bytes. If not specified, a 16 byte salt will be autogenerated (this is recommended).</p></li>
  <li><p><code>salt_size</code> (<em>int</em>) â Optional number of bytes to use when autogenerating new salts. Defaults to 16 bytes, but can be any value between 0 and 1024.</p></li>
  </ul>
</blockquote>

<p>so you <em>can</em> set your own pre-generated salt:</p>

<pre><code>&gt;&gt;&gt; from passlib.hash import pbkdf2_sha256
&gt;&gt;&gt; pbkdf2_sha256.encrypt("password", rounds=200000, salt=b'spamhameggs')
'$pbkdf2-sha256$200000$c3BhbWhhbWVnZ3M$WL9OLVcb3f7HqHeNT./kCJeunydLCi4JykzEuAdewcI'
</code></pre>

<p>However, note that the salt is part of the returned string. The string contains not only the resulting hash, but also the algorithm, the number of rounds used <em>and</em> the salt used, delimited by <code>$</code>. The salt is <a href="https://pythonhosted.org/passlib/lib/passlib.utils.html#other" rel="nofollow">encoded to modified form of base64</a>. You can verify this by decoding the string <code>c3BhbWhhbWVnZ3M</code> again::</p>

<pre><code>&gt;&gt;&gt; from passlib.utils import ab64_decode
&gt;&gt;&gt; ab64_decode(b'c3BhbWhhbWVnZ3M')
b'spamhameggs'
</code></pre>

<p>See the <a href="https://pythonhosted.org/passlib/lib/passlib.hash.pbkdf2_digest.html#format-algorithm" rel="nofollow"><em>Format &amp; Algorithm</em></a> section for the <code>pbkdf2_sha256</code> docs.</p>

<p>So when you store the full string <code>pbkdf2_sha256</code> in the database, <em>everything to validate the string</em> is right there in the value, including the salt. Leaving generating a random salt is best left to that library as it'll use a secure method to generate one.</p>

python mysql python-3.x salt pbkdf2