AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen
Thema durchsuchen
Ansicht
Themen-Optionen

XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen

Ein Thema von Headbucket · begonnen am 12. Dez 2013 · letzter Beitrag vom 12. Dez 2013
Antwort Antwort
Seite 1 von 2  1 2      
Headbucket

Registriert seit: 12. Dez 2013
Ort: Dresden
172 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#1

XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen

  Alt 12. Dez 2013, 11:19
Delphi-Version: XE5
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:
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);
Die XML-Datei sieht dann z.B. so aus:
Code:
<?xml version="1.0"?>
<Root>
   <messdaten>
      <messwerte text="Titel" messwert1="2.5" messwert2="7.6"/>
   </messdaten>
   <hashdaten>
      <hash wert="4b0fbe5ec8db72fe0ffaf8e1cbc9f50f"/>
   </hashdaten>
</Root>
Beim Einlesen haben ich diesen Hashwert dann analog berechnet und ihn mit dem Wert in der XML verglichen. Das funktioniert schonmal sehr gut.

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:
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);
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.

Für die Berechnung des Hashwertes nutze ich die Indy-Komponente von Delphi: Delphi-Referenz durchsuchenTIdHash.HashStreamAsHex

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
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.202 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen

  Alt 12. Dez 2013, 11:27
Diskussion wurde schon im Entwickler-Forum geführt
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Headbucket

Registriert seit: 12. Dez 2013
Ort: Dresden
172 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#3

AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen

  Alt 12. Dez 2013, 11:33
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
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen

  Alt 12. Dez 2013, 11:36
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.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von Guido R.
Guido R.

Registriert seit: 5. Jul 2007
141 Beiträge
 
Delphi 12 Athens
 
#5

AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen

  Alt 12. Dez 2013, 11:43
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
  Mit Zitat antworten Zitat
Headbucket

Registriert seit: 12. Dez 2013
Ort: Dresden
172 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#6

AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen

  Alt 12. Dez 2013, 11:55
@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.

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
Tatsache. Wenn ich die Position vor dem Ermitteln auf 0 setze bekomme ich für unterschiedliche Werte auch unterschiedliche Hashwerte. Was hat er denn dann vorher immer gehasht? Das ist schonmal super - vielen Dank! Dann werde ich jetzt mal versuchen das Einlesen der Daten zu bewerkstelligen.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#7

AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen

  Alt 12. Dez 2013, 12:18
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)
$2B or not $2B

Geändert von himitsu (12. Dez 2013 um 12:20 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.202 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen

  Alt 12. Dez 2013, 12:27
Im Entwickler-Forum ging es generell um die Frage, wie ich gegen eine Manipulation vorgehe. Diese Frage wurde dort geklärt -> Hashfunktion benutzen.
Nicht destotrotz ist es sinnvoll diesen Vorarbeits-Thread auch zu kennen.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen

  Alt 12. Dez 2013, 12:33
Die Frage ist doch, welche Manipulationen man erkennen möchte:

Original
XML-Code:
<?xml version="1.0"?>
<Root>
   <messdaten>
      <messwerte text="Titel" messwert1="2.5" messwert2="7.6"/>
   </messdaten>
   <hashdaten>
      <hash wert="4b0fbe5ec8db72fe0ffaf8e1cbc9f50f"/>
   </hashdaten>
</Root>
Veränderung (Formatierung) - ist egal und kann durchgewunken werden
XML-Code:
<?xml version="1.0"?>
<Root>
<messdaten><messwerte text="Titel" messwert1="2.5" messwert2="7.6"/></messdaten>
<hashdaten><hash wert="4b0fbe5ec8db72fe0ffaf8e1cbc9f50f"/></hashdaten>
</Root>
Veränderung (Attributnamen) - wird erkannt
XML-Code:
<?xml version="1.0"?>
<Root>
<mAssdaten><mAsswerte tAxt="Titel" mAsswert1="2.5" mAsswert2="7.6"/></mAssdaten>
<hashdaten><hash wert="4b0fbe5ec8db72fe0ffaf8e1cbc9f50f"/></hashdaten>
</Root>
Veränderung (Werte) - wird erkannt
XML-Code:
<?xml version="1.0"?>
<Root>
<messdaten><messwerte text="Titel1" messwert1="2.55" messwert2="7.65"/></messdaten>
<hashdaten><hash wert="4b0fbe5ec8db72fe0ffaf8e1cbc9f50f"/></hashdaten>
</Root>
Veränderung (Metadaten anhängen) - ist für die Messwerte egal - kann durchgewunken werden
XML-Code:
<?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>
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.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Headbucket

Registriert seit: 12. Dez 2013
Ort: Dresden
172 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#10

AW: XML-Datei zu Stream | Stream zu Hashwert | XML gegen Manipulation schützen

  Alt 12. Dez 2013, 13:03
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)
Genau diese Dinge werde ich wohl intern nochmal mit dem Entwicklungsleiter klären müssen. Als ich heute morgen kurz mit ihm gesprochen habe war er mit meiner ersten Version, wo nur die Werte gehasht werden nicht zufrieden und wollte alles gehasht haben. Da werde ich nochmal die Vor- und Nachteile mit ihm abklären.
Nicht destotrotz ist es sinnvoll diesen Vorarbeits-Thread auch zu kennen.
Das stimmt natürlich .

@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:
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;
Ich werde mich ggf. nochmal melden, wenn ich das Verfahren geklärt habe. Vielen Dank schonmal für die schnelle und gute Hilfe!

Grüße
Headbucket
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:00 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz