Unique Salt per User using Flask-Security
Asked Answered
B

2

8

After reading here a bit about salting passwords, it seems that it's best to use a unique salt for each user. I'm working on implementing Flask-Security atm, and from the documentation it appears you can only set a global salt: ie SECURITY_PASSWORD_SALT = 'thesalt'

Question: How would one go about making a unique salt for each password?

Thanks!

edit: from the docs on Flask-Security, I found this, which seems to again suggest that this module only uses a single salt for all passwords out of the box.

flask_security.utils.get_hmac(password)
    Returns a Base64 encoded HMAC+SHA512 of the password signed with the salt 
    specified by SECURITY_PASSWORD_SALT.
Boardwalk answered 19/9, 2014 at 20:41 Comment(3)
A global salt isn't a salt. If the same salt is used for everyone, then two users who happen to have the same password will have the same hashed password. That's the kind of thing a salt is intended to prevent.Borderline
@MichaelBurr Okay, that's what i was thinking... which is why I'm confused. How do I use this setting to make a unique salt for each password? Or do I have to override the salting built-in to Flask-Security in order to do this?Boardwalk
I'm sorry - I know nothing about Flask. I was just commenting on the idea of a global salt.Borderline
C
16

Yes, Flask-Security does use per-user salts by design if using bcrypt (and other schemes such as des_crypt, pbkdf2_sha256, pbkdf2_sha512, sha256_crypt, sha512_crypt).

The config for 'SECURITY_PASSWORD_SALT' is only used for HMAC encryption. If you are using bcrypt as the hashing algorithm Flask-Security uses passlib for hashing and it generates a random salt during hashing. This confustion is noted in issue 268: https://github.com/mattupstate/flask-security/issues/268

It can be verified in the code, walking from encrypt to passlib:

flask_security/utils.py (lines 143-151, 39, and 269)

def encrypt_password(password):
   ...
   return _pwd_context.encrypt(signed)

_pwd_context = LocalProxy(lambda: _security.pwd_context)

flask_security/core.py (269, 244-251, and 18)

pwd_context=_get_pwd_context(app)

def _get_pwd_context(app):
    ...
    return CryptContext(schemes=schemes, default=pw_hash, deprecated=deprecated)

from passlib.context import CryptContext

and finally from: https://pythonhosted.org/passlib/password_hash_api.html#passlib.ifc.PasswordHash.encrypt

note that each call to encrypt() generates a new salt,

Crites answered 22/12, 2014 at 5:15 Comment(0)
B
9

Turns out that if you use bcrypt, it takes care of the salting and stores it with the hash. So I'll go that route!

Thanks to this topic which lead me to this discovery:

Do I need to store the salt with bcrypt?

Boardwalk answered 19/9, 2014 at 23:43 Comment(1)
Kudos on coming back to your own question after finding a solution.Triode

© 2022 - 2024 — McMap. All rights reserved.