私が書いているデスクトップ アプリの認証方法を作成するのに役立つ Python ライブラリを探しています。djangoやturbogearsなどのWebフレームワークでいくつかの方法を見つけました。
ユーザー名とパスワードの関連付けをローカル ファイルに保存したいだけです。私は自分でそれを書くことができますが、実際にはすでに存在しており、より良い解決策になるでしょう(私は暗号化にあまり精通していません).
私が書いているデスクトップ アプリの認証方法を作成するのに役立つ Python ライブラリを探しています。djangoやturbogearsなどのWebフレームワークでいくつかの方法を見つけました。
ユーザー名とパスワードの関連付けをローカル ファイルに保存したいだけです。私は自分でそれを書くことができますが、実際にはすでに存在しており、より良い解決策になるでしょう(私は暗号化にあまり精通していません).
dbrは言った:
def hash_password(password): """Returns the hashed version of a string """ return hasher.new( str(password) ).hexdigest()
これは、パスワードをハッシュするための本当に安全でない方法です。あなたはこれをしたくありません。OpenBSDのパスワードハッシュシステムを作成した人たちがBycryptPaperを読んだ理由を知りたい場合。さらに、パスワードがどのように破られるかについての良い議論が必要な場合は、ジャック・ザ・リッパー(人気のあるUNIXパスワードクラッカー)の作者とのこのインタビューをチェックしてください。
今ではB-Cryptは素晴らしいですが、EKS-Blowfishアルゴリズムを利用できず、自分で実装したくなかったため、このシステムを使用していないことを認めなければなりません。私はFreeBSDシステムのわずかに更新されたバージョンを使用します。これを以下に投稿します。要点はこれです。パスワードをハッシュするだけではいけません。パスワードをソルトしてからハッシュし、10,000回ほど繰り返します。
それが意味をなさなかった場合、ここにコードがあります:
#note I am using the Python Cryptography Toolkit
from Crypto.Hash import SHA256
HASH_REPS = 50000
def __saltedhash(string, salt):
sha256 = SHA256.new()
sha256.update(string)
sha256.update(salt)
for x in xrange(HASH_REPS):
sha256.update(sha256.digest())
if x % 10: sha256.update(salt)
return sha256
def saltedhash_bin(string, salt):
"""returns the hash in binary format"""
return __saltedhash(string, salt).digest()
def saltedhash_hex(string, salt):
"""returns the hash in hex format"""
return __saltedhash(string, salt).hexdigest()
このようなシステムを展開するために考慮すべき重要なことは、HASH_REPS定数です。これは、このシステムのスケーラブルなコスト要因です。各ハッシュが計算されるのを待つ例外的な時間と、パスワードファイルに対するオフライン辞書ベースの攻撃のリスクを判断するために、テストを行う必要があります。
セキュリティは難しく、私が提示する方法はこれを行うための最良の方法ではありませんが、単純なハッシュよりもはるかに優れています。さらに、実装は非常に簡単です。したがって、より複雑なソリューションを選択しなくても、これは最悪の事態ではありません。
これがお役に立てば幸いです、ティム
独自の認証方法を作成する必要があると思います。アプリケーションに最も適したものにすることができますが、暗号化にはpycryptoやその他の軽量ライブラリなどのライブラリを使用してください。
ところで、pycrypto 用の Windows バイナリが必要な場合は、ここから入手できます。
以下を擬似コードとして扱います。
try:
from hashlib import sha as hasher
except ImportError:
# You could probably exclude the try/except bit,
# but older Python distros dont have hashlib.
try:
import sha as hasher
except ImportError:
import md5 as hasher
def hash_password(password):
"""Returns the hashed version of a string
"""
return hasher.new( str(password) ).hexdigest()
def load_auth_file(path):
"""Loads a comma-seperated file.
Important: make sure the username
doesn't contain any commas!
"""
# Open the file, or return an empty auth list.
try:
f = open(path)
except IOError:
print "Warning: auth file not found"
return {}
ret = {}
for line in f.readlines():
split_line = line.split(",")
if len(split_line) > 2:
print "Warning: Malformed line:"
print split_line
continue # skip it..
else:
username, password = split_line
ret[username] = password
#end if
#end for
return ret
def main():
auth_file = "/home/blah/.myauth.txt"
u = raw_input("Username:")
p = raw_input("Password:") # getpass is probably better..
if auth_file.has_key(u.strip()):
if auth_file[u] == hash_password(p):
# The hash matches the stored one
print "Welcome, sir!"
カンマ区切りのファイルを使用する代わりに、SQLite3(他の設定などに使用できます)を使用することをお勧めします。
また、これはあまり安全ではないことを忘れないでください。アプリケーションがローカルの場合、悪意のあるユーザーが~/.myauth.txt
ファイルを置き換える可能性があります。ローカルアプリケーションの認証をうまく行うのは困難です。ユーザーのパスワードを使用して読み取るデータを暗号化する必要があり、通常は非常に注意が必要です。
import hashlib
import random
def gen_salt():
salt_seed = str(random.getrandbits(128))
salt = hashlib.sha256(salt_seed).hexdigest()
return salt
def hash_password(password, salt):
h = hashlib.sha256()
h.update(salt)
h.update(password)
return h.hexdigest()
#in datastore
password_stored_hash = "41e2282a9c18a6c051a0636d369ad2d4727f8c70f7ddeebd11e6f49d9e6ba13c"
salt_stored = "fcc64c0c2bc30156f79c9bdcabfadcd71030775823cb993f11a4e6b01f9632c3"
password_supplied = 'password'
password_supplied_hash = hash_password(password_supplied, salt_stored)
authenticated = (password_supplied_hash == password_stored_hash)
print authenticated #True
シンプルにしたい場合は、キーがユーザー名で値がパスワードである辞書を使用します (SHA256 などで暗号化されています)。 ディスクとの間でピクルします (これはデスクトップ アプリケーションであるため、メモリに保持するオーバーヘッドは無視できると想定しています)。
例えば:
import pickle
import hashlib
# Load from disk
pwd_file = "mypasswords"
if os.path.exists(pwd_file):
pwds = pickle.load(open(pwd_file, "rb"))
else:
pwds = {}
# Save to disk
pickle.dump(pwds, open(pwd_file, "wb"))
# Add password
pwds[username] = hashlib.sha256(password).hexdigest()
# Check password
if pwds[username] = hashlib.sha256(password).hexdigest():
print "Good"
else:
print "No match"
これはパスワードをハッシュとして保存することに注意してください。したがって、それらは本質的に回復できません。パスワードを紛失した場合、古いパスワードを取り戻すのではなく、新しいパスワードが割り当てられます。
「md5」を使用してください。これはbase64よりもはるかに優れています
>>> import md5
>>> hh = md5.new()
>>> hh.update('anoop')
>>> hh.digest
<built-in method digest of _hashlib.HASH object at 0x01FE1E40>