Probleme mit hashlib

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
enricob
User
Beiträge: 2
Registriert: Montag 20. März 2017, 19:20

Hallo liebe Python Community,

ich stehe vor einem mich sehr verwirrenden Problem und bin auch der Suche nach Hilfe. Im Rahmen einer Webanwendung möchte ich Werte in eine Datenbank abspeichern (keine Passwörter). Um diese vor Veränderung zu schützen ist der Ansatz vor Abspeichern eine Prüfsumme mit einem nur der Applikation bekannten geheimen Schlüssel zu bilden und dieses in einem eigenen Feld abzuspeichern. Bei Lesen des Wertes aus der Datenbank wird erneut die Prüfsumme gebildet und mit der in der Datenbank hinterlegten verglichen. Somit erhalte ich eine Garantie, dass die Inhalte niemand unterwegs verändert hat.

Soviel zur Einleitung. Aktuell arbeite ich mit einer für Passwörtern geeigneten Bibliothek (hashlib). Dabei passiert etwas sehr merkwürdiges. Ich bilde meinen Hashwert so: hash = Hash(values + SECRET) und vergleiche anschließend über die dafür bereitgestellte Funktion Verify(values + SECRET, hash). Das funktioniert Inline total gut! Speichere ich den erzeugten Hashwert allerdings ab und möchte diesen vergleichen, funktioniert es rein zufällig. Entweder habe ich den Hash Algorithmus mit Salt nicht richtig verstanden oder ich mache etwas grundlegend falsch :(.

Hier mein Code:

Code: Alles auswählen

import json
from passlib.hash import argon2


values = json.dumps({'id': 1, 'unique': 'site1', 'version': 1})
SECRET = b'\x9f/)\x82\x81A\xbd6$\xbd\t\x8d\xcc\xf78\x18\x84_\x91\xd1\xf3\xe5\xfc\x9f\xa7\xf1\x05\x8b\xfbPAR'
hash_neu = argon2.hash(values + str(SECRET))
print(hash_neu)
# ergibt immer true
print(argon2.verify(values + str(SECRET), hash_neu))


alter_hash = '$argon2i$v=19$m=512,t=2,p=2$Oodwbk3pfU/JmfOe8/6/Nw$AWCUk3GrIyAJkYWxwKZGVw'
# ergibt zufällig true/false
print(argon2.verify(values + str(SECRET), alter_hash))

Vielen Dank für Rückmeldung und viele Grüße,
Enrico
Zuletzt geändert von Anonymous am Montag 20. März 2017, 23:28, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@enricob: Was auf jeden Fall ein Problem sein wird ist das Wörterbücher keine Ordnung haben, also nicht klar ist das `values` bei diesem Code immer den gleichen Wert haben wird. Oder anders herum: Bei verschiedenen Programmläufen wird auch bei gleichem Inhalt des Wöterbuchts `values` unterschiedlich sein.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@enricob: Wörterbücher sind nicht sortiert und eine Datenstruktur kann durch viele verschiedene JSON-Repräsentationen dargestellt werden. Daher ist das bilden eines Hash-Wertes über die Bytes einer JSON-Repräsentation nicht eindeutig. Du mußt also eine eindeutige Repräsentation wählen, z.B:

Code: Alles auswählen

values = "{0[id]}/{0[unique]}/{0[version]}/{1}".format({'id': 1, 'unique': 'site1', 'version': 1}, SECRET)
Wenn Du nur auf Unverändertheit prüfen willst, reicht ein schneller guter Hash-Algorithmus wie sha256 aus hashlib ohne Geheimnis aus. Passwort-Hashes sind absichtlich langsam, damit man möglichst wenig Passwörter pro Sekunde durchprobieren kann, was hier aber gar nicht nötig ist. Das Geheimnis ist auch unnötig, da ein guter Hash-Algorithmus absichtliche Kollisionen so gut wie unmöglich macht.
enricob
User
Beiträge: 2
Registriert: Montag 20. März 2017, 19:20

@BlackJack, @Sirius3: Vielen Dank für eure Antworten. Ich bin tatsächlich gestern Abend noch selber darauf gekommen, dass irgend etwas mit dem JSON nicht passt, aber genau den Fehler hatte ich nicht im Blick. Ich habe jetzt, wie vorgeschlagen, in einem statischen String formatiert, damit der Wert immer gleich ist.

Als Hintergrund, ich greife auf so eine ungewöhnliche Methode zurück, weil die Anwendung im GxP-Umfeld zum Einsatz kommen soll und aktuell von Behörden wie der FDA in hohem Maß auf Datenintegrität geschaut wird. Mit diesem Ansätzen versuche ich auf die hohen Anforderungen mit state of the art Technologie zu reagieren. Würde ich ohne ein SECRET arbeiten, ließe sich die Prüfsumme in der Datenbank mit dem veränderten Wert ersetzen. In meinem Konzept kommen für Audit Trail Tabellen keine Trigger zum Einsatz, um bei der Datenbank Auswahl auf Kundenseite möglichst flexibel zu sein. Die Audit Trail Funktionalität wird auch über Funktionen aus der Applikation gesteuert. Dadurch ist aber die Manipulation der eigentlichen Daten nicht geschützt, weil Updates durch DB-User nicht geloggt werden. Daher das SECRET ;).
Antworten