2009-05-27 6 views
3

Ich arbeite an einem .NET 3.5-Projekt und ich brauche einen 32-Bit-Hash-Wert. Es scheint keine Methoden in den .NET Cryptography-Klassen zu geben, die einen 32-Bit-Hash zurückgeben (MD5 ist 128 Bit, SHA1 ist 160 Bit usw.). Ich habe eine CRC32-Klasse implementiert, aber ich finde, dass die SHA1- und MD5-Hashfunktionen, die bereits existieren, viel schneller sind.Sind die ersten 32 Bits eines 160-Bit-SHA1-Hash ein akzeptabler Ersatz für einen CRC32-Hash?

Wäre es ein Problem (d. H. Erhöhte Wahrscheinlichkeit von Kollisionen) mit mir mit der SHA1-Hash-Funktion und nur die ersten 32 Bits abzubrechen, um als Hash-Wert zu speichern?

+2

Was machst du, dass du nicht den ganzen 20 Zeichen SHA-1 Hash speichern kannst? Außerdem ist CRC32 kein Hash, es ist ein Mechanismus zur Erkennung von Übertragungsfehlern. Wenn Sie also eine Fehlererkennung benötigen, ist ein Hash-Verfahren nicht die richtige Vorgehensweise. – jmucchiello

+0

Der 4-Byte-Hash wurde gewählt, um Platz zu sparen. Der Hash wird für Prüfsummen-Datenblöcke verwendet, die von einem Überwachungsgerät kommen, und es können 10 Millionen von ihnen vorhanden sein. Wir werden sehen, vielleicht wird das Speichern der ganzen Sache kein Problem sein. Sie sagten etwas Interessantes. Was genau ist der Unterschied zwischen einem "Übertragungsfehlererkennungsmechanismus" und einem Hash? Kryptographische Stärke (diese spezielle Anwendung benötigt das nicht)? – raven

+0

Shameless Selbst Stecker: cmdhashgen unterstützt CRC32 und wird von HashAlgorithm abgeleitet, so kann es nur die gleiche Art und Weise wie die andere verwendet werden, Crc32.cs überprüfen: http://cmdtools.codeplex.com/ –

Antwort

6

Wenn Sie nicht die zusätzlichen Funktionen des CRC32 (ein linearer Code) wollen, sollten Sie mit der Ausgabe auf 32 schneiden Bit.

Ob die Ausgabe einiger kryptographischer Hash-Funktionen die Sicherheit in Bezug auf Kollisionsresistenz verletzt, ist ein offenes Forschungsproblem ("unnatürlich" konstruierte Beispiele existieren, wenn ich mich richtig erinnere). Aber NIST (wahrscheinlich mit der Zustimmung der NSA) verwendete die Schneidtechnik, um den SHA-224 trotzdem von SHA-256 zu erhalten (siehe article about SHA in wikipedia).

EDIT: die CRC32 ermöglicht zu erkennen (und vielleicht korrigieren) Einzelbit Fehler, während eine kryptografische Hash-Funktion die Eigenschaft haben sollte, dass Sie nicht zwei Eingänge finden, die den gleichen Hash-Wert haben.

Kennen Sie das "Geburtstagsparadox" (siehe auch Wikipedia)? Bei einer 32-Bit-Prüfsumme erwarten Sie eine Kollision (d. H. Zwei Eingänge mit demselben Hash-Wert), wenn Sie etwa 2^16 Eingänge haben und Sie viel mehr Eingänge hashen möchten. (Erneutes Einlesen Ihres Kommentars könnte für Sie kein Problem sein.)

+0

Wenn es gut genug für NIST ist, ist es gut genug für mich. – raven

0

Wenn Sie nicht beabsichtigen, die 32-Bit für einen kryptografischen Zweck zu verwenden, sollten Sie in Ordnung sein. Ansonsten würde ich nicht darauf vertrauen, dass die ersten 32 Bits die gleiche Verteilung wie der gesamte Hash haben.

Warum können Sie nicht einfach den breiteren Hash verwenden, der verfügbar ist?

0

CRC32 ist wahrscheinlich angemessen für Ihre Bedürfnisse. Dies wurde in this question diskutiert.

In Bezug auf das Abschneiden eines Hash-Primitivs ist die einzige stark genutzte Anwendung davon die SSL/TLS Pseudo Random Function (PRF), die verwendet wird, um Schlüssel zu generieren. Es verwendet HMACs, Startwerte und Beschriftungen, um so viele Bytes zu generieren, wie Sie benötigen, indem Sie mehrere Male hashen und dann auf die benötigte Anzahl von Bytes abschneiden. obwohl

In Bezug auf Ihre Frage, können Sie die Ausgabe der Hash in Int32 der lesen und sie dann zusammen xor wenn du paranoid bist:

static void Main() 
{ 
    int xorCrc = GetHashedCrc(new SHA1Cng(), new byte[] {0xDE, 0xAD, 0xBE, 0xEF}); 
} 

private static int GetHashedCrc(HashAlgorithm algorithm, byte[] bytesToHash) 
{ 
    byte[] hash = algorithm.ComputeHash(bytesToHash); 
    int totalInt32s = hash.Length/sizeof(int); 
    int result = 0; 
    for(int i = 0; i < totalInt32s; i++) 
    { 
     int currentInt = BitConverter.ToInt32(hash, sizeof(int)*i); 
     result = result^currentInt; 
    } 

    return result; 
} 
+1

Schlechte Idee. Dies erhöht die Komplexität und bringt keinerlei Vorteile. Wenn Sie SHA1, HMAC usw. verwenden, ist das Ergebnis bereits "zufällig" genug. Schneiden Sie das Ergebnis ist nur zu finden. Es ist die Methode, die zum Beispiel NIST vorschlägt, kürzere Hashwerte zu erhalten (z.B. SHA-224 oder SHA-384) oder für kürzere HMACS. – Accipitridae

+0

Einverstanden. Ich war nur auf der Suche nach einer Möglichkeit, alle Bits zu verwenden, aber Sie haben Recht, dass es keinen Sicherheitsunterschied macht und zusätzliche Anweisungen kostet. –

2

die Annahme, dass eine Hash-Funktion gleichermaßen seine Eingänge verteilt über seinen Codecom scheint es logisch anzunehmen, dass es sich auch gleichmäßig auf jede Teilmenge davon verteilen wird. Die Verwendung einer "nativen" 32-Bit-Hash-Funktion wird jedoch wahrscheinlich immer noch die bessere Wahl sein. Vielleicht kann jemand mehr in die Sache uns einen besseren Grund als nur mein Bauchgefühl bieten :)

1

Warum verwenden Sie nicht einfach string.GetHashCode(). Es wurde entwickelt, um einen 32-Bit-Hash-Wert zu berechnen und bei realen Daten wenige Kollisionen zu erzeugen. Natürlich ist es nicht sicher, aber Ihre Frage enthält das nicht als Voraussetzung.

+0

String.GetHashCode hat den Nachteil, unterschiedliche Ergebnisse im 32- und 64-Bit-Modus zu erzeugen. Es ändert sich auch ab und zu, wenn Microsoft die neue .NET-Version veröffentlicht. Dies wird zu einem Problem, wenn Sie Ihren Hash beibehalten oder ihn sogar über das Netzwerk senden. – Constantin

Verwandte Themen