Django password hashing different from python passlib pbkdf2 library

Using django admin, I have created a user

email: cuteemail@example.com
password: ccpass!ccpass

The hashed password stored in the database is

pbkdf2_sha256$260000$alGB1h2BRHwn83nz9fSJ3V$qippfbL8g59KPoDh+cIEh70TQCjuWeH8017VcLLpDIY=

All I know is that django is generating the password hash using PBKDF2 algorithm.

I need to run a pure python script that inside a part of it, it checks if a password is matching a hash. I have found a library passlib. I can provide the password and rounds. But where does the django salt come from?

from passlib.hash import pbkdf2_sha256

password = 'ccpass!ccpass'
db_hashed_password = 'pbkdf2_sha256$260000$alGB1h2BRHwn83nz9fSJ3V$qippfbL8g59KPoDh+cIEh70TQCjuWeH8017VcLLpDIY='

salt = db_hashed_password.split('$')[2].encode()
pbkdf2_sha256.hash(password, rounds=260000, salt=salt)

result:

$pbkdf2-sha256$260000$YWxHQjFoMkJSSHduODNuejlmU0ozVg$qippfbL8g59KPoDh.cIEh70TQCjuWeH8017VcLLpDIY

The resulted password hash apparently looks the same except minor differences.

The pbkdf2-sha256 has a dash instead of an underscore but this is not a problem. I can fix it.

The main problem is that I do receive a . instead of + in the actual hash part. How to fix this? Can I blindly replace all . with + ?

I also do not understand why is the calculated salt different from the original salt?

I followed the django source code.

Having a look at encode function and pbkdf2 function, I can write the following code:

import base64
import hashlib

myhash = base64.b64encode(hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 260000, None)).decode("ascii").strip()

print("%s$%d$%s$%s" % ('pbkdf2_sha256', 260000, salt.decode(), myhash))

It will give me the same result:

pbkdf2_sha256$260000$alGB1h2BRHwn83nz9fSJ3V$qippfbL8g59KPoDh+cIEh70TQCjuWeH8017VcLLpDIY=

.

Back to Top