PHP - Wie Hash'e Ich ein string?

B

BloodSteam

Guest
Hallo,
ich hab auf meiner Internetseite ein Login System und würde gerne auch den Benutzernamen Hashen.

Ich hab mal folgendes versucht und leider funktioniert es nicht:
Code:
$LoginHash = hash("adler32",$login);

Wieso muss bei gleichem Wort/Login immer ein anderer Hash herauskommen?
 
Und was ist wenn du statt $login einen fixen String verwendest? Ist der Hash dann auch immer anders?

btw: Ich würd als Algorithmus eher etwas wie md5 nehmen.
 
Hi erstmal,

Ich hab mal folgendes versucht und leider funktioniert es nicht
Mhh wenn ich mir die "hash" Funktion anschaue, frage ich mich wo du du den Hashing-Algorythmus festlegst.

Ich würde das so machen:
$LoginString = "adler32";
$LoginHash = md5($LoginString);
Dann halt Abgleich mit dem Hash in der Datenbank.

Wirklich sicher ist das jedoch nicht.
Hier weitere Info's dazu:
PHP: Password Hashing - Manual


Wieso muss bei gleichem Wort/Login immer ein anderer Hash herauskommen?
Ein Hash ist eine Prüfsumme die in Verbindung zu den geprüften Daten entsteht.
Also entweder war dein String nicht "Bit-identisch". Oder es liegt an deinem Code.
 
Ich denke es geht hier darum, Benutzernamen zu maskieren, damit jemand, der Zugriff auf die Tabelleninhalte bekommt, nicht den Passwort-Hash einem bestimmten Nutzer zuordnen kann. Das funktioniert aber nur bedingt und vor allem bringt es einem nicht allzuviel. Man bekommt immer ein Hash mit fester Länge, wodurch direkt zu sehen ist, mit welcher Tiefe dieser arbeitet und man kann damit die Algorithmen eingrenzen. Bei MD5 sind es 32 Stellen. Dann kann man auch den Benutzernahmen vorher hashen und stattdessen nach dem Hash suchen. Wenn du es besser machen willst, dann arbeite auch hier mit einem Salt und hänge ihn an den Hash. Dann benötigt man definitiv die komplette Tabelle, um die Salt's mit dem Benutzernamen zusammen zu hashen und den richtigen zu finden. Das dauert dann auch meist ein kleines bisschen Länger und es ist eher selten, das jemand direkten Zugriff auf die komplette Tabelle hat.

Wenn es dir nur darum geht, zwischen "user" und "User" zu unterscheiden, dann kannst du auch mit der Funktion strcmp nachträglich vergleichen: PHP: strcmp - Manual
Solltest du aber mit einer relationalen Datenbank arbeiten (wovon ich ausgehe), dann kannst du aber auch die WHERE-Klausel mit BINARY erweitern:
Code:
WHERE BINARY username=:username
 
Hi erstmal,


Mhh wenn ich mir die "hash" Funktion anschaue, frage ich mich wo du du den Hashing-Algorythmus festlegst.

Ich würde das so machen:
$LoginString = "adler32";
$LoginHash = md5($LoginString);
Dann halt Abgleich mit dem Hash in der Datenbank.

Wirklich sicher ist das jedoch nicht.
Hier weitere Info's dazu:
PHP: Password Hashing - Manual



Ein Hash ist eine Prüfsumme die in Verbindung zu den geprüften Daten entsteht.
Also entweder war dein String nicht "Bit-identisch". Oder es liegt an deinem Code.
Results: (in microseconds)
1. md4 - 5307.912
2. md5 - 6890.058
3. crc32b - 7298.946
4. crc32 - 7561.922
5. sha1 - 8886.098
6. tiger128,3 - 11054.992
7. haval192,3 - 11132.955
8. haval224,3 - 11160.135
9. tiger160,3 - 11162.996
10. haval160,3 - 11242.151
11. haval256,3 - 11327.981
12. tiger192,3 - 11630.058
13. haval128,3 - 11880.874
14. tiger192,4 - 14776.945
15. tiger128,4 - 14871.12
16. tiger160,4 - 14946.937
17. haval160,4 - 15661.954
18. haval192,4 - 15717.029
19. haval256,4 - 15759.944
20. adler32 - 15796.184
21. haval128,4 - 15887.022
22. haval224,4 - 16047.954
23. ripemd256 - 16245.126
24. haval160,5 - 17818.927
25. haval128,5 - 17887.115
26. haval224,5 - 18085.002
27. haval192,5 - 18135.07
28. haval256,5 - 18678.903
29. sha256 - 19020.08
30. ripemd128 - 20671.844
31. ripemd160 - 21853.923
32. ripemd320 - 22425.889
33. sha384 - 45102.119
34. sha512 - 45655.965
35. gost - 57237.148
36. whirlpool - 64682.96
37. snefru - 80352.783
38. md2 - 705397.844

