Python认证API
我在找一个Python库,想用它来为我正在写的桌面应用程序创建一个认证方法。
我在一些网页框架,比如Django或TurboGears,找到了几种方法。
我只想要一种把用户名和密码关联起来,并存储在本地文件里的方式。我自己可以写这个,但我真的希望能找到一个现成的解决方案,因为我对加密不是很熟悉。
6 个回答
dbr 说:
def hash_password(password): """Returns the hashed version of a string """ return hasher.new( str(password) ).hexdigest()
这种方式来加密密码真的不安全。你绝对不想这么做。如果你想知道原因,可以看看这篇由为 OpenBSD 设计密码加密系统的人写的 B-Crypt 论文。另外,如果你想了解密码是怎么被破解的,可以看看 这篇采访,采访的对象是 Jack the Ripper 的作者(Jack the Ripper 是一个流行的 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 常量。这是这个系统中的可扩展成本因素。你需要进行测试,以确定你希望每次计算哈希时能接受的等待时间,以及你密码文件遭受离线字典攻击的风险之间的平衡。
安全性是个难题,我提供的方法并不是最好的,但比简单的哈希要好得多。而且实现起来非常简单。所以即使你不选择更复杂的解决方案,这个方法也不是最糟糕的。
希望这能帮到你,
Tim
把下面的内容当作伪代码来看待..
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
这个文件.. 本地应用的身份验证很难做到安全。你需要用用户的密码来加密任何读取的数据,并且通常要非常小心。