Why is there a difference in format of encrypted passwords in Django
<p>I am using Django 1.97. The encrypted passwords are significantly different (in terms of the format).</p>

<p>Some passwords are of format $$$: </p>

<pre><code>pbkdf2_sha256$24000$61Rm3LxOPsCA$5kV2bzD32bpXoF6OO5YuyOlr5UHKUPlpNKwcNVn4Bt0=
</code></pre>

<p>While others are of format :</p>

<pre><code>!9rPYViI1oqrSMfkDCZSDeJxme4juD2niKcyvKdpB
</code></pre>

<p>Passwords are set either using <code>User.objects.create_user()</code> or <code>user.set_password()</code>. Is this difference an expected one ?</p>

<p>You'll be fine.  You just have some blank passwords in your database.  </p>

<p>Going back as far as <a href="https://github.com/django/django/blob/stable/0.95.x/django/contrib/auth/models.py#L13" rel="nofollow">V0.95</a>, django used the <code>$</code> separators for delimiting algorithm/salt/hash.  These days, django <a href="https://github.com/django/django/blob/master/django/contrib/auth/hashers.py#L136" rel="nofollow">pulls out the algorithm first</a> by looking at what is in front of the first <code>$</code> and then passes the whole lot to the hasher to decode.  This allows for a wider set of formats, including the one for PBKDF2 which adds an extra iterations parameter in this list (as per your first example).</p>

<p>However, it also recognises that some users may not be allowed to login and/or have no password.  This is encoded using the second format you've seen.  As you can see <a href="https://github.com/django/django/blob/master/django/contrib/auth/hashers.py#L71" rel="nofollow">here</a>:</p>

<blockquote>
  <p>If password is None then a concatenation of UNUSABLE_PASSWORD_PREFIX and a random string will be returned which disallows logins.</p>
</blockquote>

<p>You can also see that the random string is exactly 40 characters long - just like your second example.</p>

<p>In short, then, this is all as expected.</p>

python django