Ich denke es geht hier darum, Benutzernamen zu maskieren, damit jemand, der Zugriff auf die Tabelleninhalte bekommt, nicht den Passwort-Hash einem bestimmten Nutzer zuordnen kann. Das funktioniert aber nur bedingt und vor allem bringt es einem nicht allzuviel. Man bekommt immer ein Hash mit fester Länge, wodurch direkt zu sehen ist, mit welcher Tiefe dieser arbeitet und man kann damit die Algorithmen eingrenzen. Bei MD5 sind es 32 Stellen. Dann kann man auch den Benutzernahmen vorher hashen und stattdessen nach dem Hash suchen. Wenn du es besser machen willst, dann arbeite auch hier mit einem Salt und hänge ihn an den Hash. Dann benötigt man definitiv die komplette Tabelle, um die Salt's mit dem Benutzernamen zusammen zu hashen und den richtigen zu finden. Das dauert dann auch meist ein kleines bisschen Länger und es ist eher selten, das jemand direkten Zugriff auf die komplette Tabelle hat.

Wenn es dir nur darum geht, zwischen "user" und "User" zu unterscheiden, dann kannst du auch mit der Funktion strcmp nachträglich vergleichen: PHP: strcmp - Manual
Solltest du aber mit einer relationalen Datenbank arbeiten (wovon ich ausgehe), dann kannst du aber auch die WHERE-Klausel mit BINARY erweitern:
Code:
WHERE BINARY username=:username

Bei mir wird es ein bisschen anders verlaufen.

Login kann die gleichen Zeichen haben wie ein Password. Also Zb Dät@_D1No etc.
Login wird zum einlogen benutzt, der Benutzername wird sich vom Login unterscheiden. Die Säule in meiner Tabelle sind auch nicht sichtbar beschriftet. Also weißt du am Ende nicht mal ob du einen Benutzernamen decryptest oder ein Password. (Ich weiß wo was ist :) ).

Mein Plan ist es das Login als eine 1-Way encryption zu machen, (Password wird schon mit password_hash() gehasht) und den Benutzernamen werde Ich als 2-Way encryption machen.
 
Zuletzt bearbeitet:
Die Säule in meiner Tabelle sind auch nicht sichtbar beschriftet. Also weißt du am Ende nicht mal ob du einen Benutzernamen decryptest oder ein Password. (Ich weiß wo was ist :) ).

Security by Obscurity ist ein schlechter Designansatz.
Die Sicherheit sollte gleich bleiben auch wenn der Angreifer das System kennt.
 
Login kann die gleichen Zeichen haben wie ein Password. Also Zb Dät@_D1No etc.
Login wird zum einlogen benutzt, der Benutzername wird sich vom Login unterscheiden. Die Säule in meiner Tabelle sind auch nicht sichtbar beschriftet. Also weißt du am Ende nicht mal ob du einen Benutzernamen decryptest oder ein Password. (Ich weiß wo was ist :) ).
Ich verstehe ehrlich gesagt nicht, was du einem damit sagen willst. Was ist für dich 1-Way und 2-Way Encryption? Soll "Login" bei dir für "Passwort" stehen oder steht es für den eigentlichen Prozess? Wieso drückst du das nicht klarer aus?

Deine Auflistung mit der Geschwindigkeit einzelner Algorithmen sagt zu deiner Entscheidung, Adler32 zu nutzen, garnichts aus. Er ist weder der effizienteste noch der ineffizienteste. Adler32 ist eine reine Prüfsumme und nicht dafür gedacht, Strings zu verschleiern. Denn die liefern wie CRC32 ausschließlich 8-stellige Hashes. Dies erhöht die Kollisionswahrscheinlichkeit drastisch. Im Grunde bringt dir in PHP ein ineffizienter Algorithmus nichts, wenn es von dem Algorithmus in anderen Bibliotheken bereits effizientere Implementierungen gibt. Oder glaubst du wirklich, das ein Angreifer zum Cracken bzw. Bruteforce auch PHP verwendet?

