[ Nochmal... ]Schwieriges logisches problem (Niemand kann es, kannst du's ?)



  • EDIT:
    Alles ist gelöst, bloß der erste byte wird komischerwiese falsh entschlüsselt. Siehe Seite2

    Hallo an alle, ich habe ein bild zu dem ganzen gamcht, weil das mit nur text nicht geht, da ich das schol vielemal versucht habe, aber niemand bisher helfen konnte. Ich sitze hier dran schon sehr lange und versuche diesen algorythmus rückgängig zu machen:

    Bild: http://img684.imageshack.us/img684/9397/cppftabenc.png

    Das ganze projekt:
    aktuell: http://www.filefront.com/15816375/tra_cppf.zip (+ tchk)
    (tgen.exe tgen.cpp tchk.exe tchk.cpp tenc.exe tenc.cpp tdec.exe tdec.cpp)
    alt: filefront.com/15254425/!cppf!.zip
    (enc.exe enc.cpp dec.exe dec.cpp tabgen.exe tabgen.cpp tab.dat readme.txt)

    tabgen (tgen): tra_cppf.zip
    tabcheck (tchk): tra_cppf.zip

    BISHERIGER tdec.cpp code: Das problem: Der beginnende byte ist irgendein komisher wert

    // dec.cpp: decryption
    #include <cstdlib>
    #include <cstdio>
    #include <iostream>
    #include <fstream>
    #include <time.h>
    #include <sys/stat.h>
    
    using namespace std;
    
    unsigned char tab[256][256];
    unsigned char *input, *output;
    
    void decrypt2(unsigned char *dest, const unsigned char *src, unsigned long int n)
    {
        for (size_t i = 0; i < 256; ++i)
        {
            if (src[0] == tab[i][i])
            {
                dest[0] = i;
            }
        } 
    
    	for (unsigned long int i = 1; i < n; ++i) // alle zeichen durchlaufen
    	{
    		unsigned long int spaltennummer = src [ i - 1 ]; // die spalten nummer
    
    		//reihe mit der zelle out[i] finden
    		unsigned long int j = 0;
    		for (; j < 256; ++j)
    		{
    			if (tab[j][spaltennummer] == src[i])
    				break;
    		}
    		dest[i] = j;
    	}
    } 
    
    int main (int argc, char* argv[]) // ./tdec table.trt input.txt output.txt
    {
     	cout << "Loading table...";
     	ifstream read_tab(argv[1],ios::binary);
     	read_tab.read((char*)tab[0],sizeof(tab));
     	read_tab.close();
     	cout << " done" << endl;
    	cout << "Loading input...";
    
     	ifstream infile(argv[2], ios::binary);
     	infile.seekg (0, ios::end);
     	unsigned long int length = infile.tellg();
     	infile.seekg (0, ios::beg);
     	input  = new unsigned char[length];
     	output = new unsigned char[length];
     	infile.read((char*)input, length);
     	infile.close();
    	cout << " done" << endl;
    	cout << "Decryption...";
    
    	decrypt2(output, input, length);
    
    	cout << " done" << endl;
    	cout << "Saving output...";
    	ofstream outfile;
     	outfile.open(argv[3], ios::binary);
     	outfile.write((char*)output, length);
     	outfile.close();
     	cout << " done" << endl;
     	return 0;
    }
    

    tenc

    // enc.cpp: encryption
    #include <cstdlib>
    #include <cstdio>
    #include <iostream>
    #include <fstream>
    #include <time.h>
    #include <sys/stat.h>
    
    using namespace std;
    
    unsigned char tab[256][256];
    unsigned char *input, *output;
    
    int main (int argc, char* argv[]) // ./enc table.dat input.txt output.txt
    {
    	cout << "Loading table...";
    	ifstream read_tab(argv[1],ios::binary);
    	read_tab.read((char*)tab[0],sizeof(tab));
    	read_tab.close();
    	cout << " done" << endl;
    
    	cout << "Loading input...";
    	ifstream infile(argv[2], ios::binary);
    	infile.seekg (0, ios::end);
    	unsigned long int length = infile.tellg();
    	infile.seekg (0, ios::beg);
    	input  = new unsigned char[length];
    	output = new unsigned char[length];
    	infile.read((char*)input, length);
    	infile.close();
    	cout << " done" << endl;
    
    	cout << "Encryption...";
    	output[0] = tab[input[0]] [input[length-1]];
    	for (unsigned long int i = 1; i<length; i++)
    	{
    		output[i] = tab[input[i]] [output[i-1]];
    	}
    	cout << " done" << endl;
    
    	cout << "Saving output...";
    	ofstream outfile;
    	outfile.open(argv[3], ios::binary);
    	outfile.write((char*)output, length);
    	outfile.close();
    	cout << " done" << endl;
    	return 0;
    }
    


  • Äh, du willst also anstatt zu erkennen, welche gleichen Zeichen in einer Spalte/Zeile sind, diese Zeichen selber für die Spalte/Zeile generieren?



  • Unter der Annahme, dass die Hauptdiagonale ebenfalls eindeutig ist (sonst ist das ganze offensichtlich unlösbar), sollte das etwa so gehen:

    int i, j;
    
      for(i = 0; tab[i][i] != output[0]; ++i) ;
      input[0] = (unsigned char) i;
      }
    
      for(i = 1; i < length; ++i) {
        for(j = 0; tab[j][output[i - 1]] != output[i]; ++j) ;
        input[i] = (unsigned char) j;
      }
    

    Ist allerdings ungetestet, und du willst ggf. mit Sicherheit ein paar Abfragen einbauen, damit der bei kaputter Tabelle nicht ins Unendliche weiterliest.



  • Funktioniert nicht, es wäre gut wenn sich jemand mal diese dateien runterlädt und selbst rumprobiert...



  • Ist die Frage jetzt, wie man das mit Tabelle entschlüsselt? Oder suchst du eine Schwachstelle im Algorithmus (d. h. Entschlüsselung in absehbarer Zeit ohne Tabelle)?

    EDIT:
    Ich habe das Teil mal umgekehrt:

    #include <iostream>
    #include <ctime>
    using namespace std;
    
    unsigned char tab[256][256];
    
    void ntab (unsigned int xmix, unsigned int ymix)
    {
        cout << "Generating arythmic table...";
        int offs = 0; // offset
        // create arythmetic table
        for (int y = 0; y<256; y++)
        {
            for (int x = 0; x<256; x++)
            {
                 tab[x][y] = x+offs;
            }
            offs++;
        }
        cout << " done" << endl << "Mixing rows...";
        // mix rows X
        unsigned int rnd = 0;
        for (int i = 0; i<1000; i++)
        {
              unsigned char row1[256]; // row X
            unsigned char row2[256];
            unsigned char srow1, srow2;
            srand(time(0)+rnd++);
            srow1 = rand()%256;
    
            srand(time(0)+1+rnd++);
            srow2 = rand()%256;
    
            for (int j = 0; j<256; j++) // load row1
            {
                row1[j] = tab[j][srow1];
            }
            for (int j = 0; j<256; j++) // load row2
            {
                row2[j] = tab[j][srow2];
            }
    
            for (int j = 0; j<255; j++) // replace row1 with row2
            {
                 tab[j][srow1] = row2[j];
            }
            for (int j = 0; j<255; j++) // replace row2 with row1
            {
                 tab[j][srow2] = row1[j];
            }
        }
        rnd = 1;
        cout << " done" << endl << "Mixing columns...";
        for (int i = 0; i<1000; i++)
        {
                     unsigned char row1[256]; // row X
            unsigned char row2[256];
            unsigned char srow1, srow2;
            srand(time(0)+rnd++);
            srow1 = rand()%256;
    
            srand(time(0)+1+rnd++);
            srow2 = rand()%256;
    
            for (int j = 0; j<256; j++) // load row1
            {
                row1[j] = tab[srow1][j];
            }
            for (int j = 0; j<256; j++) // load row2
            {
                row2[j] = tab[srow2][j];
            }
    
            for (int j = 0; j<255; j++) // replace row1 with row2
            {
                 tab[srow1][j] = row2[j];
            }
            for (int j = 0; j<255; j++) // replace row2 with row1
            {
                 tab[srow2][j] = row1[j];
            }
        }
    }
    
    void encrypt1(unsigned char *out, const unsigned char *in, size_t n)
    {
        out[0] = tab[in[0]] [in[0]];
        for (unsigned long int i = 1; i<n; i++)
        {
            out[i] = tab[in[i]] [out[i-1]];
        }
    }
    
    void encrypt2(unsigned char *out, const unsigned char *in, size_t n)
    {
        out[0] = tab[in[0]] [in[0]];
    	for (size_t i = 1; i < n; ++i)
    	{
    		//out[i] = tab
    		//	[ in[i] ]
    		//	[ out [i - 1] ];
    
    		//anders geschrieben:
    		unsigned char *reihe = tab[ in[i] ];
    		size_t spaltennummer = out [ i - 1 ];
    		unsigned char zelle = reihe [ spaltennummer ];
    		out[i] = zelle;
    	}
    }
    
    void decrypt2(unsigned char *dest, const unsigned char *src, size_t n)
    {
    	for (size_t i = 0; i < 256; ++i)
    	{
    		if (src[0] == tab[i][i])
    		{
    			dest[0] = i;
    		}
    	}
    	for (size_t i = 1; i < n; ++i)
    	{
    		size_t spaltennummer = src [ i - 1 ];
    		//reihe mit der zelle out[i] finden
    		size_t j = 0;
    		for (; j < 256; ++j)
    		{
    			if (tab[j][spaltennummer] == src[i])
    				break;
    		}
    		dest[i] = j;
    	}
    }
    
    int main()
    {
    	ntab(10000, 10000);
    	unsigned char buf[1024];
    	const unsigned char *text = (const unsigned char *)"hallo";
    
    	encrypt2(buf, text, 6);
    
    	unsigned char klartext[1024];
    
    	decrypt2(klartext, buf, 6);
    
    	cout << endl << "Entschluesselt: " << (const signed char *)klartext << endl;
    
    	while (true)
    		;
        return 0;
    }
    

    EDIT: Funktioniert nun.



  • Mit tabelle... Wenn es ohne tabelle wär, so geht das überhaupt nicht. Hehandle die tabelle wie eine art passwort, bloß viel größer und mit der gegebenen formation (sihe bild)



  • Das erste Zeichen lässt sich doch genauso dekodieren?!?



  • hustbaer schrieb:

    Das erste Zeichen lässt sich doch genauso dekodieren?!?

    EDIT: Kann sein, ich war davon ausgegangen, dass out[0] nicht eindeutig ist.

    void encrypt1(unsigned char *out, const unsigned char *in, size_t n)
    {
        out[0] = tab[in[0]] [in[0]]; //<-- hier
        for (unsigned long int i = 1; //fängt bei 1 an
     i<n; i++)
        {
            out[i] = tab[in[i]] [out[i-1]];
        }
    }
    

    Die Frage ist, ob die Diagonale von links oben nach rechts unten jede Zahl nur 1 mal enthält.

    EDIT 2: Hat sich erledigt, die ist eindeutig:

    void decrypt2(unsigned char *dest, const unsigned char *src, size_t n)
    {
    	for (size_t i = 0; i < 256; ++i)
    	{
    		if (src[0] == tab[i][i])
    		{
    			dest[0] = i;
    		}
    	}
    
    	for (size_t i = 1; i < n; ++i)
    	{
    		size_t spaltennummer = src [ i - 1 ];
    		//reihe mit der zelle out[i] finden
    		size_t j = 0;
    		for (; j < 256; ++j)
    		{
    			if (tab[j][spaltennummer] == src[i])
    				break;
    		}
    		dest[i] = j;
    	}
    }
    


  • Danke vielmals.

    EDIT: Geht doch nicht, der erste buchstabe wird nur verschlüsselt durch enc.exe wird aber von dec.exe einfach weggelassen, und etwas intern geht auch nicht, bin grad dabei dies herauszufinden.... 😕



  • das problem ist, dass man den ersten unentschlüsselten buchstaben kennen muss.
    das ist wie beim xor, man bekommt also 256 verschiedene lösungen heraus.



  • Also, was ich nicht verstehe ist, dass wenn bei meinem algorythm ein fehler auftritt, alles andere danach auch falsh ist o.O



  • versuch mal das:

    void decrypt(unsigned char *out, const unsigned char *in, size_t size, unsigned char start)
    {
        while (size)
        {
            for (unsigned i = 0; i < 256; ++i)
            {
                if (tab[i][start] == *in)
                {
                    *out = i;
                    start = *in;
                    break;
                }
            }
            ++out;
            ++in;
        }
    }
    


  • nein, ich meine alles ist ok. Das einzige was falsh scheint ist der beginnende buchstabe nach der entschlüsselung...



  • Also, ich habe nun lange versucht das problem mit dem ersten buchstaben zu lösen, funktioniert aber alles nicht, ich brauche unbedingd nochmal bitte hilfe...
    Ich habe tabgen nochmal geschreiben, und das ist jetzt eindeutig strukturiert. Auch ist tchk dazugekommen (Überprüft ob tabellen richtig sind).
    Das einzige, was falsch ist ist also der erste buchstabe, alles andere stimmt (MD5 checked) überein...


Log in to reply