.dat Dateien verwenden



  • Hallo,
    Ich würde gerne zum speichern von Daten Dateien des formats dat verwenden. Ich will jedoch nicht nur einen normalen text speichern, zumindest kein klartext, sondern diese kodierungen, die man bei anderen anwendungen sieht. Wenn man sich die im editor ansieht steht weiss auf schwarz sowas wie null, eol etc.
    Wie geht man damit um. Google liefert mir keine ergebnisse, ausser dass es irgendwie gezippte strukturen in dat files gibt...

    Hoffe ihr könnt mich da aufklären.

    Danke im voraus
    Mfg


  • Mod

    "dat" als Dateiformat sagt so ziemlich überhaupt gar nichts aus.

    Meinst du Binärdaten? Was willst du erreichen? Was versprichst du dir davon, wenn du nicht einmal weißt, was das bedeutet?



  • Naja ich möchte halt eben werte speichern, die nur das programm lesen kann. Muss jetzt nicht zwingend ein dat format sein. Dachte nur dass dieses für sowas eingesetzt wird.



  • Was soll den ein "dat Format" Deiner Meinung sein?



  • "dat" hat kein Format. Die Endung "dat" wird meistens verwendet, um zu kennzeichnen, dass diese Datei irgendwelche Daten enthält. In welchem Format genau diese Daten vorliegen, weiß nur der Programmierer.


  • Mod

    kralo9 schrieb:

    Naja ich möchte halt eben werte speichern, die nur das programm lesen kann.

    Eine Verschlüsselung? Zu welchem Zweck? Etwas mehr als eine Unannehmlichkeit wird das für einen Hacker sowieso nicht, da ein lokales Programm, welches lokale verschlüsselte Daten liest, zwangsweise auch den Schlüssel lokal haben muss, der dann aus dem Programm ausgelesen werden kann.

    Oder geht es darum, dass die Daten nicht direkt von einem Menschen gelesen werden können, da du gesehen hast, dass die coolen Kinder Programme schreiben, bei denen das so ist?



  • SeppJ schrieb:

    Oder geht es darum, dass die Daten nicht direkt von einem Menschen gelesen werden können, da du gesehen hast, dass die coolen Kinder Programme schreiben, bei denen das so ist?

    Näh, wahrscheinlich will er nur nicht das die Mehrheit seiner Nutzer (DAUs) einfach Highscores oder so in der Datei ändern kann.

    Wahrscheinlich hat er PI gesehen.


  • Mod

    Hacker schrieb:

    SeppJ schrieb:

    Oder geht es darum, dass die Daten nicht direkt von einem Menschen gelesen werden können, da du gesehen hast, dass die coolen Kinder Programme schreiben, bei denen das so ist?

    Näh, wahrscheinlich will er nur nicht das die Mehrheit seiner Nutzer (DAUs) einfach Highscores oder so in der Datei ändern kann.

    Dagegen hilft nur permanenter Onlinezwang während des Spiels. Das ist, was die ganz coolen Kinder derzeit machen.



  • SeppJ schrieb:

    Hacker schrieb:

    SeppJ schrieb:

    Oder geht es darum, dass die Daten nicht direkt von einem Menschen gelesen werden können, da du gesehen hast, dass die coolen Kinder Programme schreiben, bei denen das so ist?

    Näh, wahrscheinlich will er nur nicht das die Mehrheit seiner Nutzer (DAUs) einfach Highscores oder so in der Datei ändern kann.

    Dagegen hilft nur permanenter Onlinezwang während des Spiels.

    Er kann sich aber keinen Server leisten, noch kennt er sich mit Netzwerkprogrammierung aus... ⚠

    Dagegen wäre ein einfacher Verschlüsselungsalgorithmus einfach, und die PE zu disassemblieren und ihn zu knacken wäre für die meisten doch ein wenig zu viel.


  • Mod

    So langsam wird's doch sehr spekulativ. Wir brauchen eine Antwort des Threaderstellers.



  • Ich will einfach nur Daten abspeicher, Variablen oder Texte, die nicht einfach manipuliert werden können. Also wenn der DAU die Datei "punkte.dat" öffnet und sieht da seinen namen und die punktzahl, dass er aus 214142 einfach 999999999 macht.

    Mehr eigentlich nicht 😞



  • kralo9 schrieb:

    Ich will einfach nur Daten abspeicher, Variablen oder Texte, die nicht einfach manipuliert werden können. Also wenn der DAU die Datei "punkte.dat" öffnet und sieht da seinen namen und die punktzahl, dass er aus 214142 einfach 999999999 macht.

    Dann verwende einen simplen Verschlüsselungsalgorithmus. Das wird zumindest eine kleine Schwelle setzen.



  • Und was gäbe es da für Möglichkeiten? Also nur einfache Codierungen kein ARS oder wie das heißt 😃 . Am besten eine, die man für Buchstaben und Zahlen einsetzen kann.



  • Es heisst AES bzw. Rijndael. Und wieso nicht sowas? Gibt genug fertige Implementierungen, schnapp dir eine und verwende sie.

    Und... wenn du deine Scores absichern willst, würde ich empfehlen auf jeden Fall ne Prüfsumme mit zu speichern. Denn die Stelle wo der Score gespeichert wird findet man sonst früher oder später durch einfaches ausprobieren. Und als schlechter Spieler wird fast jeder zufällige Score reichen um sich zu verbessern, den man trotz Verschlüsselung leicht bekommen kann indem man einfach irgendwas an der passenden Stelle einträgt.


  • Mod

    Man kann eine einfache XOR-Verschlüsselung nehmen. Diese ist sehr einfach, da Verschlüsseln und Entschlüsseln identisch sind, das Ergebnis ist aber trotzdem unlesbar. Das kann man dann auch elegant in den Streambuf des Dateistreams packen, so dass man sehr kompakten Code erhält:

    #include <streambuf> 
    #include <ios>    
    #include <fstream>   // Nur für das Beispiel
    #include <string>    // Nur für das Beispiel
    #include <iostream>  // Nur für das Beispiel
    
    class seppjs_super_duper_codierender_streambuf : public std::streambuf
    {
    public:
      seppjs_super_duper_codierender_streambuf(std::ios& in, char code)
        : in(in) 
        , buf (in.rdbuf()) 
        , code(traits_type::to_int_type(code))
      {
        in.rdbuf(this); 
      }
      ~seppjs_super_duper_codierender_streambuf()
      {
        in.rdbuf(buf); 
      }
    
    protected:
      virtual int_type underflow() 
      {
        int_type c = buf->sgetc();
        return traits_type::eq_int_type( c, traits_type::eof()) ? c : c ^ code;  
      }
      virtual int_type uflow()   
      {
        int_type c = buf->sbumpc();
        return traits_type::eq_int_type( c, traits_type::eof()) ? c : c ^ code;
      }
      virtual int_type overflow(int_type c) 
      {
        buf->sputc(c ^ code);
        return c;  
      }
    private:
      seppjs_super_duper_codierender_streambuf( const seppjs_super_duper_codierender_streambuf& );    
      seppjs_super_duper_codierender_streambuf& operator=( const seppjs_super_duper_codierender_streambuf& ); 
    
      std::ios& in;
      std::streambuf* buf;
      int_type code;
    };
    
    int main()
    {
      {
        std::ofstream ofs("test.dat");
        seppjs_super_duper_codierender_streambuf foo(ofs, 't'); // So lange foo lebt, wird ifs codiert
    
        ofs << "Hallo Welt!\n";
      }
      {
        std::ifstream ifs("test.dat");
        seppjs_super_duper_codierender_streambuf foo(ifs, 't'); 
        std::string wort;
        while (ifs >> wort)
          std::cout<<wort<<'\n';    
      }
    }
    

    Da du die Streambuftechnik wohl sowieso nicht verstehen wirst, habe ich gar nicht erst versucht, es lesbar zu machen. Wichtig für dich ist das Beispiel, wie man es benutzt (also die main). So kannst du beliebige Streams codieren und dekodieren. Sieh dir nach Programmdurchlauf mal die test.dat an, ob dir das unleserlich genug ist. Da die ganze Verschlüsselung hinter den Kulissen der Streams abläuft, kannst du alle dir bekannten Lese-/Schreibeaktionen wie gewohnt benutzen und brauchst dich um gar nichts mehr zu kümmern. Im Idealfall kannst du sogar ein schon vorhandenes Programm mit einer einzigen Zeile pro Stream auf Verschlüsselung umstellen, ohne sonst irgendetwas ändern zu müssen.

    Das ist natürlich keine große Sicherheit, da es im Gegensatz zu AES einer Kryptoanalyse nicht lange Stand hält. Aber bei beiden stünde der Schlüssel sowieso fest eincodiert im Programm, da braucht man sich gar nicht den Mehraufwand und die Scheinsicherheit von AES zu geben. Wer wirklich will, liest den Schlüssel einfach aus dem Maschinencode. Dagegen kannst du prinzipiell nichts machen.



  • <T#

    ist das was rauskommt bei der xor verschlüsselung. WOW! Danke seppj! Genau sowas habe ich gesucht: Komische, keinem Menschen bekannten (zumindest DAU) Zeichen!
    Vielen, vielen... Dank!

    Nur nochmal kurz:

    ich muss beim Streamen nur

    seppjs_super_duper_codierender_streambuf foo(ofs, 't');
    

    zum Verschlüsseln und zum Entschlüsseln auch nur:

    seppjs_super_duper_codierender_streambuf foo(ifs, 't');
    

    angeben?

    t ist der Schlüssel oder?

    Danke nochmals,
    mfg


  • Mod

    't' ist hier der Schlüssel. Kannst natürlich auch was anderes nehmen. Bloß der Schlüssel '\0' macht nicht viel Sinn, da dann wieder das Original raus käme.

    kralo9 schrieb:

    Nur nochmal kurz:

    ich muss beim Streamen nur

    seppjs_super_duper_codierender_streambuf foo(ofs, 't');
    

    zum Verschlüsseln und zum Entschlüsseln auch nur:

    seppjs_super_duper_codierender_streambuf foo(ifs, 't');
    

    angeben?

    Sofern ich dich richtig verstehe, hast du es richtig verstanden.

    Wenn du irgendeinen Stream hast (cin (ein istream), cout (ein ostream), Dateistreams, Stringstreams, egal was), dann kannst du in diesem meinen Verschlüsseler installieren:

    seppjs_super_duper_codierender_streambuf hier_irgendein_name_egal_was(hier_der_streamname, 't');  // Statt 't' beliebiges Zeichen als Schlüssel.
    

    Das Objekt hier_irgendein_name_egal_was hängt sich dann in den Stream und solange es lebt, wird alles was der Stream macht (egal ob Lesen oder Schreiben) verschlüsselt bzw. entschlüsselt:

    int main()
    {
      using std::cout;
      cout << "Verschlüssele cout, nun folgt Buchstabensalat: ";
      {
        seppjs_super_duper_codierender_streambuf foo(cout, '2'); 
        cout << 123 << "abc" << std::endl;  // Selbst der Zeilenumbruch wird verschlüsselt
      } // Hier endet die Lebenszeit von foo, der Originalstreambuf wird wieder hergestellt
      cout << " Nun nicht mehr verschlüsselt\n";
    }
    


  • Aha also muss ich den Bereich, wo die Ver/-Entschlüsselung geschieht eingeschweiftklammern?

    Ich hab so ziemlich keinen Schimmer, wie deine Klasse aufgebaut ist. Bin mit virtuellen Funktionen und Vererbung nicht vertraut, weil ich das nicht so ganz verstehe 😞

    Vielleicht kannst du mir das kurz erklären ("kurz" - haha) oder einen Link geben, wo das ausführlich erklärt ist. Am besten deutsch, aber englisch geht auch.

    EDIT Nr n: Achsoooo! Das ist nur ein extra Scope für die Verschlüsselen *facepalm* :D:D sorry



  • Und mit diesem Doppelpost bedanke ich mich vorallem bei SeppJ, aber auch bei den anderen für diese zahlreichen Antworten.
    Ich beende diesen Thread hiermit mit dem Code:

    finish = true;
     if(finish){
       Thread.Close();
     }
    return "Danke";
    

  • Mod

    kralo9 schrieb:

    Aha also muss ich den Bereich, wo die Ver/-Entschlüsselung geschieht eingeschweiftklammern?

    EDIT Nr n: Achsoooo! Das ist nur ein extra Scope für die Verschlüsselen *facepalm* :D:D sorry

    Ja, das ist der Lebensbereich des Verschlüsselers. Man will das ja eventuell auch irgendwann mal wieder abschalten. An sich spricht aber nichts dagegen, dass der auch das ganze Programm über aktiv ist.

    Erklärung: Ja, das ist ein bisschen schwierig zu erklären, besonders wenn du nicht einmal virtuelle Funktionen & Co. kennst. Da muss man tief in den Aufbau der Streams einsteigen, um das zu verstehen, darüber sind ganze Bücher geschrieben worden:
    Standard C++ IOStreams and Locales | ISBN: 0201183951

    Ich versuche es mal:
    Verschlüsselung:
    http://en.wikipedia.org/wiki/XOR_cipher
    Lass dich nicht von dem Absatz über One-Time-Pads verwirren, das ist theoretischer Unfug. Hier wird die allersimpeltste Methode aus dem Beispiel benutzt.

    Aufbau der Streams:
    Jetzt wird's kompliziert. Was man wissen muss (ich unterschlage bewusst so etwas wie locales, die alles noch verkomplizieren):
    Ein Stream in C++ ist ein abstraktes Konstrukt, welches aus einer langen Kette von Zeichen (die von irgendwoher kommen) etwas liest oder in eine lange Kette von Zeichen etwas schreibt. Denk dir einen Lochstreifenleser oder Lochkartenstanzer. Der Stream selber tut dabei recht wenig, er stellt Funktionen zur Verfügung, mit denen man diese Zeichen irgendwie interpretieren kann (z.B. als Zahl oder als String) oder mit denen man Vor und Zurück spulen kann. Aber ansonsten hat er keine Ahnung, wo die Zeichen herkommen oder hingehen.
    Dazu hat der Stream einen Streambuf: Dieser liest dann tatsächlich Zeichen aus einer Datei oder aus dem Speicher (naja, eigentlich nicht, meistens wird er das Betriebssystem fragen, dies zu tun. Aber hier stehen tatsächlich mal konkrete Befehle, die Zeichen zu holen). Er stellt dabei eine allgemeine Schnittstelle bereit, über die der Stream sich die Zeichen holen kann. Mehr noch, er verwaltet auch einen gewissen Pufferbereich (daher der Name), der hier aber nicht wichtig ist. Wichtig ist, wenn die Pufferverwaltung feststellt, dass der Puffer leer/voll ist oder sonstwie Zeichen gebraucht werden, dann ruft sie die Funktionen underflow/ uflow bzw. overflow auf. An dieser Stelle habe ich mich eingehakt, meine Klasse überschreibt diese Funktionen und macht, dass alle Zeichen die hier vorbei kommen geXORt werden. Der Stream benutzt also den Streambuf, dieser bentuzt overflow/underflow/uflow, diese habe ich überschrieben, meine Funktionen verschlüsseln und rufen dann die Lese-/Schreiboperationen des Originalstreambuf auf und dieser weiß dann, was mit den Zeichen zu tun ist (z.B. in eine Datei schreiben).

    Und vermutlich ist diese Erklärung total unverstandlich, aber besser bekomme ich es nicht hin. Du kannst hier im Forum mal nach Beiträgen von "Werner Salomon" suchen, der ist unser Experte für Streams und hat schon viele lange Beiträge mit vielen Erklärungen zu verschiedenen Streamthemen geschrieben.

    Programmiertechnik:

    • Zeile 7: Vererbung. Meine Klasse ist nun auch ein std::streambuf und kann automatisch alles das, was dieser kann und kann anstelle eines std::streambuf benutzt werden.
    • 10-16: Der Konstruktor meiner Klasse. Zeile 11 merkt sich, zu welchem Stream sie gehört, Zeile 12 merkt sich den Original-streambuf, den wir ersetzen, Zeile 15 führt die Ersetzung durch, Zeile 13 speichert den code. Das traits_type::to_int_type(code) ist bloß eine ganz abstrakte Schreibweise einer Umwandlung char zu int, damit der Code auch in noch so exotischen Systemen läuft. In 99.99% aller Fälle kann man das auch weglassen.
    • Zeile 17-20, der Destruktor. Wird aufgerufen, wenn der Scope des Objekts endet. Zeile 19 reinstalliert den original Streambuf in dem Stream.
    • Zeile 23-37: Die Lese und Schreibfunktionen eines Streambuf überschreiben wir. Da sie virtual sind, werden sie auch dann aufgerufen, wenn der Aufrufende nur einen Verweis auf einen allgemeinen std::streambuf hat anstatt auf unseren spezialisierten Streambuf. Zeilen 25,30 und 25 benutzen die Funktionen des Originalstreambufs, um diesem ein Zeichen zu entnehmen oder eines reinzuschreiben, wir haben uns mit unserem Streambuf also nur zwischen Originalstreambuf und Stream gehängt. Die eigentlich Verschlüsselung ist das c ^ Code . Das '^' ist der XOR-Operator. Die Prufung auf eof in den Zeilen 26 und 31 dient dazu, dass das Sonderzeichen, welches das Streamende (z.B. Dateiende) signalisiert beim Auslesen nicht entschlüsselt wird. Sonst bekäme der Stream gar nicht mit, wann das Dateiende erreicht ist.
    • Zeilen 39 und 40 verhindern, dass Kopien von dem Objekt gemacht werden, sonst käme bei einer Kopie alles total durcheinander, welcher Streambuf nun wo hängt. Nun bekommt man einen Linkerfehler, wenn man eine Kopie versucht. In C++11 könnte man dies eleganter durch = delete; lösen.
    • Zeile 42-44: Die Daten, die wir zum Betrieb brauchen. std::ios ist ein allgemeines Streamobjekt, alle Streams erben von diesem, wir können so also einen Verweis auf jede Art von Stream speichern.

Anmelden zum Antworten