Dieser Code soll ein Passwort mit einem Salt hashen. Das Salt- und das Hash-Passwort werden in der Datenbank gespeichert. Das Passwort selbst ist nicht.
Angesichts der Sensibilität der Operation wollte ich sicherstellen, dass alles koscher ist.
import hashlib
import base64
import uuid
password = 'test_password'
salt = base64.urlsafe_b64encode(uuid.uuid4().bytes)
t_sha = hashlib.sha512()
t_sha.update(password+salt)
hashed_password = base64.urlsafe_b64encode(t_sha.digest())
t_sha.digest() + salt
. Sie können das Salt später wieder aufteilen, wenn Sie das Salted-Hash-Passwort dekodiert haben, da Sie wissen, dass das decodierte Hash-Passwort genau 32 Byte beträgt.secrets
stattdessen zu verwenden .Antworten:
EDIT: Diese Antwort ist falsch. Eine einzelne Iteration von SHA512 ist schnell , was es für die Verwendung als Passwort-Hashing-Funktion ungeeignet macht. Verwenden Sie stattdessen eine der anderen Antworten.
Sieht für mich gut aus. Ich bin mir jedoch ziemlich sicher, dass Sie base64 nicht benötigen. Sie könnten dies einfach tun:
import hashlib, uuid salt = uuid.uuid4().hex hashed_password = hashlib.sha512(password + salt).hexdigest()
Wenn dies keine Schwierigkeiten verursacht, können Sie die Speicherung in Ihrer Datenbank etwas effizienter gestalten, indem Sie das Salt- und Hash-Kennwort als Rohbytes und nicht als Hex-Zeichenfolgen speichern. Ersetzen Sie dazu
hex
durchbytes
undhexdigest
mitdigest
.quelle
salt
ist in der Datenbank gespeichert und das salzige Hash-Passwort auch.Basierend auf den anderen Antworten auf diese Frage habe ich einen neuen Ansatz mit bcrypt implementiert.
Warum bcrypt verwenden?
Wenn ich das richtig verstehe, ist das Argument, das verwendet
bcrypt
werden muss,SHA512
dassbcrypt
es langsam ausgelegt ist.bcrypt
Außerdem können Sie anpassen, wie langsam es beim ersten Generieren des Hash-Passworts sein soll:# The '12' is the number that dictates the 'slowness' bcrypt.hashpw(password, bcrypt.gensalt( 12 ))
Langsam ist wünschenswert, denn wenn eine böswillige Partei den Tisch mit den gehashten Passwörtern in die Hände bekommt, ist es viel schwieriger, sie brutal zu erzwingen.
Implementierung
def get_hashed_password(plain_text_password): # Hash a password for the first time # (Using bcrypt, the salt is saved into the hash itself) return bcrypt.hashpw(plain_text_password, bcrypt.gensalt()) def check_password(plain_text_password, hashed_password): # Check hashed password. Using bcrypt, the salt is saved into the hash itself return bcrypt.checkpw(plain_text_password, hashed_password)
Anmerkungen
Ich konnte die Bibliothek ziemlich einfach in einem Linux-System installieren, indem ich:
Ich hatte jedoch mehr Probleme bei der Installation auf meinen Windows-Systemen. Es scheint einen Patch zu brauchen. Siehe diese Frage zum Stapelüberlauf : py-bcrypt wird unter Win 7 64-Bit-Python installiert
quelle
py-bcrypt
das alte Pypi-Paket zu sein und wurde seitdem in umbenanntbcrypt
.Das Schlaue ist nicht, die Krypto selbst zu schreiben, sondern etwas wie passlib zu verwenden: https://bitbucket.org/ecollins/passlib/wiki/Home
Es ist leicht, das Schreiben Ihres Kryptocodes auf sichere Weise durcheinander zu bringen. Das Schlimme ist, dass Sie es bei Nicht-Krypto-Code oft sofort bemerken, wenn es nicht funktioniert, da Ihr Programm abstürzt. Während Sie mit Kryptocode arbeiten, erfahren Sie dies oft erst, wenn es zu spät ist und Ihre Daten kompromittiert wurden. Daher denke ich, dass es besser ist, ein Paket zu verwenden, das von jemand anderem geschrieben wurde, der sich mit dem Thema auskennt und auf kampferprobten Protokollen basiert.
Passlib hat auch einige nette Funktionen, die die Verwendung vereinfachen und das Upgrade auf ein neueres Passwort-Hashing-Protokoll erleichtern, wenn sich herausstellt, dass ein altes Protokoll fehlerhaft ist.
Auch nur eine einzige Runde von sha512 ist anfälliger für Wörterbuchangriffe. sha512 ist so konzipiert, dass es schnell ist, und dies ist eine schlechte Sache, wenn Sie versuchen, Passwörter sicher zu speichern. Andere Leute haben lange und gründlich über all diese Probleme nachgedacht, also nutzen Sie dies besser aus.
quelle
hashlib
ist für kryptografische Hash-Funktionen.passlib
dient zum sicheren Speichern von Passwörtern. Sie sind nicht dasselbe (obwohl viele Leute so zu denken scheinen ... und dann werden die Passwörter ihrer Benutzer geknackt).passlib
Erzeugt sein eigenes Salt, das in der zurückgegebenen Hash-Zeichenfolge gespeichert ist (zumindest für bestimmte Schemata wie BCrypt + SHA256 ) - Sie müssen sich also keine Sorgen machen.Damit dies in Python 3 funktioniert, müssen Sie beispielsweise UTF-8 codieren:
hashed_password = hashlib.sha512(password.encode('utf-8') + salt.encode('utf-8')).hexdigest()
Andernfalls erhalten Sie:
quelle
Ab Python 3.4
hashlib
enthält das Modul in der Standardbibliothek Funktionen zur Schlüsselableitung , die "für sicheres Passwort-Hashing ausgelegt sind" .Verwenden Sie also eines davon, z. B.
hashlib.pbkdf2_hmac
mit einem Salz, das erzeugt wird ausos.urandom
:from typing import Tuple import os import hashlib import hmac def hash_new_password(password: str) -> Tuple[bytes, bytes]: """ Hash the provided password with a randomly-generated salt and return the salt and hash to store in the database. """ salt = os.urandom(16) pw_hash = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000) return salt, pw_hash def is_correct_password(salt: bytes, pw_hash: bytes, password: str) -> bool: """ Given a previously-stored salt and hash, and a password provided by a user trying to log in, check whether the password is correct. """ return hmac.compare_digest( pw_hash, hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000) ) # Example usage: salt, pw_hash = hash_new_password('correct horse battery staple') assert is_correct_password(salt, pw_hash, 'correct horse battery staple') assert not is_correct_password(salt, pw_hash, 'Tr0ub4dor&3') assert not is_correct_password(salt, pw_hash, 'rosebud')
Beachten Sie, dass:
os.urandom
verwendet immer eine kryptografisch sichere Zufallsquellehmac.compare_digest
, verwendet inis_correct_password
, ist im Grunde nur der==
Operator für Strings, aber ohne die Fähigkeit zum Kurzschließen, was es immun gegen Timing-Angriffe macht. Das bietet wahrscheinlich keinen zusätzlichen Sicherheitswert , aber es tut auch nicht weh, also habe ich es verwendet.Eine Theorie darüber, was einen guten Passwort-Hash ausmacht, und eine Liste anderer Funktionen, die zum Hashing von Passwörtern geeignet sind, finden Sie unter https://security.stackexchange.com/q/211/29805 .
quelle
passlib scheint nützlich zu sein, wenn Sie Hashes verwenden müssen, die von einem vorhandenen System gespeichert wurden. Wenn Sie die Kontrolle über das Format haben, verwenden Sie einen modernen Hash wie bcrypt oder scrypt. Zu diesem Zeitpunkt scheint bcrypt von Python aus viel einfacher zu verwenden zu sein.
passlib unterstützt bcrypt und empfiehlt die Installation von py-bcrypt als Backend: http://pythonhosted.org/passlib/lib/passlib.hash.bcrypt.html
Sie können py-bcrypt auch direkt verwenden, wenn Sie passlib nicht installieren möchten. Die Readme-Datei enthält Beispiele für die grundlegende Verwendung.
Siehe auch: Verwendung von scrypt zum Generieren von Hash für Kennwort und Salt in Python
quelle
Ich möchte keinen alten Thread wiederbeleben, aber ... wer eine moderne, aktuelle, sichere Lösung verwenden möchte, verwendet argon2.
https://pypi.python.org/pypi/argon2_cffi
Es hat den Passwort-Hashing-Wettbewerb gewonnen. ( https://password-hashing.net/ ) Es ist einfacher zu verwenden als bcrypt und sicherer als bcrypt.
quelle
Erstens importieren: -
import hashlib, uuid
Ändern Sie dann Ihren Code entsprechend in Ihrer Methode:
uname = request.form["uname"] pwd=request.form["pwd"] salt = hashlib.md5(pwd.encode())
Übergeben Sie dann dieses Salt und entfernen Sie den Namen in Ihrer SQL-Datenbankabfrage. Unter der Anmeldung befindet sich ein Tabellenname:
sql = "insert into login values ('"+uname+"','"+email+"','"+salt.hexdigest()+"')"
quelle