Search code examples
pythonhashsha512pbkdf2flask-security

How can I validate a hash generated by Flask-Security without using it?


I have a Flask application running that has Flask-Security on it. My config.py file looks like this:

...

# Flask-Security config
SECURITY_URL_PREFIX = "..." # my URL prefix
SECURITY_PASSWORD_HASH = "pbkdf2_sha512"
SECURITY_PASSWORD_SALT = "..." # my 29-character long salt

...

and it generates a hash like this on the database:

$pbkdf2-sha512$25000$pXROaU2JUSrlnDPm3BsjBA$ckspsls2SWPhl9dY7XDiAZh5yucWq27fWRuVj4aOUc5dA2Ez5VH1LYiz5KjaZJscaJYAFhWIwPhkAsHiPOrvrg

which is the password 123456 hashed.

In another application, I needed this hash to be verified, but by using Flask-Security it demands me to be in a Flask application with the same configurations set.
I've tried many things but I just can't validate this password without Flask-Security and there MUST be a way of doing that.
Can you guys please help me on this?


Solution

  • Okay, so thanks to @jwag and few more digging on the Flask-Security source code, I've managed to do it.

    For those on the same situation, here's what I did:

    import hmac
    import hashlib
    import base64
    from passlib.context import CryptContext
    
    text_type = str
    salt = "YOUR_SALT_HERE"
    
    def get_pw_context ():
      pw_hash = 'pbkdf2_sha512'
      schemes = ['bcrypt', 'des_crypt', 'pbkdf2_sha256', 'pbkdf2_sha512', 'sha256_crypt', 'sha512_crypt', 'plaintext']
      deprecated = ['auto']
      return CryptContext (schemes=schemes, default=pw_hash, deprecated=deprecated)
    
    def encode_string(string):
      if isinstance(string, text_type):
        string = string.encode('utf-8')
      return string
    
    def get_hmac (password):
      h = hmac.new(encode_string(salt), encode_string(password), hashlib.sha512)
      return base64.b64encode(h.digest())
    
    def verify_password (password, hash):
      return get_pw_context().verify(get_hmac(password), hash)
    
    # Finally
    verify_password ("MY_PASSWORD", "MY_PASSWORD_HASH")