Djangoパスワード格納戦略分析
一、ソース分析
Djangoが発表した1.4バージョンには、いくつかの安全面で重要な向上が含まれています。一つは、SHA 1の代わりにPBKDF 2暗号化アルゴリズムを使用することである。もう一つの特徴は、自分の暗号化方法を追加することです。
Djangoはあなたが提供した最初の暗号化方法を使います。 setting.py 書類には少なくとも一つの方法が必要です。
DjangoはPBKDF 2アルゴリズムを使って36,000回の反復によって、暴力的な亀裂法によって簡単に破られないようにします。パスワードは下のフォーマットで保存します。
algorithm$number of iterations$salt$password hash"
例:pbkdf 2_share 256$36000 Lx 7 auRCc 8 FUI$eG 9 lX 66 cKFTOS 9 s EcihSCj 6 uqbra9 ZrO+Iq 3 H 9 xDU=
二、カスタムパスワードの暗号化方法
1、settings.pyにカスタム暗号化アルゴリズムを追加する:
3、認証方式を修正する
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。
Djangoが発表した1.4バージョンには、いくつかの安全面で重要な向上が含まれています。一つは、SHA 1の代わりにPBKDF 2暗号化アルゴリズムを使用することである。もう一つの特徴は、自分の暗号化方法を追加することです。
Djangoはあなたが提供した最初の暗号化方法を使います。 setting.py 書類には少なくとも一つの方法が必要です。
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
]
まず、PBKDF 2 Password Hasherの暗号化方式を見ます。
class BasePasswordHasher(object):
"""
Abstract base class for password hashers
When creating your own hasher, you need to override algorithm,
verify(), encode() and safe_summary().
PasswordHasher objects are immutable.
"""
algorithm = None
library = None
def _load_library(self):
if self.library is not None:
if isinstance(self.library, (tuple, list)):
name, mod_path = self.library
else:
name = mod_path = self.library
try:
module = importlib.import_module(mod_path)
except ImportError:
raise ValueError("Couldn't load %s password algorithm "
"library" % name)
return module
raise ValueError("Hasher '%s' doesn't specify a library attribute" %
self.__class__)
def salt(self):
"""
Generates a cryptographically secure nonce salt in ascii
"""
return get_random_string()
def verify(self, password, encoded):
"""
Checks if the given password is correct
"""
raise NotImplementedError()
def encode(self, password, salt):
"""
Creates an encoded database value
The result is normally formatted as "algorithm$salt$hash" and
must be fewer than 128 characters.
"""
raise NotImplementedError()
def safe_summary(self, encoded):
"""
Returns a summary of safe values
The result is a dictionary and will be used where the password field
must be displayed to construct a safe representation of the password.
"""
raise NotImplementedError()
class PBKDF2PasswordHasher(BasePasswordHasher):
"""
Secure password hashing using the PBKDF2 algorithm (recommended)
Configured to use PBKDF2 + HMAC + SHA256.
The result is a 64 byte binary string. Iterations may be changed
safely but you must rename the algorithm if you change SHA256.
"""
algorithm = "pbkdf2_sha256"
iterations = 36000
digest = hashlib.sha256
def encode(self, password, salt, iterations=None):
assert password is not None
assert salt and '$' not in salt
if not iterations:
iterations = self.iterations
hash = pbkdf2(password, salt, iterations, digest=self.digest)
hash = base64.b64encode(hash).decode('ascii').strip()
return "%s$%d$%s$%s" % (self.algorithm, iterations, salt, hash)
def verify(self, password, encoded):
algorithm, iterations, salt, hash = encoded.split('$', 3)
assert algorithm == self.algorithm
encoded_2 = self.encode(password, salt, int(iterations))
return constant_time_compare(encoded, encoded_2)
def safe_summary(self, encoded):
algorithm, iterations, salt, hash = encoded.split('$', 3)
assert algorithm == self.algorithm
return OrderedDict([
(_('algorithm'), algorithm),
(_('iterations'), iterations),
(_('salt'), mask_hash(salt)),
(_('hash'), mask_hash(hash)),
])
def must_update(self, encoded):
algorithm, iterations, salt, hash = encoded.split('$', 3)
return int(iterations) != self.iterations
def harden_runtime(self, password, encoded):
algorithm, iterations, salt, hash = encoded.split('$', 3)
extra_iterations = self.iterations - int(iterations)
if extra_iterations > 0:
self.encode(password, salt, extra_iterations)
ご覧のように、BasePassword Hasherから引き継ぎ、書き換えなければなりません。 verify() , encode() および safe_サマリー() 方法。DjangoはPBKDF 2アルゴリズムを使って36,000回の反復によって、暴力的な亀裂法によって簡単に破られないようにします。パスワードは下のフォーマットで保存します。
algorithm$number of iterations$salt$password hash"
例:pbkdf 2_share 256$36000 Lx 7 auRCc 8 FUI$eG 9 lX 66 cKFTOS 9 s EcihSCj 6 uqbra9 ZrO+Iq 3 H 9 xDU=
二、カスタムパスワードの暗号化方法
1、settings.pyにカスタム暗号化アルゴリズムを追加する:
PASSWORD_HASHERS = [
'myproject.hashers.MyMD5PasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
]
2、MyMD 5 Password Hasherを見に来ました。これは私がカスタマイズした暗号化方式です。基本的なmd 5です。djangoのMD 5 Password Hasherは塩を加えたものです。
from django.contrib.auth.hashers import BasePasswordHasher,MD5PasswordHasher
from django.contrib.auth.hashers import mask_hash
import hashlib
class MyMD5PasswordHasher(MD5PasswordHasher):
algorithm = "mymd5"
def encode(self, password, salt):
assert password is not None
hash = hashlib.md5(password).hexdigest().upper()
return hash
def verify(self, password, encoded):
encoded_2 = self.encode(password, '')
return encoded.upper() == encoded_2.upper()
def safe_summary(self, encoded):
return OrderedDict([
(_('algorithm'), algorithm),
(_('salt'), ''),
(_('hash'), mask_hash(hash)),
])
その後、データベースで確認できますが、パスワードはカスタム暗号化方式を使用しています。3、認証方式を修正する
AUTHENTICATION_BACKENDS = (
'framework.mybackend.MyBackend', #
'django.contrib.auth.backends.ModelBackend',
'guardian.backends.ObjectPermissionBackend',
)
4、カスタム認証方式を見に来てください。
framework.mybackend.py:
import hashlib
from pro import models
from django.contrib.auth.backends import ModelBackend
class MyBackend(ModelBackend):
def authenticate(self, username=None, password=None):
try:
user = models.M_User.objects.get(username=username)
print user
except Exception:
print 'no user'
return None
if hashlib.md5(password).hexdigest().upper() == user.password:
return user
return None
def get_user(self, user_id):
try:
return models.M_User.objects.get(id=user_id)
except Exception:
return None
もちろんこれらの修正を経て、最終的な安全性はdjangoが持っているものよりずっと低いですが、需要はこのようにして、満たさなければなりません。以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。