Python 3.4以降、hashlib
標準ライブラリのモジュールには、「安全なパスワードハッシュ用に設計された」鍵導出関数が含まれています。
したがって、を使用hashlib.pbkdf2_hmac
して生成されたソルトで、のようなものの1つを使用しos.urandom
ます。
from typing import Tuple
import os
import hashlib
import hmac
def hash_new_password(password: str) -> Tuple[bytes, bytes]:
"""
Hash the provided password with a randomly-generated salt and return the
salt and hash to store in the database.
"""
salt = os.urandom(16)
pw_hash = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
return salt, pw_hash
def is_correct_password(salt: bytes, pw_hash: bytes, password: str) -> bool:
"""
Given a previously-stored salt and hash, and a password provided by a user
trying to log in, check whether the password is correct.
"""
return hmac.compare_digest(
pw_hash,
hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
)
salt, pw_hash = hash_new_password('correct horse battery staple')
assert is_correct_password(salt, pw_hash, 'correct horse battery staple')
assert not is_correct_password(salt, pw_hash, 'Tr0ub4dor&3')
assert not is_correct_password(salt, pw_hash, 'rosebud')
ご了承ください:
- 16バイトのソルトの使用とPBKDF2の100000回の反復は、Pythonドキュメントで推奨されている最小数と一致します。反復回数をさらに増やすと、ハッシュの計算が遅くなり、安全性が高まります。
os.urandom
常に暗号的に安全なランダム性のソースを使用します
hmac.compare_digest
で使用されるis_correct_password
、は基本的==
に文字列の演算子ですが、短絡する機能がないため、タイミング攻撃の影響を受けません。それはおそらく実際には追加のセキュリティ値を提供しませんが、それも害はないので、私は先に進んでそれを使用しました。
優れたパスワードハッシュを作成するための理論と、パスワードのハッシュに適した他の関数のリストについては、https://security.stackexchange.com/q/211/29805を参照してください。
t_sha.digest() + salt
です。デコードされたハッシュパスワードは正確に32バイトであることがわかっているので、ソルトハッシュパスワードをデコードした後で、ソルトを再度分割できます。