crypt und bottle

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
gNeandr
User
Beiträge: 68
Registriert: Sonntag 11. Mai 2014, 16:48

Beim Versuch eine Login Seite zu bauen und die Eingaben von Username und pw gegen verschlüsselte Werte zu vergleichen stosse ich auf Schwierigkeiten.

Zur Verschlüsselung finde ich https://www.dlitz.net/software/python-pbkdf2/
Allerdings habe ich bereits bei den Beispielen Verständnis Probleme. Ich wäre der Meinung gewesen der Aufruf

Code: Alles auswählen

crypt('string')
gibt immer den gleichen Rückgabewert, aber das ist nicht der Fall!?

Code: Alles auswählen

>>> crypt("string")
u'$p5k2$$bafI079U$JgjuyTZn.6cJK5eVAvu9WDxkaUnsqkXr'
>>> crypt("string")
u'$p5k2$$9S1fFita$P1EPFGQlN6asWBun7/OJRpjvm1KmDet3'
Wo ist mein Knoten(Fehler) :?:
BlackJack

@gNeandr: Wenn Du kein „salt” angibst wird halt zufällig eines erzeugt und damit ist das Ergebnis natürlich jedes mal anders.
gNeandr
User
Beiträge: 68
Registriert: Sonntag 11. Mai 2014, 16:48

@ BlackJack
Danke. Ja das mit salt funktioniert ... aber auf der Seite https://www.dlitz.net/software/python-pbkdf2/ ist das nicht beschrieben bzw. dort sind einige Fehler in den Beispielen.

Gibt es eine "zuverlässigere" Seite, die zB. beschreibt:

Code: Alles auswählen

crypt('string', 'salt', 500)
und nicht wie auf der genannten keine oder falsche Infos?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du könntest in den Code schauen.
Das Leben ist wie ein Tennisball.
gNeandr
User
Beiträge: 68
Registriert: Sonntag 11. Mai 2014, 16:48

@EyDu

Brrrr, aber zumindest ist dort in Zeile 32

Code: Alles auswählen

# from pbkdf2 import PBKDF2
vs der web Seite

Code: Alles auswählen

from PBKDF2 import PBKDF2
Anderes habe ich nicht verglichen .. vllt später mal
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

gNeandr hat geschrieben:@ BlackJack
Danke. Ja das mit salt funktioniert ... aber auf der Seite https://www.dlitz.net/software/python-pbkdf2/ ist das nicht beschrieben bzw. dort sind einige Fehler in den Beispielen.
Da sind keine einzigen Fehler zu machen. Der Fehler liegt in deinen falschen Annahmen darüber wie man mit Passwörter umgeht.

Passwörter speichert man weder im plaintext, noch verschlüsselt. Man produziert einen Hash mit einer Key Derivation Function (KDF), den man mit den Parametern die man für den Hash und dem Passwort rekonstruieren kann. Das Ergebnis ist dass man das Passwort selbst gar nicht mehr und die Korrektheit eines Passwortes nur mit dem Hash kontrollieren kann.

Das

Code: Alles auswählen

crypt('foo')
mit jedem Aufruf einen anderen Hash zurückgibt ist also ein Feature. Dies verhindert dass ein Angreifer sich mit sogenannten Rainbow Tables - die quasi Wörterbücher in denen steht welche Passwörter zu welchen Hashes korrespondieren - auf einen Angriff vorbereiten und somit Rechenleistung einsparen kann.
Gibt es eine "zuverlässigere" Seite, die zB. beschreibt:

Code: Alles auswählen

crypt('string', 'salt', 500)
und nicht wie auf der genannten keine oder falsche Infos?
Die Seite beschreibt es schon größtenteils korrekt, das einzige Problem sind ist dass die Beispiele Hashes mit == Vergleichen und deswegen anfällig für timing basierte side-channel Attacks sind.

Code: Alles auswählen

hash = crypt('password')
produziert einen Hash. Ob ein Passwort zu diesem Hash korrespondiert prüfst du dann mit

Code: Alles auswählen

crypt('password', hash)

Code: Alles auswählen

crypt('string', 'salt', 500)
zu nutzen ist *nicht* korrekt, es ist ein massiver Fehler.

Zum einen generiert die library von selbst einen zufälligen Salt, zum anderen ist sie auch in der Lage Passwörter gegen einen Hash zu prüfen. Du musst und solltest zu keinem Zeitpunkt den Salt anfassen. Zum anderen ist 500 eine viel zu niedrige Zahl an Iterationen für PBKDF2, da ist leider auch der default der Library schlecht gewählt. Du solltest dir überlegen wieviel Zeit du in Hashing investieren kannst und dann für dass kürzeste erlaubte Passwort die Anzahl der Iterationen soweit nach oben schrauben bis du diese Zeit erreichst. Um etwas konkreter zu werden: Django empfiehlt seit kurzem 100.000 Iterationen. Man sollte schauen dass man eher etwas darüber als darunter wählt.

Noch besser wäre es allerdings wenn du passlib, speziell den CryptContext verwenden würdest. Die Library hat eine sicherere API, die timing side-channel Attacken ausschliesst. Außerdem abstrahiert sie vom dem verwenden Algorithmus und dessen Parametern und du kannst diese somit recht einfach durch neuere ersetzen und existierende Hashes upgraden. Zumindest die Anzahl der Iterationen wirst du nämlich regelmäßig erhöhen müssen und auch pbkdf2 wird wahrscheinlich irgendwann prinzipiell als unsicher gelten. Darauf sollte man mit einer Konfigurationsänderung reagieren können.
Antworten