web-dev-qa-db-ja.com

pythonでパスワードをソルトおよびハッシュします

このコードは、パスワードをソルトでハッシュすることになっています。ソルトおよびハッシュされたパスワードはデータベースに保存されています。パスワード自体はそうではありません。

操作のデリケートな性質を考えると、私はすべてがコーシャであることを確認したかった。

import hashlib
import base64
import uuid

password = 'test_password'
salt     = base64.urlsafe_b64encode(uuid.uuid4().bytes)


t_sha = hashlib.sha512()
t_sha.update(password+salt)
hashed_password =  base64.urlsafe_b64encode(t_sha.digest())
73
Chris Dutrow

編集:この答えは間違っています。 SHA512の1つの反復はfastであり、パスワードハッシュ関数としての使用には不適切です。代わりに、ここで他の回答のいずれかを使用してください。


私は元気そうだ。ただし、実際にはbase64は必要ないと確信しています。あなたはこれを行うことができます:

import hashlib, uuid
salt = uuid.uuid4().hex
hashed_password = hashlib.sha512(password + salt).hexdigest()

問題が発生しない場合は、ソルトとハッシュ化されたパスワードを16進文字列ではなく生のバイトとして保存することで、データベースの保存効率をわずかに高めることができます。これを行うには、hexbytesに、hexdigestdigestに置き換えます。

38
Taymon

この質問に対する他の回答に基づいて、bcryptを使用した新しいアプローチを実装しました。

Bcryptを使用する理由

私が正しく理解している場合、bcrypt over SHA512を使用する引数は、bcryptが低速になるように設計されているということです。 bcryptには、ハッシュ化されたパスワードを初めて生成するときの遅さを調整するオプションもあります。

# The '12' is the number that dictates the 'slowness'
bcrypt.hashpw(password, bcrypt.gensalt( 12 ))

悪意のある者がハッシュされたパスワードを含むテーブルを手に入れた場合、それらをブルートフォースすることははるかに難しいため、遅いことが望ましいです。

実装

def get_hashed_password(plain_text_password):
    # Hash a password for the first time
    #   (Using bcrypt, the salt is saved into the hash itself)
    return bcrypt.hashpw(plain_text_password, bcrypt.gensalt())

def check_password(plain_text_password, hashed_password):
    # Check hashed password. Using bcrypt, the salt is saved into the hash itself
    return bcrypt.checkpw(plain_text_password, hashed_password)

ノート

次を使用して、Linuxシステムにライブラリを簡単にインストールできました。

pip install py-bcrypt

しかし、Windowsシステムへのインストールにはさらに苦労しました。パッチが必要なようです。このスタックオーバーフローの質問を参照してください: py-bcrypt win 7 64bit pythonにインストールする

50
Chris Dutrow

賢いのは、自分で暗号を書くのではなく、passlibのようなものを使うことです: https://bitbucket.org/ecollins/passlib/wiki/Home

安全な方法で暗号コードを書くのは簡単です。厄介なのは、非暗号化コードでは、プログラムがクラッシュして動作しないときにすぐに気付くことが多いということです。暗号コードを使用すると、遅れてデータが危険にさらされた後にのみ発見することがよくあります。そのため、このテーマについて知識があり、戦闘テスト済みのプロトコルに基づいている他の誰かが作成したパッケージを使用する方が良いと思います。

また、passlibには、使いやすく、古いプロトコルが壊れていることが判明した場合に新しいパスワードハッシュプロトコルに簡単にアップグレードできるニースの機能がいくつかあります。

また、sha512の1ラウンドだけが辞書攻撃に対して脆弱です。 sha512は高速になるように設計されており、これはパスワードを安全に保存しようとすると実際には悪いことです。他の人々は、この種の問題すべてについて長い間一生懸命に考えてきたので、あなたはこれをより良く利用する。

46
M.D.

これをPython 3で機能させるには、たとえばUTF-8エンコードする必要があります。

hashed_password = hashlib.sha512(password.encode('utf-8') + salt.encode('utf-8')).hexdigest()

それ以外の場合は次のようになります:

トレースバック(最後の最後の呼び出し):
ファイル「」、1行目
hashed_pa​​ssword = hashlib.sha512(password + salt).hexdigest()
TypeError:Unicodeオブジェクトは、ハッシュする前にエンコードする必要があります

18
Wayne

passlibは、既存のシステムに保存されているハッシュを使用する必要がある場合に役立つようです。形式を制御できる場合は、bcryptやscryptなどの最新のハッシュを使用します。現時点では、bcryptはpythonから使用する方がはるかに簡単なようです。

passlibはbcryptをサポートしています。py-bcryptをバックエンドとしてインストールすることをお勧めします。 http://pythonhosted.org/passlib/lib/passlib.hash.bcrypt.html

Passlibをインストールしたくない場合は、 py-bcrypt を直接使用することもできます。 readmeには基本的な使用例があります。

参照: scryptを使用してPythonでパスワードとソルトのハッシュを生成する方法

10
Terrel Shumway

古いスレッドを復活させたくありませんが、...最新の最新の安全なソリューションを使用したい人は、アルゴン2を使用してください。

https://pypi.python.org/pypi/argon2_cffi

パスワードハッシュ化コンテストで優勝しました。 ( https://password-hashing.net/ )bcryptよりも使いやすく、bcryptよりも安全です。

6
nagylzs

最初にインポート:-

import hashlib, uuid

次に、メソッドでこれに従ってコードを変更します。

uname = request.form["uname"]
pwd=request.form["pwd"]
salt = hashlib.md5(pwd.encode())

次に、データベースのsqlクエリでこのsaltとunameを渡します。ログインの下にはテーブル名があります。

sql = "insert into login values ('"+uname+"','"+email+"','"+salt.hexdigest()+"')"
0
Sheetal Jha

Python 3.4以降、標準ライブラリのhashlibモジュールには、安全なパスワードハッシュ用に設計されたである key derivation 関数が含まれています「

したがって、 hashlib.pbkdf2_hmac などのいずれかを使用し、 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)
    )

# Example usage:
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 を参照してください。

0
Mark Amery