1

私は、php を使用して 1 つの Web サイトを Django フレームワークに移行する作業を行っています。

特定のハッシュパスワードアルゴリズムに慣れているため、次のように書く必要がありました。

#settings.py
PASSWORD_HASHERS = (
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'project.hashers.SHA1ProjPasswordHasher',        # that's mine
    '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):
    """
    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)),
            ])

が最初の場合にうまく機能しますPBKDF2PasswordHasher

>>> from django.contrib.auth import authenticate
>>> u = authenticate(username='root', password='test')
>>> u.password
u'pbkdf2_sha256$10000$EX8BcgPFjygx$HvB6NmZ7uX1rWOOPbHRKd8GLYD3cAsQtlprXUq1KGMk='
>>> exit()

次にSHA1ProjPasswordHasher、最初の認証を行いました。最初の認証はうまく機能します。ハッシュが変更されました。:

>>> from django.contrib.auth import authenticate
>>> u = authenticate(username='root', password='test')
>>> u.password
'a94a8fe5'
>>> exit()

2 回目の認証に失敗しました。新しいハッシュで認証できません。

>>> 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'

何が問題なのですか?ありがとう。


更新: OK、問題がより明確になりました。ここからスライスを削除すると:

return hashlib.sha1(force_bytes(salt + password)).hexdigest()[:8]

すべてが正常に機能しています。理由がわかりません..

4

2 に答える 2

0

無塩のmd5ハッシュのみにドル記号を含めることはできません。

# 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)

したがって、最善の方法は、現在のパスワードハッシュを次の形式に変換することです。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'
于 2012-12-30T05:37:30.617 に答える