Search code examples
pythonpbkdf2

How can I generate a PBKDF2 password hash in python?


I'm using some software that stores it's internal user database in a JSON file (users.json) where each user has a field called password where the values look like this:

pbkdf2:10000:f30dd5755d4d172d:e7b2fdda936b4ad5335c3b76c8f3568b0e3b14ce1d9b8ca1e32b7627545d0a3811aa3407a814731b1ee1c86e108c66c1616b1ea2570f7ecf8d04d4f465c33947

I want to modify this users.json programatically from python to reset a user password, without having to go through this application UI.

How can I generate a pbkdf2:xxxxxx string for a new password?


Solution

  • The

    pbkdf2:10000:f30dd5755d4d172d:e7b2fdda936b4ad5335c3b76c8f3568b0e3b14ce1d9b8ca1e32b7627545d0a3811aa3407a814731b1ee1c86e108c66c1616b1ea2570f7ecf8d04d4f465c33947
    

    follows the format

    pbkdf2:iterations:saltinhexstring:hash64bytesinhexstring
    

    to generate a new pbkdf2:xxx you can use hashlib.pbkdf2_hmac which is builtin since Python 3.4.

    For example the pbkdf2:10000:f30dd5755d4d172d:e7b2fdda936b4ad5335c3b76c8f3568b0e3b14ce1d9b8ca1e32b7627545d0a3811aa3407a814731b1ee1c86e108c66c1616b1ea2570f7ecf8d04d4f465c33947 seems to be the hash of the password admin using pbkdf2_hmac('sha1',...)

    You can generate the hash for password admin and salt f30dd5755d4d172d over 10000 iterations like this:

    from hashlib import pbkdf2_hmac
    iterations = 10000
    salt = bytes.fromhex('f30dd5755d4d172d')
    passwordtohash = 'admin'
    hash = pbkdf2_hmac('sha1',bytes(passwordtohash,'utf-8'), salt, iterations, dklen=64)
    print(f"pbkdf2:{iterations}:{salt.hex()}:{hash.hex()}")
    # pbkdf2:10000:f30dd5755d4d172d:e7b2fdda936b4ad5335c3b76c8f3568b0e3b14ce1d9b8ca1e32b7627545d0a3811aa3407a814731b1ee1c86e108c66c1616b1ea2570f7ecf8d04d4f465c33947
    

    Or in general for a completely new password (with a new random salt):

    from hashlib import pbkdf2_hmac
    import os
    import random
    import string
    iterations = 10000
    salt = os.urandom(8)
    passwordtohash = ''.join(random.choice(string.ascii_uppercase) for _ in range(16))
    hash = pbkdf2_hmac('sha1',bytes(passwordtohash,'utf-8'), salt, iterations, dklen=64)
    print(f"New password: '{passwordtohash}'")
    print(f"pbkdf2:{iterations}:{salt.hex()}:{hash.hex()}")
    
    New password: 'LGVDFKSBEUISDGUM'
    pbkdf2:10000:0ef9f6feb244efc1:2e61922d793aca79f5ad326033987d8714779795cc26e99fae2f44014afac4efdbe17e543379afd1d578a16ee3f4476dc4112cf047c908868ed0318cdf248d64