问题
I have passwords stored in web2py using SHA 512 algorithm. I am now migrating the models to django and hence need a way to hash passwords in django using SHA 512 in the same way as web2py does so that I can authenticate the old users with the same passwords.Please suggest some way.
回答1:
According to this post a Python snippet to recreate the convention used in web2py would be the following:
from hashlib import md5
import hmac
hmac_key = '<your secret key>'
password = 'insecure'
thehash = hmac.new(hmac_key, password).hexdigest()
print thehash
web2py uses hmac (which is your secret + the plaintext of the user's password) as the final hash and not just a straight MD5/SHA hash (depending on your settings). So you would just need to swap out MD5 for SHA in the above example to get things working on your end. But this implementation is all you would need to implement in your new application to make them cross compatible as long as the secret key is the same.
According to the docs the hash is stored in the following format:
<algorithm>$<salt>$<hash>
so if there is a salt used then it's stored with the hash making it easy to grab the salt for use in your new application. The dollar signs make it easy to parse each value.
algo, salt, hash = password_hash.split("$")
UPDATE: I pulled the below code from the web2py source but what you need to do is update the variable hmac_key with the value that you have set for auth.settings.hmac_key. Hopefully when you run (after you update the hmac_key variable) this the hashes should match.
import hashlib
import hmac
from hashlib import sha512
h="sha512$b850ed44943b861b$c90901439983bce7fd512592b20d83f8e654632dee51de515773e70eabe609f62cebec64fed4df03acd54e6a627c9291e70fdf3a89996ffa796897c159e95c11"
algo,salt,hash = h.split("$")
print "crypted hash: %s"%hash
pwd = "pawan123"
##get this value from auth.settings.hmac_key
hmac_key = ""
def get_digest(value):
"""
Returns a hashlib digest algorithm from a string
"""
if not isinstance(value, str):
return value
value = value.lower()
if value == "md5":
return md5
elif value == "sha1":
return sha1
elif value == "sha224":
return sha224
elif value == "sha256":
return sha256
elif value == "sha384":
return sha384
elif value == "sha512":
return sha512
else:
raise ValueError("Invalid digest algorithm: %s" % value)
#hashed = simple_hash(self.password, key, salt, digest_alg)
def simple_hash(text, key='', salt='', digest_alg='md5'):
"""
Generates hash with the given text using the specified
digest hashing algorithm
"""
if not digest_alg:
raise RuntimeError("simple_hash with digest_alg=None")
elif not isinstance(digest_alg, str): # manual approach
h = digest_alg(text + key + salt)
elif digest_alg.startswith('pbkdf2'): # latest and coolest!
iterations, keylen, alg = digest_alg[7:-1].split(',')
return pbkdf2_hex(text, salt, int(iterations),
int(keylen), get_digest(alg))
elif key: # use hmac
digest_alg = get_digest(digest_alg)
h = hmac.new(key + salt, text, digest_alg)
else: # compatible with third party systems
h = get_digest(digest_alg)()
h.update(text + salt)
return h.hexdigest()
print "result hash: %s"%simple_hash(pwd, hmac_key, salt, "sha512")
回答2:
I think your best solution is to write an auth backend that will authenticate the User against the web2py base, then ask him to change or confirm his password and build a new Django auth-passwords.
The hole idea of crypto-hashing passwords is that you or any hacker can't see them if you have access to the database.
Here is the Django documentation on writing an authentication backend.
来源:https://stackoverflow.com/questions/28088826/migrating-passwords-from-web2py-to-django