Using django
admin, I have created a user
email: [email protected]
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))
This pure python code gave me the same result as django:
pbkdf2_sha256$260000$alGB1h2BRHwn83nz9fSJ3V$qippfbL8g59KPoDh+cIEh70TQCjuWeH8017VcLLpDIY=
.