Astasor Geschrieben 5. April 2013 Geschrieben 5. April 2013 Hallo und danke das ihr euch mein Problem anschaut. Ich versuche einen Text zu verschlüsseln, ihn in verschlüsselter Form in eine .txt Datei zu schreiben und dann wieder zu entschlüsseln. Das mit dem Ver- und Entschlüsseln klappt auch alles doch beim Schreiben in die "tmp.txt" macht der fstream Zeilenumbrüche rein, die verhindern, das beim auslesen der Datei die ganzen Daten mitgelesen werden. Ich habe schon alles probiert um die Zeilenumbrüche wegzubekommen oder trotzdem mir alle Daten zu holen. Wäre nett wenn ich hier nen Denkanstoß bekommen könnte. Aber hier erstmal der Code: #include <cstdlib> #include <iostream> #include <stdlib.h> #include <fstream> #include <string> #include <windows.h> #include <stdio.h> #include <sstream> #include <wincrypt.h> using namespace std; bool bResult,hashresult,hashdata,hashdatakey,decryptdata,encryptdata; HCRYPTPROV hProv; HCRYPTHASH phHash=0; HCRYPTKEY phKey=0; BYTE *hashdatabuf =(BYTE*)"Testpasswort1234"; DWORD dwhashdatabuflen = strlen((char*)hashdatabuf); int main(int argc, char *argv[]) { fstream tmptxt("tmp.txt",ios_base::out | ios_base::binary); string content="M_220,11.1987.,1,1,5,1,5,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,70,0,3,100,1,0,1,3,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,75,1,2,3,2,1,2,3,2,5,5,1,2,3,3"; BYTE* encrDecrData=(BYTE*)content.c_str(); cout<<encrDecrData<<endl; DWORD dlength = strlen((LPCTSTR)encrDecrData)+1; bResult = CryptAcquireContext( &hProv, // Variable to hold returned handle. NULL, // Use default key container. MS_DEF_PROV, // Use default CSP. PROV_RSA_FULL, // Type of provider to acquire. 0); // No special action. if(bResult==true){cout<<"1 geschafft"<<endl;} hashresult = CryptCreateHash( hProv, CALG_MD5, 0, 0, &phHash); if(hashresult==true){cout<<"2 geschafft"<<endl;} hashdata = CryptHashData( phHash, hashdatabuf, dwhashdatabuflen, 0); if(hashdata==true){cout<<"3 geschafft"<<endl;} hashdatakey = CryptDeriveKey( hProv, CALG_RC4, phHash, CRYPT_EXPORTABLE, &phKey); encryptdata = CryptEncrypt( phKey, 0, true, 0, encrDecrData, &dlength, 2048); cout<<encrDecrData<<endl; tmptxt<<encrDecrData; tmptxt.close(); decryptdata = CryptDecrypt( phKey, 0, true, 0, encrDecrData, &dlength); if(decryptdata==true){cout<<"4 geschafft"<<endl;} cout<<encrDecrData<<endl; system("PAUSE"); return EXIT_SUCCESS; } [/PHP] Ach ja, her die Ausgabe der tmp.txt, wenn ich sie so im ordner öffne: [code] VL¶º´«ý>ì“3,d/´Î¨7|½›,Ã?K㌅’5BI€Ã‹â€™ÃšÃ€ÃžÄhŸ•&ÃŒäOÙΤ-SSÚÄËœ-äØ!zë]Ãg’ª†ÞÈlP§™8±gÅ¡;jÉeÃú@‹zÿlŒ˜ÅÔÙ**aniÂÂ~€ÃJJty¿Âp¨(ÂlÅ [òn¬Ì}—kž ÈÓRHÃ~â„¢]`~è¤ÈW…§„PN=2a07 [/code] Öffne ich die tmp.txt aber in meiner IDE- (Bloodshed Dev C++), oder kopiere den String und füge ihn woanders ein, sieht er so aus: [code] VL¶º´«ý>ì“3,d/´Î¨7|½›,Ã?K㌅’5BI€Ã‹â€™ÃšÃ€ÃžÄhŸ•&ÃŒäOÙΤ-SSÚÄËœ-äØ!zë ]Ãg’ª†ÞÈlP§™8±gÅ¡;jÉeÃú@‹zÿlŒ˜ÅÔÙ**aniÂÂ~€ÃJJty¿Âp¨(ÂlÅ [òn¬Ì}—kž ÈÓRHÃ~â„¢]`~è¤ÈW…§„PN=2a07[/code] Wie kann ich daran etwas ändern? Vielen Dank für eure Zeit. mfg Astasor Zitieren
uenetz Geschrieben 5. April 2013 Geschrieben 5. April 2013 Und wenn Du das endl bei cout weglässt ? Zitieren
Klotzkopp Geschrieben 5. April 2013 Geschrieben 5. April 2013 Dein größter Fehler ist, dass du die bei der Verschlüsselung entstehenden Binärdaten wie Text behandelst. Es ist völlig normal, dass beim Verschlüsseln auch Bytewerte entstehen, die, als ASCII interpretiert, einen Zeilenumbruch darstellen. Es ist allerdings Unsinn, Binärdaten als ASCII zu interpretieren. Du kannst die verschlüsselte Datei nicht als Text behandeln, das kann die Daten verfälschen. Du kannst auch nicht den Inhalt mit einem Texteditor kopieren und einfügen. Ich rate dir, die Datei nicht als .txt zu speichern, damit du sie nicht aus Versehen mit einem Programm für Textdateien öffnest und damit die Daten beschädigst. Du darfst Binärdaten nicht mit << in eine Datei schreiben und nicht mit >> lesen. Benutz fstream::read und fstream::write. Ein weiterer Fehler ist hier: BYTE* encrDecrData=(BYTE*)content.c_str(); c_str gibt einen const-Zeiger zurück. Wenn du die const-Qualifizierung durch den Cast entfernst, erzeugst du undefiniertes Verhalten. encryptdata = CryptEncrypt( phKey, 0, true, 0, encrDecrData, &dlength, 2048);[/code]Hier teilst du der Funktion CryptEncrypt mit, dass der übergebene Zielpuffer 2048 Bytes groß ist. encrDecrData ist aber weder 2048 Bytes groß, noch ein geeigneter Zielpuffer, siehe oben. Zitieren
Astasor Geschrieben 6. April 2013 Autor Geschrieben 6. April 2013 (bearbeitet) Vielen Dank für eure beiden Antworten. @uenetz: Das bringt glaube ich weniger @Klotzkopp: Ich habe mir deine Vorschläge angesehen und Dinge verändert. BYTE* encrDecrData=(BYTE*)content.c_str(); habe ich durch long length=content.length(); char* buf = new char[length]; content.copy(buf,content.length()-1,0); BYTE* encrDecrData=(BYTE*)buf; ersetzet und das hier tmptxt<<encrDecrData; durch das tmptxt.write((char*)encrDecrData,strlen((LPCTSTR)encrDecrData)); Die Größe des Zielpuffers habe ich so gewählt, da ich gehört habe, das zu wenig Platz eine Fehlermeldung auslöst, aber zuviel Platz geht quasi immer fehlerlos durch und mache nie Probleme. Das Format der Dateien habe ich von .txt auf .dat geändert. Nun, was ich erreichen will ist eigentlich das, ich will Daten von einem Programm verschlüsseln lassen, diese Dateien werden dann kopiert und von einem anderen Programm wieder entschlüsselt. Die Funktion CryptDeriveKey sollte bei gleichem Passwort und gleichen verwendeten Algorithmen eigentlich auch einen identischen Schlüssel garantieren. Das Ver- und Entschlüsseln innerhalb einer Datei und wenn ich es in die Datei schreibe und hiermit wieder auslese und entschlüssel, geht ja alles fabelhaft, aber wenn ich es von einem Programm schreiben und von einem anderen lesen und entschlüsseln lasse, liest er nur bis zum ersten Zeilenumbruch. So schreibt es Programm A in die spezifische Datei: //----------------------Ergebnisse zusammenfügen-------------------------------- finalres=firstres+secondres+thirdres; finalres=(string)userannounce+","+finalres; long sizeFinalres = finalres.length(); char* bufFinalres = new char[sizeFinalres]; finalres.copy(bufFinalres,finalres.length()-1,0); byteFinalres=(BYTE*)bufFinalres; dlength = strlen((LPCTSTR)byteFinalres); // MessageBox(hwnd,finalres.c_str(),"Title",MB_OK); //zum testen //----------------------Ergebnisse verschlüsseln-------------------------------- bResult = CryptAcquireContext( &hProv, // Variable to hold returned handle. NULL, // Use default key container. MS_DEF_PROV, // Use default CSP. PROV_RSA_FULL, // Type of provider to acquire. 0); // No special action. //if(bResult==true){MessageBox(hwnd,"1 geschafft","title",MB_OK);} hashresult = CryptCreateHash( hProv, CALG_MD5, 0, 0, &phHash); //if(hashresult==true){MessageBox(hwnd,"2 geschafft","title",MB_OK);} hashdata = CryptHashData( phHash, hashdatabuf, dwhashdatabuflen, 0); //if(hashdata==true){MessageBox(hwnd,"3 geschafft","title",MB_OK);} hashdatakey = CryptDeriveKey( hProv, CALG_RC4, phHash, CRYPT_EXPORTABLE, &phKey); //if(hashdatakey==true){MessageBox(hwnd,"4 geschafft","title",MB_OK);} encryptdata = CryptEncrypt( phKey, 0, true, 0, byteFinalres, &dlength, 2048); //if(encryptdata==true){MessageBox(hwnd,"5 geschafft","title",MB_OK);} /* decryptdata = CryptDecrypt( phKey, 0, true, 0, byteFinalres, &dlength); */ //----------------------Ergebnisse in die Datei schreiben----------------------- if(true){ string filetmp="EncodedT0Answers"+(string)userannounce+".dat"; fstream a_file(filetmp.c_str(), ios_base::out | ios_base::binary); GetLocalTime(&loctime); long finalresLength=finalres.length(); char* finalresBuf = new char[finalresLength]; finalres.copy(finalresBuf,finalres.length()-1,0); a_file.write(finalresBuf,strlen(finalresBuf)); // a_file.write((char*)byteFinalres,strlen((LPCTSTR)byteFinalres));[/PHP] Problem: wenn ich das Byte Objekt in die Datei schreiben will, dann schreibt es nur bis zum ersten Zeilenumbruch, schreibe ich den String [b]finalres[/b] in die Datei, dann schreibt er alles aber Programm B liest dann nur bis zum ersten Zeilenumbruch. und so liest es Programm B aus eben jener Datei und entschlüsselt es dann wie in Post 1: [PHP] lpFileName=(LPCTSTR)".\\Encoded*.dat"; h= FindFirstFile(lpFileName,&lpFindFileData); fstream lpFile(lpFindFileData.cFileName,ios_base::in | ios_base::binary); lpFile.seekg(0,lpFile.ios_base::end); long lpFileSize = lpFile.tellg(); lpFile.seekg(0,lpFile.ios_base::beg); char* fbuf = new char[lpFileSize]; lpFile.read(fbuf,lpFileSize); BYTE* encrDecrData=(BYTE*)fbuf; DWORD dlength = strlen((LPCTSTR)encrDecrData); . .//hier findet dann die Entschlüsselung statt . FindClose(h); lpFile.close(); kurze Zusammenfassung: Ich schaffe es nicht, etwas von einem Programm verschlüsseln und dann von einem anderen wieder entschlüsseln zu lassen. Das was ein Programm geschrieben hat, kann es fehlerlos selbst wieder lesen und entschlüsseln, aber von Programm zu Programm kommt nur Gekrissel als Klartext heraus. Vielen Dank, wenn ihr bis hierhin gelesen habt. mfg Astasor Bearbeitet 6. April 2013 von Astasor Zitieren
Klotzkopp Geschrieben 6. April 2013 Geschrieben 6. April 2013 (bearbeitet) Du darfst nicht strlen benutzen, diese Funktion ist für Text. Sie zählt die Bytes bis zum ersten Nullbyte, das bei Strings eine Endmarkierung darstellt. In Binärdaten dürfen aber durchaus auch mittendrin Nullbytes auftauchen. Die Größe des Zielpuffers habe ich so gewählt, da ich gehört habe, das zu wenig Platz eine Fehlermeldung auslöst, aber zuviel Platz geht quasi immer fehlerlos durch und mache nie Probleme.Dein Puffer ist aber nicht so groß. Du musst den Puffer wirklich vergrößern, es reicht nicht, die Funktion über die Größe zu belügen. Bearbeitet 6. April 2013 von Klotzkopp Zitieren
flashpixx Geschrieben 7. April 2013 Geschrieben 7. April 2013 Die Funktion CryptDeriveKey sollte bei gleichem Passwort und gleichen verwendeten Algorithmen eigentlich auch einen identischen Schlüssel garantieren. Ich habe mir jetzt nicht im Detail die API Funktionen angeschaut, aber ich gebe zu Bedenken, dass das durchaus nicht so sein muss, denn im Normalfall ist es üblich den Schlüssel in Abhängigkeit von einem Zufallszahlengenerator zu generieren, d.h. gleiches Passwort und gleiches Algorithmus liefern nicht zwingend den gleichen Schlüssel. Es sollte Angreifern möglichst schwer gemacht werden, aus teilweise bekannten Daten die Schlüssel ggf durch Brute-Force zu rekonstruieren. Schau über die genauere Generation der Schlüssel in die Doku Deiner API, da steht letztendlich auch drin, wie dies im Detail gemacht wird. Zitieren
Astasor Geschrieben 8. April 2013 Autor Geschrieben 8. April 2013 Vielen Dank euch allen und ganz besonders dir Klotzi, ich konnte jetzt alle Probleme lösen. Danke das ihr euch alle die Zeit genommen habt, meinen Thread zu lesen und zu Antworten. Die Dateiendung habe ich auf .bin geändert. Damit wird mein Ciphertext nicht mehr verändert, so wie wenn ich ihn als Text oder in Dateien mit .dat-Endung schreiben würde. Ich habe mir die Funktion CryptEncrypt mal genau angeschaut und wenn ich sie nur mit dem Parameter der die Länge des Eingangspuffers durchlaufen lasse, dann enthält dieser dann die erforderliche Größe für den Ciphertext beim zweiten Aufruf. Krass, sage ich mal. Die Funktion CryptDeriveKey sollte mit gleichem CSP, gleichem Algorithmus und gleicher Datenbasis eigentlich dasselbe Ergebnis liefern. Hier von http://msdn.microsoft.com The CryptDeriveKey function generates cryptographic session keys derived from a base data value. This function guarantees that when the same cryptographic service provider (CSP) and algorithms are used, the keys generated from the same base data are identical. The base data can be a password or any other user data. Aber naja, die Probleme haben sich geklärt. Könnte aber noch jemand den Titel des Threads in "Verschlüsselung von Daten und deren Speicherung" ändern? Denn das mit den fstreams tangiert das behandelte Problem ja nur ein wenig. mfg Astasor Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.