Threefish selber implementieren


  • Mod

    Gar nicht, denn das gibt es in C++ schlichtweg nicht, weil wofür? Selbst in C wurden die wieder abgeschafft. Und wenn du altes C machen würdest, dann sind die auch anders gedacht als du denkst, aber das ist erst einmal egal, weil du ja kein altes C machst.



  • @EinNutzer0 sagte in Threefish selber implementieren:

    Was muss ich hier umstellen, damit mich Visual Studio nicht anmeckert, dass nur Arrays mit konstanten Werten erstellt werden dürfen? Ich vermute, das ist nicht ISO-Standard...

    Microsoft hatte nie einen compliant C-Compiler. Leb' Damit. Auch: Wer VLAs braucht hat die Kontrolle über sein Leben verloren.


  • Gesperrt

    Bin mit dem Debugger durch:

    // ConsoleApplication1.cpp : Diese Datei enthält die Funktion "main". Hier beginnt und endet die Ausführung des Programms.
    //
    
    #include <cstdint>
    #include <cstring>
    #include <iostream>
    #include <sstream>
    
    using namespace std;
    
    typedef uint8_t u8;
    typedef uint64_t u64;
    
    struct sizes
    {
    	const size_t len1, len2, len3;
    };
    
    sizes get_sizes(const string& s) {
    	size_t len1 = s.length();
    	size_t len2 = 72 * 8;
    	if (len2 < len1) {
    		len2 = len1;
    	}
    	while (len2 % 8 != 0) {
    		len2++;
    	}
    	size_t len3 = len2 * 8;
    	sizes ss{ len1, len2, len3 };
    	return ss;
    }
    
    size_t min_len_from_string(size_t len)
    {
    	while (len <= 72 * 8 || len % 8 != 0)
    	{
    		len++;
    	}
    	return len / 8;
    }
    
    size_t min_len_from_string_2(size_t len)
    {
    	return len / 8;
    }
    
    void string_to_u64_array(const size_t len, const string& s1, u64  a[])
    {
    	string s2 = "";
    	for (size_t i = 0; i < len * 8; i++)
    	{
    		s2 += s1[i % s1.length()];
    	}
    	for (size_t i = 0; i < len; i++)
    	{
    		a[i] = 0;
    		for (size_t j = 0; j < 8; j++)
    		{
    			a[i] <<= 8;
    			a[i] |= (u8)s2[i * 8 + j];
    		}
    	}
    }
    
    string u64_array_to_string(const size_t len, u64 a[])
    {
    	string s = "";
    	for (size_t i = 0; i < len; i++)
    	{
    		u64 t = a[i];
    		for (size_t j = 0; j < 8; j++)
    		{
    			u8 c = (u8)t;
    			s.insert(0, 1, c);
    			t >>= 8;
    		}
    	}
    	return s;
    }
    
    u64 rl64(u64 x, u8 r)
    {
    	return (x << (r & 63)) | (x >> (64 - (r & 63)));
    }
    
    u64 rr64(u64 x, u8 r)
    {
    	return (x >> (r & 63)) | (x << (64 - (r & 63)));
    }
    
    void mix(u64 a, u64 b, u64* c, u64* d, u8 r)
    {
    	u64 tmp = a + b;
    	*d = rl64(b, r) ^ tmp;
    	*c = tmp;
    }
    
    void mixinv(u64 c, u64 d, u64* a, u64* b, u8 r)
    {
    	u64 tmp = rr64(c ^ d, r);
    	*a = c - tmp;
    	*b = tmp;
    }
    
    void threefish_round(size_t nwords, u64 v[], u8 r[], u8 p[])
    {
    	for (size_t w = 0; w < nwords; w += 2)
    	{
    		mix(v[p[w]], v[p[w + 1]], &v[p[w]], &v[p[w + 1]], r[w / 2]);
    	}
    }
    
    void threefish_roundinv(size_t nwords, u64 v[], u8 r[], u8 p[])
    {
    	for (size_t w = 0; w < nwords; w += 2)
    	{
    		mixinv(v[p[w]], v[p[w + 1]], &v[p[w]], &v[p[w + 1]], r[w / 2]);
    	}
    }
    
    void encrypt(size_t nwords, u64 plaintext[], u64 ciphertext[], u64 xkey[])
    {
    	size_t nrounds = 72;
    	u8 rot[8][2] = {
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    	};
    	u8 perm[4][4] = {
    		{0, 1, 2, 3},
    		{0, 3, 2, 1},
    		{0, 1, 2, 3},
    		{0, 3, 2, 1},
    	};
    
    	u64* v = new u64[nwords];
    	for (size_t w = 0; w < nwords; w++)
    	{
    		v[w] = plaintext[w];
    	}
    	for (size_t n = 0; n < nrounds; n += 8)
    	{
    		for (size_t w = 0; w < nwords; w++)
    		{
    			v[w] += xkey[w];
    		}
    		threefish_round(nwords, v, rot[(n + 0) % 8], perm[0]);
    		threefish_round(nwords, v, rot[(n + 1) % 8], perm[1]);
    		threefish_round(nwords, v, rot[(n + 2) % 8], perm[2]);
    		threefish_round(nwords, v, rot[(n + 3) % 8], perm[3]);
    
    		for (size_t w = 0; w < nwords; w++)
    		{
    			v[w] += xkey[w];
    		}
    		threefish_round(nwords, v, rot[(n + 4) % 8], perm[0]);
    		threefish_round(nwords, v, rot[(n + 5) % 8], perm[1]);
    		threefish_round(nwords, v, rot[(n + 6) % 8], perm[2]);
    		threefish_round(nwords, v, rot[(n + 7) % 8], perm[3]);
    	}
    	for (size_t w = 0; w < nwords; w++)
    	{
    		ciphertext[w] = v[w] + xkey[w];
    	}
    	delete[] v;
    }
    
    void decrypt(size_t nwords, u64 plaintext[], u64 ciphertext[], u64 xkey[])
    {
    	size_t nrounds = 72;
    	u8 rot[8][2] = {
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    	};
    	u8 perm[4][4] = {
    		{0, 1, 2, 3},
    		{0, 3, 2, 1},
    		{0, 1, 2, 3},
    		{0, 3, 2, 1},
    	};
    
    	u64* v = new u64[nwords];
    	for (size_t w = 0; w < nwords; w++)
    	{
    		v[w] = ciphertext[w] - xkey[w];
    	}
    	for (int n = (int)nrounds - 8; n >= 0; n -= 8)
    	{
    
    		threefish_roundinv(nwords, v, rot[(n + 7) % 8], perm[3]);
    		threefish_roundinv(nwords, v, rot[(n + 6) % 8], perm[2]);
    		threefish_roundinv(nwords, v, rot[(n + 5) % 8], perm[1]);
    		threefish_roundinv(nwords, v, rot[(n + 4) % 8], perm[0]);
    		for (size_t w = 0; w < nwords; w++)
    		{
    			v[w] -= xkey[w];
    		}
    
    		threefish_roundinv(nwords, v, rot[(n + 3) % 8], perm[3]);
    		threefish_roundinv(nwords, v, rot[(n + 2) % 8], perm[2]);
    		threefish_roundinv(nwords, v, rot[(n + 1) % 8], perm[1]);
    		threefish_roundinv(nwords, v, rot[(n + 0) % 8], perm[0]);
    		for (size_t w = 0; w < nwords; w++)
    		{
    			v[w] -= xkey[w];
    		}
    	}
    	for (size_t w = 0; w < nwords; w++)
    	{
    		plaintext[w] = v[w];
    	}
    	delete[] v;
    }
    
    string encrypt_string_with_password(const sizes ss, const string& s, const string& p) {
    	u64* plaintext = new u64[ss.len2];
    	u64* ciphertext = new u64[ss.len2];
    	u64* xkey = new u64[ss.len2];
    	string_to_u64_array(ss.len2, s, plaintext);
    	string_to_u64_array(ss.len2, p, xkey);
    	encrypt(ss.len2, plaintext, ciphertext, xkey);
    	string r = u64_array_to_string(ss.len2, ciphertext);
    	delete[] plaintext, ciphertext, xkey;
    	return r;
    }
    
    string decrypt_string_with_password(const sizes ss, const string& s, const string& p) {
    	u64* plaintext = new u64[ss.len3];
    	u64* ciphertext = new u64[ss.len3];
    	u64* xkey = new u64[ss.len3];
    	string_to_u64_array(ss.len3, s, ciphertext);
    	string_to_u64_array(ss.len3, p, xkey);
    	decrypt(ss.len3, plaintext, ciphertext, xkey);
    	string r = u64_array_to_string(ss.len1, plaintext);
    	delete[] plaintext, ciphertext, xkey;
    	return r;
    }
    
    int main()
    {
    	string s = "HhaLLoio";
    	string p = "Buchstab";
    	sizes ss = get_sizes(s);
    	string e = encrypt_string_with_password(ss, s, p);
    	string d = decrypt_string_with_password(ss, e, p);
    	cout << e << endl;
    
    	return 0;
    }
    
    // Programm ausführen: STRG+F5 oder Menüeintrag "Debuggen" > "Starten ohne Debuggen starten"
    // Programm debuggen: F5 oder "Debuggen" > Menü "Debuggen starten"
    
    // Tipps für den Einstieg: 
    //   1. Verwenden Sie das Projektmappen-Explorer-Fenster zum Hinzufügen/Verwalten von Dateien.
    //   2. Verwenden Sie das Team Explorer-Fenster zum Herstellen einer Verbindung mit der Quellcodeverwaltung.
    //   3. Verwenden Sie das Ausgabefenster, um die Buildausgabe und andere Nachrichten anzuzeigen.
    //   4. Verwenden Sie das Fenster "Fehlerliste", um Fehler anzuzeigen.
    //   5. Wechseln Sie zu "Projekt" > "Neues Element hinzufügen", um neue Codedateien zu erstellen, bzw. zu "Projekt" > "Vorhandenes Element hinzufügen", um dem Projekt vorhandene Codedateien hinzuzufügen.
    //   6. Um dieses Projekt später erneut zu öffnen, wechseln Sie zu "Datei" > "Öffnen" > "Projekt", und wählen Sie die SLN-Datei aus.
    
    

    Zeile 201: C6385: Ungültige Daten werden aus "rot" gelesen.

    Und genau das verstehe ich nicht, kann mir jemand helfen? 😞

    Die Speicherzugriffsverletzung erfolgt wohl in Zeile 117: r[w / 2]);.



  • @EinNutzer0

    Bin mit dem Debugger durch:

    Nein bist du ganz und gar nicht. Warum weigerst du dich so vehement einen Debugger zu nutzen?


    Ein kleine Internet-Recherche zu C6385 liefert: Invalid data: accessing buffer-name, the readable size is size1 bytes, but size2 bytes may be read: Lines: x, y

    Du musst also einen Breakpoint in Zeile 201 legen und jeden Indize und jede Array-Größe anschauen und überprüfen. Springe unbedingt auch in die Funktion threefish_roundinv und überprüfe die Grenzen der Parameter.

    PS:
    Wenn du std::vector oder ähnliches nutzen würdest, würdest du auch die Größen der Parameter erkennen. Denn ich frage mich in der Funktion threefish_roundinv wieviele Elemente der Parameter r enthält und wie groß w/2 werden kann.


  • Gesperrt

    @Quiche-Lorraine sagte in Threefish selber implementieren:

    Nein bist du ganz und gar nicht. Warum weigerst du dich so vehement einen Debugger zu nutzen?

    Ist das jetzt von dir eine Realitätsverweigerung oder Lügenunterstellung? 😊 (Nur als kleine Randnotiz: Ich lüge nie... das ist eine schlechte Angewohnheit. Ich würde nur in Ausnahmefällen lügen, also zum Beispiel unter Folterung usw., wenn erheblicher, unabwendbarer Schaden drohen würde. Das ist zum Teil bedingt durch meine Sozialisierung und zum anderen durch genetische Faktoren. Ich hätte doch nix davon, zu behaupten, ich hätte den Debugger verwendet, wenngleich ich ihn nicht verwendet hätte...)

    Ich bin mit dem Debugger durchgegangen. Brauchst du dafür extra einen Beweis?



  • Und dann hast du dir die Variablenwerte angeschaut, wenn der Speicherzugriffsfehler erfolgt?

    Das bei threefish_round und threefish_roundinv übergebene Array r hat doch nur 2 Werte. Wie soll dann der Zugriff darauf mit dem Index w / 2 in der Schleife sinnvoll sein?

    Soll da evtl. w % 2 hin?


  • Gesperrt

    Ich wollte nur kurz schreiben, dass es nun geklappt hat. 🙂

    // A Threefish implementation: 256bit, 4 words, 72 rounds
    
    #include <cstdint>
    #include <cstring>
    #include <iostream>
    #include <sstream>
    
    using namespace std;
    
    typedef uint8_t u8;
    typedef uint64_t u64;
    
    void string_to_u64_array(const string& s1, u64 a[4])
    {
    	const size_t len = 4;
    	string s2 = "";
    	for (size_t i = 0; i < len * 8; i++)
    	{
    		s2.insert(0, 1, s1[i % s1.length()]);
    	}
    	for (size_t i = len; i > 0;)
    	{
    		i--;
    		a[i] = 0;
    		for (size_t j = 8; j > 0;)
    		{
    			j--;
    			a[i] <<= 8;
    			a[i] |= (u8)s2[i * 8 + j];
    		}
    	}
    }
    
    string u64_array_to_string(u64 a[4])
    {
    	const size_t len = 4;
    	string s = "";
    	for (size_t i = 0; i < len; i++)
    	{
    		u64 t = a[i];
    		for (size_t j = 0; j < 8; j++)
    		{
    			u8 c = (u8)t;
    			s.insert(0, 1, c);
    			t >>= 8;
    		}
    	}
    	return s;
    }
    
    u64 rl64(u64 x, u8 r)
    {
    	return (x << (r & 63)) | (x >> (64 - (r & 63)));
    }
    
    u64 rr64(u64 x, u8 r)
    {
    	return (x >> (r & 63)) | (x << (64 - (r & 63)));
    }
    
    void mix(u64 a, u64 b, u64* c, u64* d, u8 r)
    {
    	u64 tmp = a + b;
    	*d = rl64(b, r) ^ tmp;
    	*c = tmp;
    }
    
    void mixinv(u64 c, u64 d, u64* a, u64* b, u8 r)
    {
    	u64 tmp = rr64(c ^ d, r);
    	*a = c - tmp;
    	*b = tmp;
    }
    
    void threefish_round(size_t nwords, u64 v[4], u8 r[2], u8 p[4])
    {
    	for (size_t w = 0; w < nwords; w += 2)
    	{
    		mix(v[p[w]], v[p[w + 1]], &v[p[w]], &v[p[w + 1]], r[w / 2]);
    	}
    }
    
    void threefish_roundinv(size_t nwords, u64 v[4], u8 r[2], u8 p[4])
    {
    	for (size_t w = 0; w < nwords; w += 2)
    	{
    		mixinv(v[p[w]], v[p[w + 1]], &v[p[w]], &v[p[w + 1]], r[w / 2]);
    	}
    }
    
    void encrypt(u64 plaintext[4], u64 ciphertext[4], u64 xkey[4])
    {
    	const size_t nwords = 4;
    	const size_t nrounds = 72;
    	// change it !!!
    	u8 rot[8][2] = {
    		{0, 0},
    		{5, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 6},
    		{0, 0},
    	};
    	u8 perm[4][4] = {
    		{0, 1, 2, 3},
    		{0, 3, 2, 1},
    		{0, 1, 2, 3},
    		{0, 3, 2, 1},
    	};
    
    	u64* v = new u64[nwords];
    	for (size_t w = 0; w < nwords; w++)
    	{
    		v[w] = plaintext[w];
    	}
    	for (size_t n = 0; n < nrounds; n += 8)
    	{
    		for (size_t w = 0; w < nwords; w++)
    		{
    			v[w] += xkey[w];
    		}
    		threefish_round(nwords, v, rot[(n + 0) % 8], perm[0]);
    		threefish_round(nwords, v, rot[(n + 1) % 8], perm[1]);
    		threefish_round(nwords, v, rot[(n + 2) % 8], perm[2]);
    		threefish_round(nwords, v, rot[(n + 3) % 8], perm[3]);
    
    		for (size_t w = 0; w < nwords; w++)
    		{
    			v[w] += xkey[w];
    		}
    		threefish_round(nwords, v, rot[(n + 4) % 8], perm[0]);
    		threefish_round(nwords, v, rot[(n + 5) % 8], perm[1]);
    		threefish_round(nwords, v, rot[(n + 6) % 8], perm[2]);
    		threefish_round(nwords, v, rot[(n + 7) % 8], perm[3]);
    	}
    	for (size_t w = 0; w < nwords; w++)
    	{
    		ciphertext[w] = v[w] + xkey[w];
    	}
    	delete[] v;
    }
    
    void decrypt(u64 plaintext[4], u64 ciphertext[4], u64 xkey[4])
    {
    	const size_t nwords = 4;
    	const size_t nrounds = 72;
    	// change it !!!
    	u8 rot[8][2] = {
    		{0, 0},
    		{5, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 0},
    		{0, 6},
    		{0, 0},
    	};
    	u8 perm[4][4] = {
    		{0, 1, 2, 3},
    		{0, 3, 2, 1},
    		{0, 1, 2, 3},
    		{0, 3, 2, 1},
    	};
    
    	u64* v = new u64[nwords];
    	for (size_t w = 0; w < nwords; w++)
    	{
    		v[w] = ciphertext[w] - xkey[w];
    	}
    	for (size_t n = nrounds; n > 0;)
    	{
    		n -= 8;
    
    		threefish_roundinv(nwords, v, rot[(n + 7) % 8], perm[3]);
    		threefish_roundinv(nwords, v, rot[(n + 6) % 8], perm[2]);
    		threefish_roundinv(nwords, v, rot[(n + 5) % 8], perm[1]);
    		threefish_roundinv(nwords, v, rot[(n + 4) % 8], perm[0]);
    		for (size_t w = 0; w < nwords; w++)
    		{
    			v[w] -= xkey[w];
    		}
    
    		threefish_roundinv(nwords, v, rot[(n + 3) % 8], perm[3]);
    		threefish_roundinv(nwords, v, rot[(n + 2) % 8], perm[2]);
    		threefish_roundinv(nwords, v, rot[(n + 1) % 8], perm[1]);
    		threefish_roundinv(nwords, v, rot[(n + 0) % 8], perm[0]);
    		for (size_t w = 0; w < nwords; w++)
    		{
    			v[w] -= xkey[w];
    		}
    	}
    	for (size_t w = 0; w < nwords; w++)
    	{
    		plaintext[w] = v[w];
    	}
    	delete[] v;
    }
    
    string encrypt_string_with_password(const string& s, const string& p) {
    	u64* plaintext = new u64[4];
    	u64* ciphertext = new u64[4];
    	u64* xkey = new u64[4];
    	string_to_u64_array(s, plaintext);
    	string_to_u64_array(p, xkey);
    	encrypt(plaintext, ciphertext, xkey);
    	string r = u64_array_to_string(ciphertext);
    	delete[] plaintext, ciphertext, xkey;
    	return r;
    }
    
    string decrypt_string_with_password(const string& s, const string& p) {
    	u64* plaintext = new u64[4];
    	u64* ciphertext = new u64[4];
    	u64* xkey = new u64[4];
    	string_to_u64_array(s, ciphertext);
    	string_to_u64_array(p, xkey);
    	decrypt(plaintext, ciphertext, xkey);
    	string r = u64_array_to_string(plaintext);
    	delete[] plaintext, ciphertext, xkey;
    	return r;
    }
    
    int main()
    {
    	string s = "HhaLLoioBuchstab";
    	string p = "Buchstabbb";
    	string e = encrypt_string_with_password(s, p);
    	string d = decrypt_string_with_password(e, p);
    	cout << e << endl;
    	cout << endl;
    	cout << d << endl;
    	return 0;
    }
    
    

    Jetzt dürft ihr mich wieder bannen.



  • @NutzerZwei sagte in Threefish selber implementieren:

    u64* v = new u64[nwords];
    

    Es tut so weh 😔


  • Gesperrt

    @Swordfish sagte in Threefish selber implementieren:

    Es tut so weh

    Beschwer dich beim Visual Studio/Microsoft, nicht bei mir.



  • @NutzerZwei Nimm an vector oder an smartpointer verdammte Axt!


Anmelden zum Antworten