![]() |
Delphi-Version: XE5
XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Guten Tag,
ich lese schon sehr lange hier im Forum und habe oft Antworten auf meine Fragen gefunden. Aus diesem Grund habe ich mich heute angemeldet und muss direkt mal eine erste Frage stellen. Hintergrund: Ich möchte XML-Dateien gegen Manipulation schützen. Diese XML-Datei enthält Messdaten, welche nicht verändert werden sollen. Die XML-Datei soll aber trotzdem lesbar bleiben. Es genügt beim öffnen der Datei eine Überprüfung, ob die Datei verändert wurde. In einer ersten Version habe ich lediglich die Werte aller Attribute eingelesen, als Strings aneinander gehängt und daraus dann einen Hashwert bestimmt, welchen ich ebenso in der XML speicher:
Delphi-Quellcode:
Die XML-Datei sieht dann z.B. so aus:
procedure TForm1.SchreibeXML;
var xmlDoc : IXMLDocument; iNode: IXMLNode; s: string; Hashwert: string; begin ErstelleXML; xmlDoc := newXMLDocument; XMLDoc.LoadFromFile(PATH + Dateiname); xmlDoc.Active := true; //Neue Knoten anlegen XMLDoc.DocumentElement.AddChild('messdaten'); XMLDoc.DocumentElement.AddChild('hashdaten'); //Attribute zuweisen - Messwerte iNode := XMLDoc.DocumentElement.ChildNodes['messdaten'].AddChild('messwerte'); iNode.Attributes['text'] := TextEdt.Text; iNode.Attributes['messwert1'] := Messwert1Edt.Text; iNode.Attributes['messwert2'] := Messwert2Edt.Text; iNode.Text := ''; s := TextEdt.Text + Messwert1Edt.Text + Messwert2Edt.Text; Hashwert := getMd5HashString(s); //Attribute zuweisen - Hashwert iNode := XMLDoc.DocumentElement.ChildNodes['hashdaten'].AddChild('hash'); iNode.Attributes['wert'] := Hashwert; iNode.Text := ''; //Speichern xmlDoc.SaveToFile(PATH + Dateiname);
Code:
Beim Einlesen haben ich diesen Hashwert dann analog berechnet und ihn mit dem Wert in der XML verglichen. Das funktioniert schonmal sehr gut.
<?xml version="1.0"?>
<Root> <messdaten> <messwerte text="Titel" messwert1="2.5" messwert2="7.6"/> </messdaten> <hashdaten> <hash wert="4b0fbe5ec8db72fe0ffaf8e1cbc9f50f"/> </hashdaten> </Root> Nun möchte ich aber generelle Manipulationen in der XML-Datei erkennen können. Ich möchte somit alles bis auf den Knoten "hashdaten" hashen. Ich scheitere jedoch schon bei der Berechnung des Hashwertes. Mein Ansatz:
Delphi-Quellcode:
Ich möchte die XML.Datei somit z.B. erstmal in den Hauptspeicher laden (Stream), um diesen Stream dann zu hashen. Danach füge ich einen weiteren Knoten "hashdaten" mit dem Hashwert an. Leider ist der berechnete Hashwert stets der selbe, egal, welche Daten das XML enthält. Habe ich hier vllt noch einen grundsätzlichen Fehler drin? Ich leider bisher noch nie mit Streams gearbeitet.
procedure TForm1.SchreibeXML;
var xmlDoc : IXMLDocument; iNode: IXMLNode; s: string; Hashwert: string; Stream: TStream; begin ErstelleXML; xmlDoc := newXMLDocument; xmlDoc.LoadFromFile(PATH + Dateiname); xmlDoc.Active := true; //Neuen Knoten anlegen - Messdaten xmlDoc.DocumentElement.AddChild('messdaten'); //Attribute zuweisen - Messwerte iNode := XMLDoc.DocumentElement.ChildNodes['messdaten'].AddChild('messwerte'); iNode.Attributes['text'] := TextEdt.Text; iNode.Attributes['messwert1'] := Messwert1Edt.Text; iNode.Attributes['messwert2'] := Messwert2Edt.Text; iNode.Text := ''; Stream := TMemoryStream.Create; //Stream.size = 0 (logischerweise) xmlDoc.SaveToStream(Stream); //Stream.size steigt z.B. auf 132 Hashwert := getMd5StreamToStr(Stream); Für die Berechnung des Hashwertes nutze ich die Indy-Komponente von Delphi: ![]() Wenn dieses Problem geklärt ist bleibt noch die Frage, wie ich das ganze dann beim Einlesen bewerkstellige. Denn wenn ich die XML-Datei wieder einlese habe ich ja auch den Knoten "hashdaten" mit drin. Dieser darf natürlich bei der Berechnung des Hashwertes keine Rolle spielen. Ich hoffe sehr, dass ich verständlich gemacht habe, wo mein Problem liegt und hoffe auf Rat von euch :-). Wahrscheinlich lassen sich beide Probleme schnell und einfach lösen. Grüße Headbucket |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Diskussion wurde schon im
![]() |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Im Entwickler-Forum ging es generell um die Frage, wie ich gegen eine Manipulation vorgehe. Diese Frage wurde dort geklärt -> Hashfunktion benutzen.
Hier geht es vorwiegend um die Frage, wie ich einen Stream hashen kann. Ich habe diese Frage hier gestellt, da es eine Frage zu Delphi ist und mein anderer Beitrag im Entwickler-Forum in der Kategorie XML war und ich mir deshalb wenig Hilfe zu Delphi-Fragen erhofft habe. Grüße Headbucket |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Erst mal als Grundsatz:
Die Daten komplett in eine Klasse (Container) schreiben. Diesen Container dann an eine Klasse (ContainerIO) übergeben, die diesen Container speichern und lesen kann. Jetzt kann eine Klasse (ContainerIO) die Daten aus dem Container in ein XML schreiben und berechnet aus den Daten auch den Hash. Dazu ist es nicht erforderlich die XML-Ausgabe zu hashen, sondern rein die Daten. Am Ende fügt ContainerIO noch den ermittelten Hashwert in die XML Datei ein. Beim Einlesen geht das quasi umgekehrt. ContainerIO liest die Daten ein, bildet den Hashwert (wie schon vorher beim Speichern) und vergleicht diesen Hashwert mit dem aus der XML-Datei. Stimmt der Hashwert, dann alles ok, ansonsten Exception werfen, oder was auch immer. |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Zu Deinem Hashwert-Problem :
Bekommst Du etwas anderes heraus, wenn Du die Position Deines MemoryStreams vor dem ermitteln des Hash-Wertes auf 0 setzt ? (Kann es gerade nicht selber testen) Gruß Guido |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
@Sir Rufo
Inwiefern unterscheidet sich dieses Konzept von meiner ersten Version? Es werden ja dann wieder nur die Werte der einzelnen Attribute gehasht. Generelle Manipulationen an der Struktur der XML-Datei werden somit dann nicht bzw. durch andere Fehler sichtbar. Vllt habe ich dich aber auch falsch verstanden. Zitat:
|
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Das mit dem Hash in der XML hatte ich auch mal gemacht.
Es gibt da zwei grundsätzliche Wege: - den XML-Text als kompletten String/Stream haschen (hierbei muß der Hash vorher durch einen "Dummy"-Wert ersetzt oder entfernt werden, da er ja mitgehasht wird) - das XML im DOM hashen, also alle Nodes, Values und Attributes durchgehen und deren Werte haschen (dabei den Hash-Node ignorieren) (hier ist dann die Formatierung des XML-Textes egal und man kann "unwichtige" Werte überspringen, bzw. Teile einzeln/getrennt haschen) |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Zitat:
|
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Die Frage ist doch, welche Manipulationen man erkennen möchte:
Original
XML-Code:
Veränderung (Formatierung) - ist egal und kann durchgewunken werden
<?xml version="1.0"?>
<Root> <messdaten> <messwerte text="Titel" messwert1="2.5" messwert2="7.6"/> </messdaten> <hashdaten> <hash wert="4b0fbe5ec8db72fe0ffaf8e1cbc9f50f"/> </hashdaten> </Root>
XML-Code:
Veränderung (Attributnamen) - wird erkannt
<?xml version="1.0"?>
<Root> <messdaten><messwerte text="Titel" messwert1="2.5" messwert2="7.6"/></messdaten> <hashdaten><hash wert="4b0fbe5ec8db72fe0ffaf8e1cbc9f50f"/></hashdaten> </Root>
XML-Code:
Veränderung (Werte) - wird erkannt
<?xml version="1.0"?>
<Root> <mAssdaten><mAsswerte tAxt="Titel" mAsswert1="2.5" mAsswert2="7.6"/></mAssdaten> <hashdaten><hash wert="4b0fbe5ec8db72fe0ffaf8e1cbc9f50f"/></hashdaten> </Root>
XML-Code:
Veränderung (Metadaten anhängen) - ist für die Messwerte egal - kann durchgewunken werden
<?xml version="1.0"?>
<Root> <messdaten><messwerte text="Titel1" messwert1="2.55" messwert2="7.65"/></messdaten> <hashdaten><hash wert="4b0fbe5ec8db72fe0ffaf8e1cbc9f50f"/></hashdaten> </Root>
XML-Code:
Wenn nur die Messdaten interessant sind, dann braucht man auch nur diese zu hashen, und nicht auch noch die Struktur darum, denn ohne gültige Struktur können die Daten nicht gelesen werden.
<?xml version="1.0"?>
<Root> <messdaten><messwerte text="Titel" messwert1="2.5" messwert2="7.6"/></messdaten> <hashdaten><hash wert="4b0fbe5ec8db72fe0ffaf8e1cbc9f50f"/></hashdaten> <metadaten><metawert Autor="Ich"/></metadaten> </Root> |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Zitat:
Zitat:
@Sir Rufo Meiner Meinung nach hast du recht. Der Aufbau der Struktur sollte keinen Einfluss haben. Es macht dann zwar mehr Arbeit bei der Auswertung aber mal sehen. Der Vollständigkeit halber hier nochmal beide Prozeduren mit Streams:
Delphi-Quellcode:
Ich werde mich ggf. nochmal melden, wenn ich das Verfahren geklärt habe. Vielen Dank schonmal für die schnelle und gute Hilfe!
procedure TForm1.LiesXML;
var xmlDoc: IXMLDocument; HashDatei, HashBerechnet: string; Stream: TStream; begin //XMLDocument erzeugen und xml-Datei laden xmlDoc := newXMLDocument; xmlDoc.LoadFromFile(PATH + Dateiname); xmlDoc.Active := true; TextEdt.Text := xmlDoc.DocumentElement.ChildNodes['messdaten'].ChildNodes['messwerte'].Attributes['text']; Messwert1Edt.Text := xmlDoc.DocumentElement.ChildNodes['messdaten'].ChildNodes['messwerte'].Attributes['messwert1']; Messwert2Edt.Text := xmlDoc.DocumentElement.ChildNodes['messdaten'].ChildNodes['messwerte'].Attributes['messwert2']; HashDatei := xmlDoc.DocumentElement.ChildNodes['hashdaten'].ChildNodes['hash'].Attributes['wert']; xmlDoc.DocumentElement.ChildNodes.Remove(xmlDoc.DocumentElement.ChildNodes.FindNode('hashdaten')); Stream := TMemoryStream.Create; xmlDoc.SaveToStream(Stream); Stream.Position := 0; HashBerechnet := getMd5StreamToStr(Stream); if HashDatei = HashBerechnet then begin StatusBar1.Panels[1].Text := 'Hash ok!'; end else begin StatusBar1.Panels[1].Text := 'Hash nicht ok!'; end; end; procedure TForm1.SchreibeXML; var xmlDoc : IXMLDocument; iNode: IXMLNode; Hashwert: string; Stream: TStream; begin ErstelleXML; xmlDoc := newXMLDocument; xmlDoc.LoadFromFile(PATH + Dateiname); xmlDoc.Active := true; //Neuen Knoten anlegen - Messdaten xmlDoc.DocumentElement.AddChild('messdaten'); //Attribute zuweisen - Messwerte iNode := XMLDoc.DocumentElement.ChildNodes['messdaten'].AddChild('messwerte'); iNode.Attributes['text'] := TextEdt.Text; iNode.Attributes['messwert1'] := Messwert1Edt.Text; iNode.Attributes['messwert2'] := Messwert2Edt.Text; iNode.Text := ''; Stream := TMemoryStream.Create; xmlDoc.SaveToStream(Stream); Stream.Position := 0; Hashwert := getMd5StreamToStr(Stream); //Neuen Knoten anlegen - Hashdaten xmlDoc.DocumentElement.AddChild('hashdaten'); //Attribute zuweisen - Hashwert iNode := XMLDoc.DocumentElement.ChildNodes['hashdaten'].AddChild('hash'); iNode.Attributes['wert'] := Hashwert; iNode.Text := ''; //Speichern xmlDoc.SaveToFile(PATH + Dateiname); end; Grüße Headbucket |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:40 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz