![]() |
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 |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Man kann vor dem Haschen die XML nochmal "neu" formatiert in einen String/Stream kopieren und da hashen (den Hash entfernt/ersetzt).
Da wäre die Formatierung auch fast egal, abgesehn von der Groß-/Kleinschreibung, denn XML ist grundsätzlich erstmal CaseInsensitiv und auch die Reihenfolge der Parameter könnte interessant sein, welche ja praktisch auch egal ist, aber beim Haschen kommt es dann wieder auf die Reihenfolge drauf an. Je nach Auswertung könnte auch die Reihenfolge der Nodes egal sein. Auch kann ein Node so
Delphi-Quellcode:
oder
<node></node>
Delphi-Quellcode:
gespeichert sein, was aber vom Inhalt, bzw. aus Sicht des DOMs nahezu egal ist.
<node />
Und womöglich kann für die Auswertung auch egal sein, ob ein leerer Node vorhanden ist oder nicht. |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Wäre es bei diesem aufwand nicht vllt. einfacher einen (verschlüselte) Zip-Datei mit den XML-Daten zu erstellen und vor Programmstart, diese zu entpacken?
oder aber die Daten gleich Binär speichern, und dort einen Hash dazu packen. GGf. kann man ja für Neugierige dann noch eine xml-Datei generieren. Gruß K-H |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Zitat:
Wenn ich aus einer wie auch immer gearteten Datei eine Datenstruktur auslesen kann, die vom Daten-Inhalt her identisch ist, dann sind die Daten unverändert. So kann diese Datei dann auch in ein JSON, YAML, Ini, etc. Format überführt werden (inkl. dem Hashwert) und die Daten können zuverlässig auf Unversehrtheit/Änderung geprüft werden. Darum würde ich in einen Hash niemals die Speicherstruktur aufnehmen, wenn es mir um die Daten geht. Bei einem EAN13 Barcode wird ja auch nicht die Strichbreite, Höhe, Druckfarbe oder Papierart in der Prüfziffer berücksichtigt. Auch nicht der Karton, wo der dran draufklebt ;) |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Nur mal so am Rande: Wenn jemand eine Stelle im Hash ändert und die Messwerte nicht manipuliert, dann schlägt Deine Prüfung trotzdem fehl, obwohl die Messwerte noch korrekt sind.
Ich würde es daher auch wie p80286 machen und die XML-Datei in eine passwortgeschützte ZIP-Datei schmeißen und Ruhe ist. Das Passwort ist in geeigneter Form (nicht MD5) zu hinterlegen. madas |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Zitat:
Und der wird also zuverlässig erkannt. Was soll denn jetzt die ZIP-Datei noch bringen? Ist die gegen Veränderungen geschützt? Kann ich da etwa keine Bytes ändern? :roll: Und jetzt kennt einer das Hashverfahren, baut die Datei neu auf mit falschen Werten und löscht auch noch die ZIP-Datei ... Und es fällt ein Klavier vom Himmel und alle Häuser fallen um, alle Kühe fallen um und es gibt kein Strom mehr ... ja, was denn dann? |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
:-D
Bevor die Diskussion in dieser Richtung ausartet möchte ich doch kurz auf diesen Thread verweisen: Zitat:
In der Regel soll eigentlich Niemand etwas an den Daten verändert. Deshalb wäre es im Prinzip auch nicht schlimm, wenn man die Struktur im Hashwert mit berücksichtigt. Es soll rein informativ jedoch möglich sein, sich die XML-Datei anzuschauen. Möchte man wirklich Messwerte manipulieren, dann würde sich das auch deutlich leichter realisieren lassen als durch das "knacken" meines Hashwertes. So könnte man z.B. einfach "falsch" Messen, bis man seine Wunschwerte hat. Aus diesem Grund ist bereits MD5 als Hashfunktion mehr als ausreichend. Es soll somit lediglich gegen eine offensichtliche Manipulation schützen. Es wird wohl nun auf die Methode mit den Streams und einer eventuellen Neuformatierung dieser Streams hinauslaufen. |
AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Da gibt es u.a. auch einen Standard, welcher sich mit XML-Signaturen beschäftigt.
![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:51 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