Wie verlässlich ist der _Crypt_FileHash Befehl

  • Hallo zusammen,

    ich habe eine Verteilungssoftware geschrieben, die von einer zentralen Stelle aus ein Programm auf verschiedene Standorte verteilt, um das Update vor Ort zu beschleunigen.
    Ein Update besteht aus mehreren Datein unterschiedlicher Dateitypen, z.B. Exe-Dateien, Rpt, Ini etc.
    Da die Verbindungen zwischen den Standorten eher langsam sind, mitunter nur 1Mbit, ermittle ich während der Verteilung, ob die Datei im Ziel schon existiert und falls ja, ob die Hashwerte der Dateien
    übereinstimmen. Ist dies nicht der Fall wird die neue Datei kopiert.
    Nun habe ich heute zum ersten Mal den Fall gehabt, dass zwei nachweislich unterschiedliche Dateien den gleichen Hashwert haben und somit das Update nicht kopiert wurde.
    Wie groß ist die Wahrscheinlichkeit dass so ein Fall auftritt? Wie verlässlich ist die Hashwert-Ermittlung mit _Crypt_Hashfile?

    Hat jemand da Erfahrungen?

    Gruß

    Man hat's nicht leicht, aber leicht hat's einen.

  • Wie groß ist die Wahrscheinlichkeit dass so ein Fall auftritt?

    Kommt ganz auf den verwendeten Hashalgorithmus an.
    Im Grunde aber brutal unwahrscheinlich.

    Könnte eventuell auch ein Codeproblem sein.
    Kannst du eventuell mal ein Minimalbeispiel basteln welches das Verhalten reproduziert?
    Also ein möglichst kleines Skript welches im Grunde nur die beiden Dateien hasht und deren Ergebnisse ausgibt?
    Idealerweise wäre es auch gut die beiden Dateien mal zur Verfügung zu stellen wenn das geht.

    Auch wenn ich den Fall des gleichen Hashwertes bei z.B. MD5 für nahezu ausgeschlossen halte könntest du das Auftreten des Falles deutlich verringern in dem du vor dem Hashen erstmal auf gleiche Dateigröße prüfst. Das macht eine Kollision unwahrscheinlicher und ist auch der Performance zuträglich da dabei nur dann gehasht wird, wenn es auch sinnvoll ist.

  • Also,

    die Zieldatei liegt in $copy_to und die Quelldatei liegt in $copy_from

    Die Daten der Quelldateien ermittle ich mit einer Inventarisierungsroutine, die mir die Dateinamen kpl. mit Dateipfad ausgibt.
    Beim Durchlaufen dieses Arrays ermittle ich den Hashwert, diei Dateigröße etc. und speichere die Werte in ein weiteres Array.
    Dieses wird dann für den Verteilungsvorgang durchlaufen, wobei die Bedingungen für ein Kopieren der jeweiligen Datei geprüft werden.

    Die Dateien kann ich leider nicht zur Verfügung stellen, da es sich um Programme eines Lieferanten handelt.
    Die zusätzliche Prüfung auf Dateigröße ist eine gute Idee. Ich hatte zuvor schon mit einer Textdatei gearbeitet, die ich im Zielordner ablege und die die aktuellen Hashwerte der Dateien in diesem Ordner enthält. Dadurch konnte ich zuerst eine Prüfung gegen die Werte in dieser Datei vornehmen, ohne den Hashwert jedes mal ermitteln zu müssen. Eine enorme Zeitersparnis.

    Man hat's nicht leicht, aber leicht hat's einen.

  • Also prinzipiell fällt mir spontan nichts problematisches auf.
    Außer dass das Skript so nicht ausgeführt werden kann da noch ein Schreibfehler drin ist und das #Include fehlt.
    Hast du es wirklich mal exakt so laufen lassen mit dem entsprechenden Resultat (das ist ja der Sinn eines Minimalbeispieles)?
    Führe wirklich mal nur dieses minimale Skript aus. So kannst du schonmal den Rest deines eigentlichen Skriptes ausschließen (z.B. die Eintragung der Hashes in das Array und ähnliches).

    Gehen wir also jetzt mal davon aus du hast tatsächlich nur dieses Miniskript ausgeführt und die Datei wird nicht überschrieben.
    Woran könnte es liegen?
    Nun einmal könnte es eventuell zu Fehlern in der _Crypt_HashFile kommen. Z.B. wenn die Datei nicht geöffnet werden kann (weil sie blockiert wurde oder weil sie schlicht nicht existiert).
    In diesem Falle wäre die Ausgabe der Funktion "-1". Kommt es zu Fehlern bei beiden Dateien haben beide den Wert "-1" und folglich kommt es nicht zum Kopiervorgang.
    Dieser Fall muss also auch mit beachtet werden.
    Des Weiteren könnte es ja auch sein, dass alles stimmt nur der Aufruf der FileCopy() fehlschlägt.
    Das müsste man noch mit prüfen.

    Prinzipiell wäre es also sinnvoll mal ein bisschen Debugging zu betreiben und die Ausgaben der einzelnen Teile sich mal anzeigen zu lassen um schrittweise den Fehler einzugrenzen.
    Folgender Grundaufbau sollte das ganze schonmal deutlich robuster werden lassen:

  • Ich werde mir die beiden Dateien mal in das Scriptverzeichnis kopieren und den Vergleich direkt dort vornehmen.

    Ich werde dann mal Info geben.
    Vielen Dank bis hierhin.

    Man hat's nicht leicht, aber leicht hat's einen.

  • Wie groß ist die Wahrscheinlichkeit dass so ein Fall auftritt? Wie verlässlich ist die Hashwert-Ermittlung mit _Crypt_Hashfile?

    Hat jemand da Erfahrungen?

    Ja, hunderttausende Dateien "gehashed" und "logischerweise" kam keiner der 16 Byte langen Hashcodes doppelt vor.
    Das ist auch klar, wenn man weiß, wie die Erstellung eines Hash funktioniert. Ändert man an den Daten auch nur ein einziges Bit, dann wird der Hash völlig anders sein!
    Und bei 128 Bit (das sind dezimal 18446744073709551616, also 18e18 unterschiedliche Hashes) bleiben statistisch nicht viele Möglichkeiten für einen doppelten Hash bei einigen hunderttausend Dateien :D . Aber wie das bei Statistik so ist, nichts ist unmöglich! Also mach das, was AspirinJunkie vorgeschlagen hat, und prüfe die beiden Dateien mit "angeblich" gleichem Hash!