2015-02-22 6 views
7

Ich verwende SHA-1, um Duplikate in einem Programm zu erkennen, das Dateien verarbeitet. Es muss nicht kryptographisch stark sein und kann reversibel sein. Ich fand diese Liste der schnellen Hash-Funktionen https://code.google.com/p/xxhash/Schnelle Hash-Funktion mit Kollisionsmöglichkeit in der Nähe von SHA-1

Was wähle ich, wenn ich eine schnellere Funktion und Kollision auf Zufallsdaten in der Nähe von SHA-1 möchte?

Vielleicht ist ein 128-Bit-Hash für die Datendeduplizierung gut genug? (vs 160 bit sha-1)

In meinem Programm wird der Hash auf Chuncks von 0 - 512 KB berechnet.

+0

Verwenden Sie den, den git verwendet. Wenn es gut genug für Git ist, ist es gut genug für Sie! – joop

+1

Git verwendet SHA-1 und die "Hot-Loop" des Git-Workflow ist eindeutig nicht Git-Commit. Das OP und ich selbst sind an Hash-Funktionen interessiert, die für die ~ hot-Schleife sinnvoll sind (z. B. eine In-Mem-Datenbank) und bieten sehr starke Kollisionsgarantien und Bit-Unabhängigkeit usw. – alphazero

+1

CPU "Fast" ist wahrscheinlich irrelevant - Die E/A wird wahrscheinlich fast die gesamte verstrichene Zeit sein. –

Antwort

5

Vielleicht wird Ihnen helfen: https://softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed

Kollisionen selten: FNV-1, FNV-1a, DJB2, DJB2a, SDBM & MurmurHash

Ich weiß nicht, über xxHash aber es sieht auch vielversprechend aus.

MurmurHash ist sehr schnell und Version 3 unterstützt 128bit Länge, würde ich diese wählen. (Implementiert in Java und Scala.)

+0

Danke. Die angenommene Antwort ist empirischer Natur und die Stichprobenmenge ist 2^20, was winzig ist. – alphazero

+0

Es gibt keine allgemein beste Hash-Funktion. Es hängt immer davon ab, was Sie erreichen möchten und was Ihre realen Live-Daten sind. machen Sie Ihre eigenen Tests für Ihren Anwendungsfall;) –

2

Google entwickelt und verwendet (glaube ich) FarmHash für leistungskritisches Hashing. Vom project page:

ist FarmHash ein Nachfolger CityHash und enthält viele der gleichen Tricks und Techniken, einige von ihnen aus Austin Appleby MurmurHash genommen.

...

Auf CPUs mit allen notwendigen Maschinenbefehle, etwa sechs verschiedene Hash-Funktionen können zu FarmHash Lineup beitragen. In einigen Fällen haben wir gegenüber CityHash erhebliche Leistungssteigerungen erzielt, indem wir neuere Anweisungen verwendet haben, die jetzt allgemein verfügbar sind. Wir haben aber auch etwas mehr Geschwindigkeit auf andere Weise verdrängt, so dass die meisten Programme, die CityHash verwenden, beim Umschalten auf FarmHash mindestens ein bisschen mehr gewinnen sollten.

(CityHash war bereits eine leistungsoptimierte Hash-Funktion Familie von Google.)

vor einem Jahr veröffentlicht wurde, an welcher Stelle es an Sicherheit grenzender Wahrscheinlichkeit der Stand der Technik, zumindest unter dem veröffentlichten Algorithmen. (Sonst hätte Google etwas Besseres benutzt.) Es besteht eine gute Chance, dass es immer noch die beste Option ist.

+0

war eigentlich nur eine HN-Diskussion, wo sie CityHash gerissen haben. https://news.ycombinator.com/item?id=4600425 :( – alphazero

+0

Wissen Sie, ob es auch für FarmHash gilt? So oder so, wir sprechen nicht-kryptografische Hashes, also sind alle Wetten gegen bösartige Eingaben. –

+0

(möglicherweise dup) Nein, tue ich nicht, ich höre dich, aber das mag nur eine semantische Unterscheidung sein Warum ist es so einfach, eine Kollision zu fischen? Auch, lasst uns erinnern: Bugs .. :) – alphazero

3

Die Fakten:

  1. gute Hash-Funktionen, speziell die Verschlüsselungs diejenigen (wie SHA-1), erfordern erhebliche CPU-Zeit, weil sie eine Reihe von Eigenschaften zu ehren, die gewohnt sehr nützlich sein für Sie in diesem Fall;
  2. Jede Hash-Funktion gibt Ihnen nur eine Sicherheit: Wenn die Hash-Werte von zwei Dateien unterschiedlich sind, sind die Dateien sicherlich unterschiedlich. Wenn jedoch ihre Hash-Werte gleich sind, besteht die Möglichkeit, dass die Dateien auch gleich sind, aber die einzige Möglichkeit, sicher zu sagen, ob diese "Gleichheit" nicht nur eine Hash-Kollision ist, besteht darin, auf einen binären Vergleich der beiden zurückzugreifen Dateien.

Fazit:
In Ihrem Fall ich einen viel schnelleren Algorithmus wie CRC32 versuchen würde, die so ziemlich alle Eigenschaften, die Sie brauchen, und würde der Umgang mit mehr als 99,9% der Fälle fähig sein und nur auf eine langsamere Vergleichsmethode zurückgreifen (wie Binärvergleich), um die Falschpositiven auszuschließen. In der großen Mehrheit der Vergleiche würde es viel schneller sein, würde es wahrscheinlich kompensieren, dass es keine "ehrfurchtgebietende" Gleichförmigkeit (möglicherweise einige weitere Kollisionen) aufweist.

+0

