API de autenticación de Python
-
09-06-2019 - |
Pregunta
Estoy buscando una biblioteca de Python que me ayude a crear un método de autenticación para una aplicación de escritorio que estoy escribiendo.He encontrado varios métodos en framework web como django o turbogears.
Sólo quiero una especie de asociación de nombre de usuario y contraseña almacenada en un archivo local.Puedo escribirlo yo solo, pero en realidad ya existe y será una mejor solución (no soy muy fluido con el cifrado).
Solución
Trate lo siguiente como pseudocódigo.
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!"
En lugar de usar un archivo separado por comas, recomendaría usar SQLite3 (que podría usarse para otras configuraciones y demás).
Además, recuerde que esto no es muy seguro: si la aplicación es local, los usuarios malintencionados probablemente podrían simplemente reemplazar la ~/.myauth.txt
archivo..Es difícil realizar bien la autenticación de aplicaciones locales.Tendrás que cifrar todos los datos que lea usando la contraseña del usuario y, en general, tener mucho cuidado.
Otros consejos
dbr dijo:
def hash_password(password): """Returns the hashed version of a string """ return hasher.new( str(password) ).hexdigest()
Esta es una forma realmente insegura de codificar contraseñas.Tú no quiero hacer esto.Si quieres saber por qué lee el Papel Bycrypt por los chicos que hicieron el sistema de hash de contraseñas para OpenBSD.Además, si desea una buena discusión sobre cómo se descifran las contraseñas, consulte esta entrevista con el autor de Jack el Destripador (el popular descifrador de contraseñas de Unix).
B-Crypt es genial, pero debo admitir que no uso este sistema porque no tenía el algoritmo EKS-Blowfish disponible y no quería implementarlo yo mismo.Utilizo una versión ligeramente actualizada del sistema FreeBSD que publicaré a continuación.La esencia es esta.No se limite a codificar la contraseña.Sal la contraseña, luego haz un hash de la contraseña y repítela unas 10.000 veces.
Si eso no tiene sentido aquí está el código:
#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()
Para implementar un sistema como este, la clave a considerar es la constante HASH_REPS.Este es el factor de costo escalable en este sistema.Deberá realizar pruebas para determinar cuál es la cantidad de tiempo excepcional que desea esperar para que se calcule cada hash frente al riesgo de un ataque basado en un diccionario fuera de línea en su archivo de contraseña.
La seguridad es difícil y el método que presento no es la mejor manera de hacerlo, pero es significativamente mejor que un simple hash.Además, es muy sencillo de implementar.Entonces, incluso si no elige una solución más compleja, esta no es la peor que existe.
Espero que esto ayude, Tim
Si lo desea simple, use un diccionario donde las claves sean los nombres de usuario y los valores sean las contraseñas (cifradas con algo como SHA256). Pepinillo hacia/desde el disco (como se trata de una aplicación de escritorio, supongo que la sobrecarga de mantenerla en la memoria será insignificante).
Por ejemplo:
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"
Tenga en cuenta que esto almacena las contraseñas como un picadillo - por lo que son esencialmente irrecuperables.Si pierde su contraseña, se le asignará una nueva y no se le devolverá la anterior.
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
ver también gae-autenticarse-en-un-sitio-de-terceros
Utilice "md5", es mucho mejor que base64.
>>> import md5
>>> hh = md5.new()
>>> hh.update('anoop')
>>> hh.digest
<built-in method digest of _hashlib.HASH object at 0x01FE1E40>