Python身份验证API
我正在寻找一个Python库,该库我为正在编写的桌面应用程序创建身份验证方法。
我在django或者turbogears等网络框架中发现了几种方法。
我只想将一种用户名-密码关联存储到本地文件中。
我可以自己编写,但实际上它已经存在并且将是一个更好的解决方案(我不太会加密)。
解决方案
回答
我认为我们应该使用自己的身份验证方法,因为它可以使其最适合应用程序,但要使用一个用于加密的库,例如pycrypto或者其他轻量级的库。
顺便说一句,如果我们需要Windows二进制文件进行pycrypto,可以在此处获取它们
回答
如果我们想简单一点,可以使用字典,其中的键是用户名,值是密码(使用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"
请注意,这会将密码存储为散列,因此它们基本上不可恢复。如果我们忘记了密码,则将获得一个新密码,而不是原来的密码。
回答
将以下内容视为伪代码。
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
文件。本地应用程序的auth很难做得很好。我们必须使用用户密码对读取的所有数据进行加密,并且通常要非常小心。
回答
dbr说:
def hash_password(password): """Returns the hashed version of a string """ return hasher.new( str(password) ).hexdigest()
这是散列密码的真正不安全的方法。我们不想这样做。如果我们想知道为什么要阅读使用OpenBSD密码哈希系统的家伙的Bycrypt论文。此外,如果想就如何破解密码进行深入的讨论,请访问开膛手Hyman(流行的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常量。这是该系统中可伸缩的成本因素。我们将需要进行测试,以确定要等待等待每个哈希值被计算的异常时间量,以及对密码文件进行基于脱机字典攻击的风险。
安全性很困难,我介绍的方法并不是做到这一点的最佳方法,但是它比简单的哈希更好。另外,它实现起来非常简单。因此,即使我们不选择更复杂的解决方案,也不是最糟糕的解决方案。
希望这可以帮助,
提姆
回答
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
另请参阅gae对第三方网站进行身份验证