ユーザー名とパスワードをデータベースに保存しようとしていて、そのための最も安全な方法は何か疑問に思っています。どこかでソルトを使用する必要があることは知っていますが、ソルトを安全に生成する方法や、パスワードを暗号化するためにソルトを適用する方法がわかりません。いくつかのサンプルPythonコードをいただければ幸いです。ありがとう。
6 に答える
パスワードとソルトをハッシュとソルトとして保存します。Django がどのようにそれを行うかを見てみましょう: basic docsとsource . <type of hash>$<salt>$<hash>
データベースでは、単一の char フィールドに格納 されます。3 つのパーツを別々のフィールドに保管することもできます。
パスワードを設定する関数:
def set_password(self, raw_password):
import random
algo = 'sha1'
salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
hsh = get_hexdigest(algo, salt, raw_password)
self.password = '%s$%s$%s' % (algo, salt, hsh)
get_hexdigest は、一部のハッシュ アルゴリズムの薄いラッパーです。そのためにhashlibを使用できます。何かのようなものhashlib.sha1('%s%s' % (salt, hash)).hexdigest()
そして、パスワードをチェックする関数:
def check_password(raw_password, enc_password):
"""
Returns a boolean of whether the raw_password was correct. Handles
encryption formats behind the scenes.
"""
algo, salt, hsh = enc_password.split('$')
return hsh == get_hexdigest(algo, salt, raw_password)
私はここでこれに答えました:https://stackoverflow.com/a/18488878/1661689、そして@Koffieもそうでした。
受け入れられた答えが安全ではないことを十分に強調する方法がわかりません。プレーンテキストよりも優れており、ソルトなしのハッシュよりも優れていますが、それでも辞書やブルートフォース攻撃に対して非常に脆弱です. 代わりに、bcrypt のようなSLOW KDF (または少なくとも10,000 回の反復を伴う PBKDF2)を使用してください。
これはより簡単な方法です (effbot から取得)。8 文字を超える長さのパスワードは問題になりません*:
import crypt
import random, string
def getsalt(chars = string.letters + string.digits):
# generate a random 2-character 'salt'
return random.choice(chars) + random.choice(chars)
パスワードを生成するには:
crypt.crypt("password", getsalt())
*: 8 文字を超える長さのパスワードは、右側から 8 文字の長さに削除されます