Charset-unabhängiger Hash aus String?

mccae

Senfdazugeber
Hallo!

Ich habe folgendes Problem:

Ich möchte gerne Strings einlesen und diese vergleichen.
Dazu generiere ich aus den Strings einen MD5 Hash.

Jedoch kommt es vor, dass eine Maschine ein Charset nutzt, welches bestimmte Symbole nicht unterstützt (Seien es Umlaute, chinesische oder gar arabische Zeichen).

Ein Beispiel:

Das Wort "Möbelmann" eingegeben auf einem Windows System ergibt den Hash:

dbe574d5ee57404a616e7e510833391e

Sobald man aber versucht auf Linux so einen Hash zu generieren (mit US-ASCII Zeichensatz), ergibt sich dieser hier:

278255ea1633265c03b816e9f8952f18

Auf dem selben System ergibt eine Modifikation des Sonderzeichens auf ü (Mübelmann) auch:

278255ea1633265c03b816e9f8952f18


Wie kann ich jetzt also für User "Möbelmann" eine einzigartige ID generieren die auf allen Systemen gleich ist und immer gleich sein wird?

So sachen wie die getBytes(String charset) hab' ich schon durchprobiert...


Ach, und falls die Frage kommen soll' worum es eigentlich geht:

Es geht um ein Client Server Szenario bei dem gegenseitig Objekte ausgetauscht werden.
Wenn sich ein User einloggt, wird sein übertragener Username mit einer Serverseitigen UserDB verglichen.

Zuerst habe ich das mit einfachen Strings gemacht, die sind aber auf Systemen mit verschiedenen default Charsets anders.
Deshalb habe ich mich dazu entschieden Hash-Strings zu benutzen, da die Zeichen von 0-9 , A-F ja überall gleich sind (glaub ich zumindest).

Nun will ich wissen, wie ich eine korrekte ID generieren, bzw. einen Hash erzeugen kann. Dabei ist der Datentyp egal.

Kann mir jemand helfen?

mfg
Martin
 
Zuletzt bearbeitet:
Warum gehst du vorm Registrieren/Einloggen nicht einfach das Passwort durch, und ersetzt alle Buchstaben/Zeichen, die nicht im englischen Vorkommen, durch ein vorgegebenes Zeichen, z. B. '4'. Dadurch dürfte es funktionieren, durch die Nummer nimmt eventuell die Sicherheit zu, und kein Nutzer merkt was.
 
Du musst eben Sicherstellen, dass beim erzeugen des Hashcodes immer der selbe Zeichensatz verwendet wird. Aber es wundert mich, dass du auf verschiedenen Systemen verschiedene Ergebnisse bekommst, denn Java verwendet überall unicode.

Java:
"mein Toller String!".getBytes("UTF8");

Wie erzeugst du denn deine obigen Beispiel Hashs?
 
Hallo,

Vielen Dank für die Antworten!

Warum gehst du vorm Registrieren/Einloggen nicht einfach das Passwort durch, und ersetzt alle Buchstaben/Zeichen, die nicht im englischen Vorkommen, durch ein vorgegebenes Zeichen, z. B. '4'. Dadurch dürfte es funktionieren, durch die Nummer nimmt eventuell die Sicherheit zu, und kein Nutzer merkt was.

Jedoch existieren tausende, wenn nicht gar zehntausende Zeichen. All den Zeichen einen Wert zuzuweisen ist unmöglich.

Du musst eben Sicherstellen, dass beim erzeugen des Hashcodes immer der selbe Zeichensatz verwendet wird. Aber es wundert mich, dass du auf verschiedenen Systemen verschiedene Ergebnisse bekommst, denn Java verwendet überall unicode.

Ich hole die Strings direkt mit getText() aus JTextFields, bzw. hol' ich mir ein char Array aus PasswordFields.

Der String hat dann das default-encoding des Systems.
Wenn ich diesen String als Objekt zu einem Server übertrage, und das Zielsystem ein anderes default-Charset verwendet werden unbekannte Symbole ersetzt - meist zu Fragezeichen. Dadurch ändert sich auch der Ascii-Code der Sonderzeichen und es geht Information verloren.

Wenn ich jetzt auf jedem System für eben diesen String ein fixes Charset benutze, (string.getBytes("UTF8")), kann dies durchaus funktionieren, jedoch nicht garantiert.
Es kann vorkommen, dass ein System ein Encoding benutzt, welches sich nicht ohne Nebeneffekte zum Beispiel zu "UTF8" konvertieren lässt. (Wenn ein System zum Beispiel UTF16 kommt Müll raus).

Das ist das GROßE Problem. Konvertieren klappt nicht immer.
 
Wenn ich diesen String als Objekt zu einem Server übertrage, und das Zielsystem ein anderes default-Charset verwendet werden unbekannte Symbole ersetzt - meist zu Fragezeichen.

Da wird nix ersetzt. Die Bytes bleiben doch beim übertragen die gleichen. Es ist einfach eine Frage der Interpretation, also des Charsets.
 
Da wird nix ersetzt. Die Bytes bleiben doch beim übertragen die gleichen. Es ist einfach eine Frage der Interpretation, also des Charsets.

Eben nicht.

Java:
String s = new String("Möbelmann");
		
byte[] array = s.getBytes(Charset.forName("ISO-8859-1"));
byte[] array2 = s.getBytes(Charset.forName("UTF-8"));
		
System.out.println(Arrays.toString(array));
System.out.println(Arrays.toString(array2));

Output:

Code:
[77, -10, 98, 101, 108, 109, 97, 110, 110]
[77, -61, -74, 98, 101, 108, 109, 97, 110, 110]

Verstehst du was ich meine?

Wenn ich jetzt hashes aus den Strings errechnen soll, kommt auf Systemen mit anderem Charset immer etwas anderes raus.
 
Zuletzt bearbeitet:
Da UTF-8 überall vorhanden ist, musst du einfach konsequent UTF-8 nutzen. Oder auch ASCII oder ähnliches. Mehr fällt mir nicht ein.
 
Da UTF-8 überall vorhanden ist, musst du einfach konsequent UTF-8 nutzen. Oder auch ASCII oder ähnliches. Mehr fällt mir nicht ein.

Na ja, da taucht ja wieder das Problem auf, dass man das default Charset nur beim Starten der JVM setzen kann...

Kennt den niemand eine einfache Lösung für diese Unstimmigkeit?
 
Zurück