2016-10-04 2 views
2

Ich erstelle eine URL, die aus einem Token für den einmaligen Gebrauch besteht, und sende sie per E-Mail an einen Benutzer. Der Benutzer sollte auf diesen Link klicken und zu einer Seite weitergeleitet werden, die das Token validiert und einige Aktionen ausführt.Gespeicherte gesalzene Token- und Token-Vergleiche

Auf der Datenbankseite, ich speichere dieses Token (Hashed und gesalzen, aus Sicherheitsgründen). Das Problem ist, dass ich einige Schwierigkeiten habe, das Token zu validieren, da ich, wie ich es speichere, nicht dasselbe Salz für dasselbe Token erzeugen kann. Und deshalb kann ich dieses Salz nicht mit denen vergleichen, die ich aufbewahrt habe.

# Retrieving or creating object usertokens 
usr, created = UserToken.objects.get_or_create(email=email) 
# Adding a new token 
token = uuid.uuid4().hex 
usr.token = make_password(token) # Stores in the local database the salted and hashed token 
usr.save() 

Diese make_password Methode Ich verwende in django.contrib.auth.hashers definiert.

Mit dieser Methode kann ich nicht zweimal das gleiche Salz aus dem gleichen Token generieren.

>>> token = 'test' 
>>> enc_token1 = make_password(token) 
>>> enc_token2 = make_password(token) 
>>> enc_token1 == enc_token2 
False 

Diese führt jedoch helfen Sie mir nicht auf das Token aus meiner Datenbank den Eintrag abrufen entspricht, und ich kann es nicht bestätigen kann.

+0

Jetzt gibt es etwas, was ich noch nie zuvor gehört habe; _Hashed und gesalzene Tokens_. Möchten Sie etwas Ketchup mit diesen Token? ..... –

+2

Alle Witze beiseite, ist der Zweck des Hashing und Salzens, dass das ursprüngliche Passwort nicht aus der Hash-Zeichenfolge abgerufen werden kann. Bei Passwörtern ist dies ein Problem, da Passwörter häufig in irgendeiner Weise wiederverwendet werden und Sie möchten, dass sie auch nach einer möglichen Sicherheitsverletzung geheim bleiben. Token können einfach zurückgesetzt werden, und dann hat der Angreifer absolut keinen Nutzen mehr für die erworbenen Token. Wie Sie bemerkt haben, gibt es keine effiziente Möglichkeit, nach einem gesalzenen und gehashten Token zu fragen. Aus diesem Grund werden Tokens normalerweise als Nur-Text gespeichert. Aus welchen Sicherheitsgründen möchten Sie die Hashes speichern? – knbk

Antwort

1

Die Verwendung einer einfachen String-Gleichheitsüberprüfung von zwei Hash- und Salted-Tokens funktioniert nicht. Die Django docs for password management bieten eine sehr einfache Methode, in der django.contrib.auth.hashers Namespace, der das alles für Sie Griffe:

>>> token = 'test' 
>>> enc_token1 = make_password(token) 
>>> check_password('test', enc_token1) 
True 

Die check_password Methode hat ein paar Dinge hinter der Haube, wie zu überprüfen, ob der Hash-Algorithmus verändert hat. Es gibt das Ergebnis der verify Methode eines Algorithmus zurück, der die Basisklasse BasePasswordHasher implementiert. Hier ist ein Beispiel für eine Implementierung von den source of the PBKDF2PasswordHasher:

def verify(self, password, encoded): 
    algorithm, iterations, salt, hash = encoded.split('$', 3) 
    assert algorithm == self.algorithm 
    encoded_2 = self.encode(password, salt, int(iterations)) 
    return constant_time_compare(encoded, encoded_2) 

Beachten Sie, wie das Salz durch Aufspalten des encoded_string auf ‚$‘ gefunden wird, da das Django docs note dass

Das Passwort-Attribut eines Benutzerobjekts ist eine Zeichenfolge in diesem Format:

<algorithm>$<iterations>$<salt>$<hash> 
+0

danke für die antwort. Das Problem bei der Verwendung von check_password liegt darin, dass ich sowohl die codierte Zeichenfolge als auch das Token kennen muss. In meinem Fall ist meine Eingabe das Token und ich speichere viele codierte Strings in meiner Datenbank. Verzeihen Sie, wenn ich falsch liege, aber wenn ich die check_password-Methode verwende, scheint es, dass ich einen paarweisen Vergleich zwischen dem Token und allen gespeicherten codierten Strings durchführen soll. Vielleicht wird es teuer. – revy

+0

Denken Sie daran, dass ein Hashalgorithmus von Natur aus unidirektional ist. Wenn Sie Hashes verifizieren, ohne die ursprüngliche Zeichenkette zu kennen, dann vereiteln Sie ziemlich genau den Zweck eines Hashes an erster Stelle, nämlich einen Angreifer zu verhindern, der die Hashes den Klartext kennt. – brianpck