Autor Beitrag
JackCoder
Hält's aus hier
Beiträge: 7



BeitragVerfasst: Di 20.05.14 22:08 
Hallo,
ich möchte von einigen (auch größeren) Dateien den SHA512-Hash ermitteln. Nun habe ich dazu einige Fragen.
Ich habe bereits im Internet einige Lösungen gefunden. Dabei ist mir aufgefallen, dass immer wieder unterschiedliche Konstruktoren benutzt werden:

ausblenden C#-Quelltext
1:
SHA512 sha512 = SHA512.Create();					

oder
ausblenden C#-Quelltext
1:
SHA512Managed sha512 = new SHA512Managed();					

usw... Was ist der unterschied zwischen diesen Klassen und welche sollte ich nehmen?

Zudem habe ich im Internet folgende Lösung gefunden:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
using (FileStream stream = File.OpenRead(file))
    {
        SHA512Managed sha = new SHA512Managed();
        byte[] hash = sha.ComputeHash(stream);
    }


Dazu hat man mir gesagt, es sei die langsamste Art (also eine Datei Bitweise einzulesen) um einen Hash zu berechnen. Ich sollte stattdessen mit Chunks arbeiten. Wie mache ich das?
Kann mir jemand helfen??
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 21.05.14 10:44 
Hallo JackCoder :welcome:

du beziehst dich wohl auf deinen Beitrag myCSharp.de - Feedback: Was haltet ihr von meinem Code der eine Verzeichnisstruktur in eine Datei schreibt? ?

Bzgl. der Konstruktoren gibt es keinen relevanten Unterschied, da SHA512Managed die Implementierung der abstrakten Basisklasse SHA512 ist und beide daher eine SHA512Managed-Instanz zurückgeben, s.a. MSDN SHA512.Create und SHA512 (unter "Hinweise" bzw. englisch "Remarks").

Und zum chunk-weisen Hashen s. z.B. Hashing Data In Chunks Using .NET oder How to compute hash of a large file chunk?.

Ob jedoch das chunk-weise Verarbeiten wirklich schneller ist, als die Datei als Stream zu bearbeiten, wirst du wohl nur durch Tests rauskriegen.

Einzig jedoch das Rauschreiben des Hashwerts in die Datei mittels
ausblenden C#-Quelltext
1:
foreach(byte hashSubstring in sha512Hash) File.AppendAllText(pathFileList, Convert.ToString(hashSubstring, 16));					

solltest du so optimieren, daß zuerst der String berechnet wird und erst abschließend dieser Hash-String als ganzes in die Datei geschrieben wird (IO-Operationen sind immer teuer).
JackCoder Threadstarter
Hält's aus hier
Beiträge: 7



BeitragVerfasst: Mi 21.05.14 16:36 
Vielen Dank für deine Antwort, ich habe mal ein paar Tests gemacht:
Ohne Chunks zu benutzten, brauche ich um eine bestimmte Datei zu hashen ca. 900ms.
Dann habe ich mit Chunks gearbeitet. Nun hängt die Zeit ganz komisch von der Größe des Buffers ab:
Mache ich das Array 1024 Felder groß, benötigt die Software ca 700ms, nehme ich z.B. 21, brauch das Programm nur 10 MS zum hashen. Komischerweise braucht es bei 22 wieder 700ms. Was geht hier vor? :D
Ich habe die Zeit bisher mit DateTime.Now gemessen und den Unterschied berechnet, geht da vielleicht was schief?
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 21.05.14 16:47 
Zum Zeitmessen bietet sich die StopWatch an.
Um deine Ergebinsse einschätzen zu können wäre es darüber hinaus hilfreich auch zu sehen was du gemacht hast.
JackCoder Threadstarter
Hält's aus hier
Beiträge: 7



BeitragVerfasst: Mi 21.05.14 16:52 
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
static void Main(string[] args)
        {
            DateTime Time1 = DateTime.Now;
            string sFile = @"C:\test.txt";

            // Use a file as an input stream, but we can pretend that it is something like a response stream from 
            // a web request.
            using (SHA512 md5 = SHA512.Create())
            using (Stream input = File.OpenRead(sFile))
            {
                // small enough buffer to make us read the file in chunks
                byte[] buffer = new byte[BUFFER_SIZE];
                int bytesRead;

                // open the file, 
                while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
                {
                    // hash each chunk at a time.
                    md5.TransformBlock(buffer, 0, bytesRead, null0);
                }

                // We need this, even though no data is hashed.  Do not
                // pass null for the buffer
                md5.TransformFinalBlock(buffer, 00);

                byte[] hashVal = md5.Hash;

                // convert the hash value to a nice string, something like would see on a download site or 
                // get from the Microsoft hasing utility, fciv.exe.
                StringBuilder sbHash = new StringBuilder(hashVal.Length * 2);
                int idxMax = hashVal.Length;
                for (int idx = 0; idx < idxMax; ++idx)
                {
                    sbHash.Append(hashVal[idx].ToString("x2"));
                }

                Console.WriteLine(sbHash.ToString());
                DateTime Time2 = DateTime.Now;
                TimeSpan timeSpan = Time2 - Time1;
                Console.WriteLine(timeSpan.Milliseconds);
            }


So sieht es im Moment bei mir aus.



EDIT:
Habs jetzt mit StopWatch gemacht, ich bekomme die selben Ergebnisse.:/
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 21.05.14 17:13 
Sehe keinen Grund warum da bei verschiedenen Blockgrößen große Unterschiede, schon gar nicht die von dir beobachteten, herauskommen sollten. Außer vielleicht bei extrem kleinen Blöcken oder bei Extrem großen dateien wo auch kleine Unterschiede im Promille Bereich sich zu meßbaren Größen addieren. Wenn du zwischendurch mal ~abweichende~ Werte siehst würde ich von äußeren Einflüssen ausgehen. Zum Beispiel das die Datei einmal aus dem Filecache kommt das andere mal von der Platte, Hackler bei der Consolenausgabe du misst ja einen Console.WriteLine mit, irgendwelche Dinge die Windows nebenbei erledigt u.s.w.
JackCoder Threadstarter
Hält's aus hier
Beiträge: 7



BeitragVerfasst: Do 22.05.14 11:16 
Danke für deine Antwort, ich habe mich dann dafür entschieden ein paar Tests zu machen.
Ich habe jeweils 1000 mal die Dauer gemessen und den Durchschnitt berechnet. Ob ich nun mit Chunks (egal welche Buffer-Größe) oder mit dem Stream arbeite, es dauert alles gleich lange.
Ich entscheide mich dann wohl für die Stream-Methode, die ist etwas kürzer.
Viele Grüße