Eine ausreichend große Wahrscheinlichkeit kann für den praktischen Gebrauch als sicher angesehen werden. Wenn Sie in Betracht ziehen, Code zu schreiben, der die Wahrscheinlichkeit hat, dass 1/1000000 während der Laufzeit eines Programms ausgeführt wird, können Sie genauso gut vermeiden, nach draußen zu gehen, weil Blitzunfälle doppelt so wahrscheinlich sind! –

+1

Die Wahrscheinlichkeit von Kollisionen ist in diesem Fall wahrscheinlich nicht so niedrig, wie Sie vielleicht denken, wenn Sie ein paar Millionen zu testende Dateien haben (siehe: http://preshing.com/20110504/hash-collision-probabilities/). Beispiel: Die Wahrscheinlichkeit ist so hoch wie 1/2, wenn Sie eine 32-Bit-Hash-Funktion mit nur 77k-Dateien verwenden! Während die Chancen mit 160 oder sogar 64 Bit-Funktionen drastisch sinken, ist mein Punkt, dass es wahrscheinlich schneller ist, CRC32 zu verwenden, um 99,99% der Fälle zu eliminieren, selbst wenn man eine langsamere Hash-Funktion benötigt, um mit einer kleinen Anzahl von Fällen fertig zu werden. als alles auf einmal zu tun, indem für jede Datei eine 160-Bit-Hash-Funktion berechnet wird. – ulix

1

128 Bits sind in der Tat gut genug, um verschiedene Dateien oder Chunks zu erkennen. Das Risiko einer Kollision ist infinitesimal, zumindest solange keine beabsichtigte Kollision versucht wird.

64 Bits können auch gut genug sein, wenn die Anzahl der Dateien oder Chunks, die Sie verfolgen möchten, "klein genug" bleibt (d. H. Nicht mehr als ein paar Millionen).

Sobald die Größe des Hashes festgelegt ist, benötigen Sie einen Hash mit einigen sehr guten Verteilungseigenschaften, wie z. B. den mit Q.Score = 10 in Ihrem Link aufgeführten.

3

Da die einzige relevante Eigenschaft von Hash-Algorithmen in Ihrem Fall die Kollisionswahrscheinlichkeit ist, sollten Sie sie schätzen und den schnellsten Algorithmus wählen, der Ihre Anforderungen erfüllt.

Wenn wir annehmen, Ihr Algorithmus absolute Gleichmäßigkeit hat, ist die Wahrscheinlichkeit einer Hash-Kollision zwischen n Dateien Hashes mit d möglichen Werte werden mit:

enter image description here

Zum Beispiel, wenn Sie benötigen Bei einer Kollisionswahrscheinlichkeit von weniger als einer Million unter einer Million Dateien müssen Sie mehr als 5 * 10^17 unterschiedliche Hashwerte haben, was bedeutet, dass Ihre Hashes mindestens 59 Bit haben müssen. Lassen Sie uns auf 64 Punkte eingehen, um eine mögliche schlechte Uniformität zu erklären.

Also ich würde sagen, jede anständige 64-Bit-Hash sollte für Sie ausreichend sein. Längere Hashes werden die Kollisionswahrscheinlichkeit weiter reduzieren, und zwar zu einem Preis mit höherer Rechenleistung und erhöhtem Hash-Speichervolumen. Bei kürzeren Caches wie CRC32 müssen Sie einen expliziten Kollisionsverarbeitungscode schreiben.

+0

erkannte nicht, dass Kopfgeld Standard wäre. Hätte es dir überlassen. – alphazero

+0

Das ist sehr schmeichelhaft, danke! Denken Sie daran, dass automatisch vergebene Kopfgelder die Hälfte ihres Wertes verlieren. Daher ist es immer am besten, sie manuell zu vergeben, auch wenn Sie die Antwort mit den meisten Upvotes auswählen. –

+0

unter der Annahme, dass diese Algorithmen absolute Gleichförmigkeit haben, ist es wie gesagt, dass die Erde eine perfekte Kugel ist. Dies kann für einige Fälle in Ordnung sein, aber nutzlos, wenn Sie sich um die Details kümmern. Es ist nur gut für eine Schätzung der benötigten Hash-Länge. –

1

Es hängt davon ab, wie viele Hashes Sie in einer Iteration über berechnen werden. ZB 64bit Hash erreicht eine Kollisionswahrscheinlichkeit von 1 in 1000000 mit 6 Millionen Hashes berechnet.

Siehe auch: Hash collision probabilities

+0

"Wahrscheinlichkeit von 1 in 100000 mit 6 Millionen Hashes berechnet" Ich denke, dass Sie dort eine Null verpasst haben, wäre die tatsächliche Wahrscheinlichkeit etwa 10 mal weniger. –

+0

Ein interessanter Fall ist, wenn Hash-Ausgabe ist, z. B. 128b,> 64b, & die Bits unabhängig sind, und Sie maskieren 64b, um als Schlüssel zu verwenden. Berücksichtigen Sie, dass eine Kollision in den Bits auftreten kann, die maskiert wurden (d. H. Nicht Teil des erhaltenen Schlüssels). Intuitiv scheint es, dass wir in diesem Fall bessere Wahrscheinlichkeiten hätten. (Haben Sie nicht die Mathematik gemacht.) – alphazero

+0

Eine Kollision ist, wenn alle Bits der Hashes übereinstimmen, also, wenn Sie einige der Bits maskieren, die noch eine Kollision ist. Sie können jedoch neue Kollisionen beim Maskieren einführen. Nicht sicher, welche praktische Verwendung eine solche Maskierung haben könnte - Sie verbrauchen Rechenzeit, die Sie nicht benötigen. –