it-swarm.com.de

Wie sicher ist Javas hashCode ()?

In unseren Ansichten in einer Java Webanwendung) verwende ich derzeit hashCode als IDs für Objekte, damit ich am Serverende dasselbe Objekt zurückerhalten kann.

Ich frage mich jedoch, wie sicher Javas hashCode wirklich ist, damit jemand es nicht hacken kann, um die Objekte anderer Personen abzurufen. Ich bin nicht sehr geneigt zum Verschlüsselungs-Entschlüsselungs-Mechanismus, da er viel CPU verursacht.

Welche anderen schnell noch sicher Mechanismen kann ich verwenden?

21
Novice User

Sie brechen eines der Tabus hashCode(); Sie verwenden die Ausgabe als Schlüsselkennung. Das ist falsch.

Sie sehen, die Ausgabe von hashCode() (in der Standardimplementierung) ist eine 32-Bit-Ganzzahl ohne Vorzeichen, das sind ungefähr 4 Milliarden eindeutige Hashcodes. Klingt ziemlich viel? Nun, nicht so sehr. Das Anwenden des Geburtstagsproblems zeigt in diesem Fall, dass bei ungefähr 77000 Objekten eine Kollisionswahrscheinlichkeit von ungefähr 50% besteht. 50% ige Chance, dass zwei Objekte denselben Hashcode haben.

Ein weiteres Problem ist, dass sich die Implementierung von hashCode() von einer Version Java Version zur anderen) ändern kann. Es ist nicht als permanente Kennung eines Objekts gedacht, daher gibt es nichts, was es dazu zwingt Versionsübergreifend konsistent sein.

Wenn Sie darauf bestehen, Hashes als Objektkennungen zu verwenden, ist es viel besser, eine eigene Methode anstelle von hashCode() für Ihre Schlüsselkennungen zu verwenden (z. B. getMySpecialHashKey(). Sie können etwas verwenden wie MessageDigest.getInstance("SHA-256"), um das Objekt in einen netten 256-Bit-Schlüssel zu verdauen.

Meine Empfehlung: Machen Sie Schluss mit der ganzen Idee, das Objekt zu hashen, und generieren Sie stattdessen eine zufällige Kennung für Ihr Objekt, wenn Sie es erstellen. Etwas in der Art von (in Java)

SecureRandom secRand = new SecureRandom();
byte[] objIdBytes = new byte[16]; //128-bit
secRand.nextBytes(objIdBytes);
String objId = Base64.encodeBase64String(objIdBytes); //Here's your ID

Sie scheinen den Zugriff auf ein Objekt auch nur an die Kenntnis seines Schlüssels zu binden. Das ist auch falsch. Ein ordnungsgemäßes berechtigungsbasiertes Modell mit ordnungsgemäßer Authentifizierung und Autorisierung ist erforderlich.

54
Adi

Java hashCode() sollte niemals so verwendet werden. Tu es niemals! Es ist sogar legal (obwohl nicht empfohlen), dass alle Instanzen einer Klasse denselben Hashcode zurückgeben. Der Vertrag in Java ist "zwei Objekte, die als gleich angesehen werden, müssen denselben Hashcode haben". Nicht mehr und nicht weniger. Es wäre beispielsweise gültig, Hashcode 1 für alle ungeraden Zahlen und 0 für zurückzugeben sogar diejenigen.

hashCode wird für eine schnellere Suche in Sammlungen wie HashMap verwendet und Kollisionen sind erwartet.

Viele Klassen definieren ihre eigene Version von hashCode(), und wenn Sie den Code kennen, können Sie den Hashcode oft leicht erkennen oder erraten.

Das ist also absolut unsicher.

30
Axel

Es ist nicht kryptografisch sicher, da dies nicht Teil seiner Anforderungen ist.

Die Implementierung des HashCodes ist ein Implementierungsdetail bis zur JVM und kann für verschiedene Objekttypen unterschiedlich sein (Objekte können die HashCode-Methode überschreiben und eine eigene Implementierung bereitstellen).

Der Zweck des Java hashCode besteht darin, Objekte beim Platzieren in Hash-Tabellen zu identifizieren. Die Hauptanforderung ist die Leistung. Außerdem hat er eine Länge von nur 32 Bit, was zu kurz ist, um Kollisionen zu vermeiden Der beabsichtigte Zweck (Hash-Tabellen) von zwei Objekten mit demselben Hash ist nur ein kleines Problem. Die Identifizierung von Objekten ohne Mehrdeutigkeitskollisionen ist jedoch ein großes Problem.

Im Allgemeinen sollten Sie jedoch keinem Benutzer erlauben, auf ein Objekt zuzugreifen, nur weil er den Hash-Code des Objekts kennt. Verwenden Sie ein ordnungsgemäßes Rechteverwaltungsschema. Verwenden Sie kennwortgeschützte Benutzerkonten, bei denen jeder Benutzer einen anderen Satz von Berechtigungsparametern hat. Wenn der Benutzer versucht, auf ein Objekt zuzugreifen, überprüfen Sie, ob seine Berechtigungen dies zulassen, und lehnen Sie die Anforderung ab, wenn dies nicht der Fall ist.

12
Philipp

Es ist sicherlich nicht sicher genug für eine Situation, in der das Erraten von Werten Informationen enthüllen kann.

Zumindest einige der Überschreibungen sind nicht einmal sicher genug, um angesichts beliebiger vom Benutzer ausgewählter Eingaben als Hash-Code verwendet zu werden (mit Javas String.hashCode() ist es wirklich einfach, einen Hash-DoS-Angriff gegen irgendetwas durchzuführen überschreiben).

In Fällen, in denen Sie einen Bezeichner wünschen, empfehle ich, einen einfachen Bezeichner zu verwenden (z. B. einen numerischen Schlüssel in einer Datenbank, eine atomar inkrementierte Ganzzahl, die ein Schlüssel für eine Hash-Tabelle ist usw.) und dann einen kryptografischen Hash davon und ein Salt anzuhängen .

Das heißt, Ihre öffentlich zugängliche ID hätte die Form (in sprachunabhängiger Form):

Concatenate(PrivateID, HexString(SHA256(UTF8Bytes(Concatenate(Salt, PrivateID)))))

(Sie können einen Teil des Hashs für eine kleinere ID entfernen, um die Zeit bis zur Brute-Force zu verkürzen.).

Dann kann die private ID als Teilzeichenfolge abgerufen und die vollständige ID erneut überprüft werden. Das allgemeine Verfahren lässt sich auch leicht zwischen Sprachen portieren.

Die Handvoll CPU-Zyklen, die dies kosten wird, werden im Vergleich zum Rest des Systems keine großen Auswirkungen haben, es sei denn, Ihr System ist so trivial, dass Sie sowieso nicht viel CPU verwenden, es sei denn, Sie führen dies aus etwas wirklich stromsparendes (wie in, weit weniger leistungsstark als ein billiges Telefon) wird es kein Problem sein.

In Fällen, in denen Sie tatsächlich einen Hash-Code als Hash-Code verwenden möchten und sich mit benutzerdefinierten Eingaben befassen müssen, verwenden Sie einen Startwert-Hash-Algorithmus (z. B. SpookyHash) und stützen Sie Ihren Startwert auf die Startzeit (oder noch besser) , eine Mischung aus Startzeit und der Zeit, zu der Sie den Hash-Container erstellen). (Nichts mit kryptografischen Hashes zu tun, daher können sie viel schneller sein. Das nur Sicherheitsrisiko, das dadurch vermieden wird, ist Hash-DoSing.).

2
Jon Hanna