Python身份验证API

时间:2020-03-05 18:55:28  来源:igfitidea点击:

我正在寻找一个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对第三方网站进行身份验证