我使用的是一个特定的哈希密码算法,所以我不得不写道:
我正在使用php将一个网站迁移到Django框架。 / p>
#settings.py PASSWORD_HASHERS =('django.contrib.auth.hashers.PBKDF2PasswordHasher' 'project.hashers.SHA1ProjPasswordHasher',#这是我的'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', ... )和:
#hashers .py import hashlib from django.contrib.auth.hashers import(BasePasswordHasher,mask_hash) from django.utils.datastructures import SortedDict from django.utils.encoding import force_bytes from django.utils.crypto import constant_time_compare from django.utils.translation import ugettext_noop as _ class SHA1ProjPasswordHasher(BasePasswordHasher ):特殊的雪花算法第一个版本。 php code:$ pass = substr(sha1(trim($ _ POST ['password'])),0,8); algorithm =unsalted_and_trimmed_sha1 def salt(self): return'' def encode(self,密码,salt): return hashlib.sha1(force_bytes(salt + password))。hexdigest()[:8] def verify(self,password,encoded): encoded_2 = self.encode(password,'') return constant_time_compare(encoded,encoded_2) def safe_summary(self,encoded): return SortedDict([(_('algorithm'),self.algorithm),(_('hash'),mask_hash(encoded,show = 3)),])当 PBKDF2PasswordHasher 是第一个:
>>> from django.contrib.auth import authenticate >>> u = authenticate(username ='root' password ='test')>>> u.password u'pbkdf2_sha256 $ 10000 $ EX8BcgPFjygx $ HvB6NmZ7uX1rWOOPbHRKd8GLYD3cAsQ tlprXUq1KGMk ='>>> exit()然后我把我的 SHA1ProjPasswordHasher 首先,第一认证工作很好。哈希已更改:
>>>来自django.contrib.auth import authenticate >>> u = authenticate(username ='root',password ='test')>>> u.password 'a94a8fe5'>>> exit()第二个身份验证失败。无法使用新的哈希进行身份验证。
>>>来自django.contrib.auth import authenticate >>> u = authenticate(username ='root',password ='test')>>> u.password 追溯(最近的最后一次呼叫):文件< console>,第1行,< module> AttributeError:'NoneType'对象没有属性'password'可能是什么问题?谢谢。
更新:好的,问题变得更加清晰。当我从这里删除切片时:
返回hashlib.sha1(force_bytes(salt + password))hexdigest()[:8 ]一切正常。我不能为什么..
解决方案只有没有限制的md5哈希值不能包含美元符号:
#django / contrib / auth / hashers.py def identify_hasher(编码):返回加载的密码哈希的一个实例 通过检查编码的哈希标识哈希算法,并调用 get_hasher()返回hasher,如果算法不能引发ValueError 如果len(编码)== 32和'$'未编码: algorithm ='unsalted_md5'否则: algorithm = encoded.split('$',1)[0] 返回get_hasher(算法)所以最好的方法是将当前的密码哈希转换为格式: alg $ salt $ hash
类SHA1ProjPasswordHasher(BasePasswordHasher):特殊的雪花算法从第一个版本 php code:$ pass = substr(sha1(trim($ _ POST ['password'])),0,8); algorithm =unsalted_and_trimmed_sha1 def salt(self): return'' def encode(self,密码,盐): assert密码 assert'$'不在盐哈希= hashlib.sha1(强制字符(salt +密码))hexdigest()[:8] 返回%s $%s $%s%(self.algorithm,salt,hash) def verify(self,password,encoded): algorithm,salt,hash = encoding.split('$',2) assert algorithm == self.algorithm encoded_2 = self.encode(password,salt) return constant_time_compare(encoded,encoded_2) def safe_summary(self,encoded):算法,salt,hash = encoded.split('$',2) assert algorithm == self.algorithm return SortedDict [(_('algorithm'),algorithm),(_('salt'),mask_hash(salt,show = 2)),(_('hash' mask_hash (哈希)),])。
>>>来自django.contrib.auth import authenticate >>> x = authenticate(username ='root',password ='test')>>> x < User:root> >>> x.password u'unsalted_and_trimmed_sha1 $$ a94a8fe5'
I am working on the migration of one website with php to Django framework.
There is used to a specific hash passwords algorithm, so I had to write:
#settings.py PASSWORD_HASHERS = ( 'django.contrib.auth.hashers.PBKDF2PasswordHasher', 'project.hashers.SHA1ProjPasswordHasher', # that's mine 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', ... )and:
#hashers.py import hashlib from django.contrib.auth.hashers import (BasePasswordHasher, mask_hash) from django.utils.datastructures import SortedDict from django.utils.encoding import force_bytes from django.utils.crypto import constant_time_compare from django.utils.translation import ugettext_noop as _ class SHA1ProjPasswordHasher(BasePasswordHasher): """ Special snowflake algorithm from the first version. php code: $pass=substr(sha1(trim($_POST['password'])),0,8); """ algorithm = "unsalted_and_trimmed_sha1" def salt(self): return '' def encode(self, password, salt): return hashlib.sha1(force_bytes(salt + password)).hexdigest()[:8] def verify(self, password, encoded): encoded_2 = self.encode(password, '') return constant_time_compare(encoded, encoded_2) def safe_summary(self, encoded): return SortedDict([ (_('algorithm'), self.algorithm), (_('hash'), mask_hash(encoded, show=3)), ])It's works well when PBKDF2PasswordHasher is first:
>>> from django.contrib.auth import authenticate >>> u = authenticate(username='root', password='test') >>> u.password u'pbkdf2_sha256$10000$EX8BcgPFjygx$HvB6NmZ7uX1rWOOPbHRKd8GLYD3cAsQtlprXUq1KGMk=' >>> exit()Then I put my SHA1ProjPasswordHasher on the first place, first authentication works great. The hash was changed.:
>>> from django.contrib.auth import authenticate >>> u = authenticate(username='root', password='test') >>> u.password 'a94a8fe5' >>> exit()Second authentication is failed. Can't authenticate with new hash.
>>> from django.contrib.auth import authenticate >>> u = authenticate(username='root', password='test') >>> u.password Traceback (most recent call last): File "<console>", line 1, in <module> AttributeError: 'NoneType' object has no attribute 'password'What could be the problem? Thanks.
UPDATE: Ok, the problem became more clear. When I remove slice from here:
return hashlib.sha1(force_bytes(salt + password)).hexdigest()[:8]everything working fine. I can't get why..
解决方案Only unsalted md5 hashes can not include a dollar sign:
# django/contrib/auth/hashers.py def identify_hasher(encoded): """ Returns an instance of a loaded password hasher. Identifies hasher algorithm by examining encoded hash, and calls get_hasher() to return hasher. Raises ValueError if algorithm cannot be identified, or if hasher is not loaded. """ if len(encoded) == 32 and '$' not in encoded: algorithm = 'unsalted_md5' else: algorithm = encoded.split('$', 1)[0] return get_hasher(algorithm)So the best way is convert the current password hashes to the format: alg$salt$hash
class SHA1ProjPasswordHasher(BasePasswordHasher): """ Special snowflake algorithm from the first version. php code: $pass=substr(sha1(trim($_POST['password'])),0,8); """ algorithm = "unsalted_and_trimmed_sha1" def salt(self): return '' def encode(self, password, salt): assert password assert '$' not in salt hash = hashlib.sha1(force_bytes(salt + password)).hexdigest()[:8] return "%s$%s$%s" % (self.algorithm, salt, hash) def verify(self, password, encoded): algorithm, salt, hash = encoded.split('$', 2) assert algorithm == self.algorithm encoded_2 = self.encode(password, salt) return constant_time_compare(encoded, encoded_2) def safe_summary(self, encoded): algorithm, salt, hash = encoded.split('$', 2) assert algorithm == self.algorithm return SortedDict([ (_('algorithm'), algorithm), (_('salt'), mask_hash(salt, show=2)), (_('hash'), mask_hash(hash)), ]).
>>> from django.contrib.auth import authenticate >>> x = authenticate(username='root', password='test') >>> x <User: root> >>> x.password u'unsalted_and_trimmed_sha1$$a94a8fe5'
更多推荐
无法使用自定义PASSWORD
发布评论