C++ AES Problem ( oder eher Pointer oder so)



  • Hallo Ihr,

    Ich arbeite gerade an einer Verschlüsselung und Entschlüsselung von einem serial und das will ich mit AES machen.

    Folgenden Code habe ich:

    char *EncryptAES(char *key, char *szDataIn)
    {
    	char szDataOut[17] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
    
    	CRijndael oRijndael;
    	oRijndael.MakeKey(key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 16);
    	oRijndael.EncryptBlock(szDataIn, szDataOut);
    
    	return szDataOut;
    }
    
    char *GenerateSerial(char *serial)
    {
    	char aesKey[7] = "Key123";
    
    	char *encryptedAES = EncryptAES(aesKey, c4dsn);
    	cout << "EncAES " << encryptedAES << "\n";
    
    	return encryptedAES;
    }
    
    char *DecryptAES(char *key, char *szDataIn)
    {
    	char *szDataOut= new char[17];
    
    	CRijndael oRijndael;
    	oRijndael.MakeKey(key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 16);
    	oRijndael.DecryptBlock(szDataIn, szDataOut);
    
    	return szDataOut;
    }
    
    bool CheckSerial(char *serial)
    {
    	char aesKey[7] = "Key123";
    
    	cout << "EncAES " << serial << endl;
    
    	char *decryptedAES = DecryptAES(aesKey, serial);
    	cout << "DecAES " << decryptedAES << "\n";
    
    	return true;
    }
    
    int main(int argc, char *argv[])
    {
    	char serial[12] = "457362325";
    
    	Key privateKey = Key(BigInt(MODULUS), BigInt(PRIVATE));
    
    	char *result = GenerateSerial(serial, privateKey);
    
    	Key publicKey = Key(BigInt(MODULUS), BigInt(PUBLIC));
    	CheckSerial(serial, result, publicKey);
    
    	cin.sync();
    	cin.get();
    }
    

    Problem ist, das hier wohl einige Pointerprobleme habe. Da die ausgabe zwischen Debug und Release unterschiedlich ist.

    Zum Beispiel ist die Ausgabe bei
    CheckSerial EncAES unterschiedlich zu EncAES in GenerateSerial

    Ich weiß leider nicht mehr weiter und ich sitze schon Stunden daran.



  • Das sieht alles überhaupt nicht so aus als könntest du C++ auch nur in den Grundlagen*, sicher, dass du etwas machen willst, was Verschlüsselung erfordert? Ich hoffe das wird nirgends eingesetzt..
    Wie auch immer, dein (größtes) Problem hier ist, dass du in Zeile 9 des ersten Codeausschnitts einen Pointer auf Speicher zurückgibst, der gleich freigegeben wird. Das Array liegt doch nur auf dem Stack, und es existiert nur innerhalb des Funktionsscopes. Sowas gehört halt wirklich zu den absoluten Grundlagen. Du kannst hier z.B. einfach auf std::vector (Speicher auf dem Heap) oder std::array (Speicher auf dem Stack) umsteigen, je nach dem, was dir lieber ist. Dann bekommst du auch garantiert keine Speicherleaks, die hast du da oben nämlich auch.

    * Immerhin ist die Frage halbwegs sauber gestellt, das gibt etwas Hoffnung. 🙂

    PS: Wenn du Compilerwarnungen lesen würdest, wäre dir das bestimmt sofort aufgefallen. Immer schön mit -Wall kompilieren und alles lesen.



  • Benutze std::string statt char* und char-Arrays.



  • Vielen Dank für eure Antworten, ich habe es versucht umzusetzen.

    Wie findet ihr das Resultat (funktioniert nun übrigens).
    Würdet ihr hier noch etwas verändern?

    void EncryptAES(const char key[], const char szDataIn[], char *szDataOut)
    {
    	CRijndael oRijndael;
    	oRijndael.MakeKey(key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 16);
    	oRijndael.EncryptBlock(szDataIn, szDataOut);
    }
    
    string GenerateSerial(char *serial)
    {
    	const char *aesKey = "Key1234";
    
    	char encryptedAES[17] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
    	EncryptAES(aesKey, serial, encryptedAES);
    	cout << "EncAES " << encryptedAES << "\n"; 
    	return encryptedAES;
    }
    
    void DecryptAES(const char key[], const char szDataIn[], char *szDataOut)
    {
    	memset(szDataOut, 0, 16);
    
    	cout << key << " ++++ " << szDataIn << " +++ " << "\n";
    
    	CRijndael oRijndael;
    	oRijndael.MakeKey(key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 16);
    	oRijndael.DecryptBlock(szDataIn, szDataOut);
    
    	cout << szDataOut << endl;
    }
    
    bool CheckSerial(string serial)
    {
    	const char *aesKey = "Key1234";
    
    	cout << "EncAES " << serial << endl;
    
    	char *decryptedAES = new char[17];
    
    	DecryptAES(aesKey, serial.c_str(), decryptedAES);
    	cout << "DecAES " << decryptedAES << "\n";
    
    	return true;
    }
    

    Ist es legitim, dass ich über einen return value vom Type string einen char* zurück gebe?

    Was ich nicht ganz verstehe ist:

    Funktioniert:

    const char *aesKey = "Key1234";
    

    Funktioniert nicht

    const char aesKey[7] = "Key1234";
    


  • manni66 schrieb:

    Benutze std::string statt char* und char-Arrays.

    nt2005 schrieb:

    Vielen Dank für eure Antworten, ich habe es versucht umzusetzen.

    const char key[], const char szDataIn[], char *szDataOut [..] char *serial [..] const char *aesKey  [..] char encryptedAES[17]  [..] const char key[], const char szDataIn[], char *szDataOut [..] const char *aesKey [..] char *decryptedAES = new char[17]
    


  • Hallo Sone,

    Und das funktionert wieder nicht. 😞

    string DecryptAES(string aesKey, string dataIn)
    {
    	char key[7];
    	char *szDataIn = new char[dataIn.size()+1];
    	char szDataOut[17] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
    
    	strcpy((char*) key, aesKey.c_str());
    	strcpy((char*) szDataIn, dataIn.c_str());
    
    	CRijndael oRijndael;
    	oRijndael.MakeKey(key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 16);
    	oRijndael.DecryptBlock(szDataIn, szDataOut);
    
    	return szDataOut;
    }
    
    bool CheckSerial(string serial)
    {
    	string aesKey = "Key1234";
    
    	cout << "EncAES " << serial << endl;
    
    	string decryptedAES = DecryptAES(aesKey, serial);
    	cout << "DecAES " << decryptedAES << "\n";
    
    	return true;
    }
    
    string EncryptAES(string aesKey, string dataIn)
    {
    
    	char key[7];
    	char *szDataIn = new char[dataIn.size()+1];
    	char szDataOut[17] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
    
    	strcpy((char*) key, aesKey.c_str());
    	strcpy((char*) szDataIn, dataIn.c_str());
    
            cout << key << " -- " << szDataIn << endl;
    
    	CRijndael oRijndael;
    	oRijndael.MakeKey(key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 16);
    	oRijndael.EncryptBlock(szDataIn, szDataOut);
    
    	return szDataOut;
    }
    
    string GenerateSerial(string serial)
    {
    	string aesKey = "Key1234";
    
    	string encryptedAES = EncryptAES(aesKey, serial);
    	cout << "EncAES " << encryptedAES << "\n"; 
    
    	return encryptedAES;
    }
    

    Also bis zu CheckSerial scheint alles ordentlich zu laufen. Nur dann die konvertierung zu den chars (ist notwengig wegen Rijndael funktion) scheint es zu holpen. Obwohl die Ausgabe an der Stelle vor der Entschlüsselung identisch ist, was eigentlich sein müsste.

    void MakeKey(char const* key, char const* chain, int keylength=DEFAULT_BLOCK_SIZE, int blockSize=DEFAULT_BLOCK_SIZE);
    
    void EncryptBlock(char const* in, char* result);
    


  • cooky hat das schon gut gesagt:

    cooky451 schrieb:

    Das sieht alles überhaupt nicht so aus als könntest du C++ auch nur in den Grundlagen sicher



  • Das hilft mir leider auch nicht wirklich weiter, Sone. Komme aus Java und da hat mein bekanntermaßen weniger damit am Hut.

    Was ist denn die Grundlage die mir fehlt?

    Ich sehe, das eine Funktion einen char* braucht, was ich besitze ist ein string.
    Was mache ich nur Falsch in der beziehung?

    Neuer Versuch: (funktioniert leider auch nicht)

    string EncryptAES(string aesKey, string dataIn)
    {
    	char szDataOut[17] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
    
    	CRijndael oRijndael;
    	oRijndael.MakeKey(aesKey.c_str(), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 16);
    	oRijndael.EncryptBlock(dataIn.c_str(), szDataOut);
    
    	return szDataOut;
    }
    string GenerateSerial(string serial)
    {
    	string aesKey = "Key1234";
    
    	string encryptedAES = EncryptAES(aesKey, serial);
    	cout << "EncAES " << encryptedAES << "\n"; 
    }
    
    string DecryptAES(string aesKey, string dataIn)
    {
    	char szDataOut[17];
    
    	CRijndael oRijndael;
    	oRijndael.MakeKey(aesKey.c_str(), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 16);
    	oRijndael.DecryptBlock(dataIn.c_str(), szDataOut);
    
    	return szDataOut;
    }
    
    bool CheckSerial(string serial)
    {
    	string aesKey = "Key1234";
    
    	cout << "EncAES " << serial << endl;
    
    	string decryptedAES = DecryptAES(aesKey, serial);
    	cout << "DecAES " << decryptedAES << "\n";
    
    	return true;
    }
    

    Edit: Es funktioniert, aber nur im Debug mode?!?



  • Fehler gefunden.
    Scheinbar muss der Key größer sein als ein bestimmter Wert. Nun funktioniert es.

    Oder wäre hier noch Handlungsbedarf?



  • Handlungsbedarf herrscht immer

    Zum Beispiel das hier:

    string EncryptAES(string aesKey, string dataIn)
    

    Da wird jedesmal der aesKey kopiert. Das ist unnötig. Daher übergibt man strings im allgemeinen als const-reference:

    string EncryptAES(const string& aesKey, const string& dataIn)
    


  • nt2005 schrieb:

    Komme aus Java und da hat mein bekanntermaßen weniger damit am Hut.

    Von Java scheinst du auch nicht sooo viel Ahnung zu haben, sonst wärst du doch wohl zumindest mal auf die Idee gekommen, dir eine Klasse Serial zu bauen? 😉
    Aber mal so nebenbei: Einfach überall std::string/std::vector nutzen. .c_str()/.data() geben dir direkte Zeiger auf die internen Daten, falls du das brauchst. Ansonsten für Elementzugriff einfach wie gewohnt [] nutzen. Und alle Typen wie value-Types behandeln. Pointer brauchst du gar nicht.

    Erstmal ein paar einfache Regeln die die helfen sollten, das zum laufen zu bekommen. Solange Performance unwichtig ist, brauchst du dich mit Pointern/Referenzen gar nicht zu beschäftigen. Wenn du C++ lernen willst, solltest du dir allerdings ein Buch kaufen. Primer wird hier oft empfohlen für Anfänger, auch wenn ich C++ eher von C aus lernen würde, aber das ist Geschmackssache. Da du Java ja schon "kannst", sollte dir der Einstieg über den Primer leicht fallen.

    PS: Diese CRijndael wirkt irgendwie genau so.. ungeschickt wie dein Code; woher hast du die?



  • Vielen Dank! Diesen Fehler hatte ich an vielen Stellen meines Programmes.



  • ... und die Verwendung von Ungarischer Notation, insbesondere zur technischen, statt, wie ursprünglich gedacht, fachlichen Bezeichnung, ist sowas von 80'er


Log in to reply