Außerdem bringt es einem nichts, wenn man die Tabellenspalten mit irgendwelchen abstrusen Namen kaschiert. Auf Grund der Tabellen-Inhalte lässt sich darauf schließen, was am Ende was ist. Das Passwort erkennt ein kundiger sofort, gerade wenn es mit der Password-Hash Funktion verarbeitet wurde. Algo$Coast&Hash&Salt erkennt jeder, der es weiß auf einen Blick und schon kannst du die Spalte Schweineschwarte2000 nennen. Er sieht, das es die Passwortspalte ist. Dann hast du noch eine weitere Spalte mit Hashes und er findet keine Benutzernamen. Und schon weiß er, das die Spalte mit den anderen Hashes die gehashten Benutzernamen sein müssen. Den Schritt mit der "maskierten" Spalte kannst du dir also komplett sparen und stellt einen Angreifer vor keine Herausforderung. Da ist es schon deutlich schwieriger, zu einem Passwort den richtigen Benutzernamen bzw. zum Benutzernamen das richtige Passwort zu finden. Aber wie ich schon gesagt habe, wird ein Hash ohne Salt (was übrigens sehr schwer zu implementieren ist) diesen Vorgang auch nicht schwerer machen, weil er den Benutzernamen, den er angreifen will selbst erst einmal hasht und dann nach dem Hash statt nach dem Benutzer sucht.

Und zum Thema "Security by Obscurity". Ein geschlossenes und konfuses System versucht, Schwächen an den sicherheitsrelevanten Komponenten zu kaschieren. Im Idealfall sollte ein Angreifer garnicht zu den Tabellen kommen. Wenn er es dann doch schafft, dann liegt das Problem an einer völlig anderen Stelle. Wenn er also erst einmal so weit ist, dann hilft es auch nicht, den Karren im letzten Moment durch solche Verwirrungen aus dem Dreck zu ziehen. Genauso ist es auch beim Hashen und verschlüsseln. Wenn er bei den Benutzernamen ein Adler32, CRC32, MD5, Sha1 oder What-ever sieht, dann zuckt dieser nur mit den Schulter. Wenn er aber das Passwort mit erhöhtem Kostenfaktor sieht, dann lässt er es meist sowieso bleiben. Das lohnt meistens nicht. Du machst dir also beim kaschieren unnötig Arbeit, bringen tut es dir nichts und weckt nur unnötig die Neugier eines Angreifers. Zudem machst du dir selbst das Leben schwer, wenn es um die Wartung geht.
 
Doublequotes sind bei leeren und einfachen Strings einfach unnötig. Nicht zwingend vom Performance-Mythos her, da liegt der Unterschied wenn es hochkommt maximal im Tausendstel-Bereich, sondern einfach um den Interpreter an der Stelle nicht unnötig "nachschauen" zu lassen, ob Ersetzungsvariablen im String vorhanden sind. Hat keinen signifikanten Impact ist aber einfach unsauber.
 
Doublequotes sind bei leeren und einfachen Strings einfach unnötig. Nicht zwingend vom Performance-Mythos her, da liegt der Unterschied wenn es hochkommt maximal im Tausendstel-Bereich, sondern einfach um den Interpreter an der Stelle nicht unnötig "nachschauen" zu lassen, ob Ersetzungsvariablen im String vorhanden sind. Hat keinen signifikanten Impact ist aber einfach unsauber.

Also einfach
Code:
$bob;
lassen?
 
Ich kenne nicht wirklich den Unterschied zwischen '' und ""
Double-Quotes (") unterstützen das Ersetzen von Variablen durch ihre Inhalte. Außerdem werden Escapesequenzen für Sonderzeichen erlaubt. Das alles kostet aber performance, die sich zwar im Einzelfall nicht bemerkbar, aber auf die Masse sich merklich auf die Skallierbarkeit einer Anwendung auswirken könnten. Desweiteren hat das Einfügen von Variableninhalten in einen String durch Verkettung den Vorteil, das in IDE's sowie Editoren direkt zu sehen ist, wo in einem String sich die variablen Inhalte befinden.
Anhang anzeigen 1003139
Handbuch: PHP: Strings - Manual
 
Bsp.: 2 Variablen - $a="hallo", $b="welt"

Unterschied doppelte und einfache Anführungszeichen
- doppelte Anführungszeichen - php wertet $ etc bei der Ausgabe aus,
- einfache Anführungszeichen - php gibt den String wieder, wertet nichts aus!

gibt folgendes aus:
c="$a; $b" -> gibt den string 'hallo welt' aus
c='$a $b' -> gibt den string '$a $b' aus

.. das ist in etwa der unterschied, ist die selbe Syntax wie in der Bash- bzw. Shell-Programmierung.
Aber daran denken, wenn du einen String angeben bzw. ausgeben willst, sollte man per Default immer
die doppelten Hochkommata nehmen
 
Zurück