[CHANGE]fehler in xor verschlüsselung... 3 buffer io 2 buffer nio...
-
Hey @ll.
Ich habe ein Programm geschrieben was eine Datei sicher löscht,
nun wollte ich in dem Zuge weiter mit Dateien arbeiten und ein Programm schreiben, was Dateien verschlüsselt.Die Art der Dateien sollte egal sein, ich teste momentan jedoch nur mit *.txt Dateien.
Es sieht so aus:
meine org.txt hat 442KB und 452.990 Zeichen.
meine new.txt hat 443KB und 453.906 Zeichen.Die new.txt entsteht, wenn ich den Algorithmuss deaktiviere, und dann die org.txt Datei verschlüssele.
Dass sie größer ist liegt an der Abbruchbedingung dess Schreibvorgangs... (bekomm ihc noch hin).Jetzt aktiviere ich denn Verschlüsselungs-Algorithmus:
buf[i] = buf[i] ^ key[j];
buf ist ein Pointer mit malloc( 1034 * sizeof(char) ); (10 sind überflüssig, aber schutzhalber da), und key ist ein Pointer worin der eingegebene Schlüssel steht, um die Datei zu Ver- und Entschlüsseln.
Mit Algorithmuss (diese eine Zeile) sieht es so aus:
org.txt hat 442KB und 452.990 Zeichen
new.txt hat 395KB und 401.621 Zeichen
Differenz: 51.821 ZeichenSo kann dass ja nicht gut gehen...
Ich habe wirklich nur diese Zeile einmal auskommentiert (unverschlüsselt quasi) und dann wieder in gebauch genommen.meine Funktion lautet:
int encryptingText( FILE *source, char *key, int destination ) { char *buf; buf = malloc( sizeof(char) * 1034 ); int i = 0, j = 0, zahl = 0, cryptedChar = 0, durchgaenge = 0; //Solange Datei nicht zu Ende ist. while( !feof( source ) ) { durchgaenge++; fread( buf, sizeof(char), 1024, source ); i = 0; j = 0; //solange kein \0 auftritt und i kleiner als 100 ist while( '\0' != buf[i] && 1024 > i ) { //Wenn das Ende der Datei nicht erreicht wurde if( EOF != buf[i] ) { cryptedChar++; //Verschlüsseln buf[i] = buf[i] ^ key[j]; if( strlen( key )-1 == j ) j = -1; i++; j++; } else { if( 1024 > i+1 ) { buf[i+1] = '\0'; i++; } } } buf[i+1] = '\0'; //In Datei schreiben zahl += write( destination, buf, i ); if( 1024 > i ) printf( "\n%d:\t\t%d", durchgaenge, i ); } free( buf ); return zahl; }
-
Wenn ich raten müsste, würde ich auf einen Konflikt zwischen Text- und Binärmodus tippen (im Textmodus wird der Zeilenumbruch \n in einen systemspezifischen Umbruch (unter Windows \r\n - 2 Zeichen) umgewandelt).
Zur Diagnose solltest du mal den Wert von zahl am Ende der Funktion ausgeben lassen und in beiden Fällen mit den Dateigrößen vergleichen (und nur testweise mitzählen, wieviele \n du unterwegs gelesen/geschrieben hast).
-
Die Datei hat 51.371 Zeilen, also 51.370 "\n"s
Unverschlüsselt hat zahl den Wert 402.432
Verschlüsselt hat zahl den Wert 401.628War dass das was du wissen wolltest?
-
Wie hast du deine Datei(en) eigentlich geöffnet?
(btw, hat es einen Grund, daß du die Eingabedatei als FILE* übergibst, die Ausgabedatei aber als Unix File Deskriptor (int)?)
-
source = fopen( argv[1], "r+w" ); [...] datei = creat( "cryptedFile.cf", 0777 );
Ich weiß nicht, ob es einen speziellen grund hatte, dass ich create genommen habe, aber dass ist ja auch kein unterschied zu fopen mit dem create parameter oder?
[edit]die Lösung ist
if( '\n' != buf[i] ) buf[i] = buf[i] ^ key[j];
dann ist lediglich 1 zeichen zu viel vorhanden, dass bekomm ichauch noch hin...
Danke[/edit]
-
Den Modus "r+w" kannte ich noch nicht - dort sollte doch eher "r+b" stehen, oder (eventuell reicht sogar "rb"? Und anstelle von creat() kannst du auch fopen() verwenden mit dem Modus "wb" (allerdings bin ich nicht sicher, wie fopen() die Zugriffsrechte vorbelegt).
Edit: Laut Man-Page setzt man: fopen die Zugriffsrechte auf 0666 (kann mittels umask() angepasst werden) - aber ausführen willst du das verschlüsselte File sowieso nicht, oder?
-
Das File kann behandelt werden wie jedes andere auch, dass stört mich nicht.
Mit create klappt es ja auch, wieso sollte ich es umschreiben, hat dass einen Grund?
Dass r+w lass ich so, da ich -wenn alles klappt- es so umschreibe dass direkt die Datei überschrieben wird, und ich sie nicht erst noch löschen muss.
Ich werde mich jetzt mal an dass Entschlüsseln setzen -wo ich schon Fehler habe- und nochmal alles prüfen,
du könntest mir ja gerne nochmal den unterschied zwischen fopen und create erklären...
-
"r+w" ist aber Käse - du kannst nur eine der Kennungen "r", "w" oder "a" beim Modus angeben. (und die Angabe "r+" reicht schon aus, um die Datei zum Lesen UND Schreiben zu öffnen)
("b" kannst du zusätzlich angeben und setzt damit die Datei in den Binärmodus - das bewirkt im wesentlichen, daß die Dateifunktionen nicht mehr zwischen \n und \r\n konvertieren)
lippoliv schrieb:
du könntest mir ja gerne nochmal den unterschied zwischen fopen und create erklären...
fopen() ist eine Funktion des Ansi-Standards, create() ist eine systemspezifische Funktion (und afaik nur auf Unix-Derivaten verfügbar).
-
CStoll schrieb:
[...]und afaik nur[...]
Was ist afaik?
Ok dann nutze ich r+.
Müsste ich etwas unschreiben wenn ich r+b nutze?
Ich habe ein Problem:
if( '\n' != buf[i] ) buf[i] = buf[i] ^ key[j]; else j--;
Wenn ich dass else auskommentiere sind es weniger Zeichen als wenn es in benutzung ist, wass ich echt überhaupt nicht nachvollziehen kann.
Das j-- sorgt lediglich dafür, dass wenn beim überspringen eines \n im nächsten durchgang (beim nächsten buchstaben) der gleiche buchstabe aus dem key zum Verschlüsseln genutzt wird, wie der der eigentlich hätte bei dem \n kommen sollen.
[edit]Dass liegt übrigens daran, dass wenn am ende der Datei eine Leerzeile ist, ein fehler auftritt... ich weißnoch nicht wie ich das fixen kann.[/edit]
-
lippoliv schrieb:
CStoll schrieb:
[...]und afaik nur[...]
Was ist afaik?
"as far as I know" = soweit ich weiß
Ok dann nutze ich r+.
Müsste ich etwas unschreiben wenn ich r+b nutze?
Ja, du kannst deine Sonderbehandlung für \n wieder rauswerfen.
[/quote]Ich habe ein Problem:
if( '\n' != buf[i] ) buf[i] = buf[i] ^ key[j]; else j--;
Wenn ich dass else auskommentiere sind es weniger Zeichen als wenn es in benutzung ist, wass ich echt überhaupt nicht nachvollziehen kann.
[/quote]Das kann ich auf die Schnelle auch nicht nachvollziehen. Hast du mal im Debugger verfolgt, was genau da passiert?
-
Dazu müsstest du mir sagen wie ich das machen kann:
Editor Notepad++
Compiler MinGWIch habe jetza uf "r+b" umgestellt, und wenn ich dann das verschlüsseln auskommentiere werden bei \n immer noch 1 leerzeile hinzugefügt...
Wieso?
Des weiteren ist die Textdatei jetzt wieder größer:
org.txt
+186 KB
+21.671 Zeilen
+191.090 Zeichennew.txt
+189 KB
+6.551 Zeilen
+194.168 ZeichenWieso weicht dass bei den Zeichen so sehr ab?
-
Hast du auch die Ausgabedatei im Binärmodus geöffnet? (wenn ich die Manpage von create() betrachte, verwendet das Textmodus, also solltest du mindestens auf open() ausweichen (ich sehe gerade, open() hat kein Flag, um die Datei im Binärmodus zu setzen, also bleibt nur
out=fopen(name,"wb");
)PS: Auf was für einem Betriebssystem entwickelst du eigentlich?
-
Ob man Windows Vista betriebssystem nennen kann... Ja eigentlich schon.
Also ich habe umgestellt:
int encryptingText( FILE *source, char *key, FILE *destination ) { char *buf; buf = malloc( sizeof(char) * 1034 ); int textPos = 0, keyPos = 0, zahl = 0, cryptedChar = 0, end = 0; //Solange Datei nicht zu Ende ist. while( !feof( source ) && 0 == end ) { memset( buf, '\0', 1024 ); fread( buf, sizeof(char), 1024, source ); textPos = 0; keyPos = 0; //solange kein \0 auftritt und textPos kleiner als 100 ist while( '\0' != buf[textPos] && 1024 > textPos && 0 == end ) { //Wenn das Ende der Datei nicht erreicht wurde if( EOF != buf[textPos] ) { cryptedChar++; //Verschlüsseln buf[textPos] = buf[textPos] ^ key[keyPos]; if( strlen( key )-1 == keyPos ) keyPos = -1; textPos++; keyPos++; } else end = 1; } //In Datei schreiben zahl += fwrite( buf, sizeof(char), textPos-1, destination ); } free( buf ); return zahl; }
Abweichungen:
new.txt ist 187 Byte kleiner, das finde ich aber noch, nach dem Entschlüsseln.Ich lasse mal eben cryptedChar ausgeben:
es wird quasi die größe der org.txt angezeigt, also durchläuft er alle Zeichen einmal, lässt aber einige fallen !?
Fehler gefunden... "zahl += fwrite( buf, sizeof(char), textPos-1, destination );" muss "zahl += fwrite( buf, sizeof(char), textPos, destination );" sein.Jetzt gehts ans decrypten...
-
Er hängt einfach ans ende der Entschlüsselten Datei -die echt entschlüsselt wird- so ca 100 mal das Codewort ran...
sizeof( org.txt ) = 191.088 Bytes sizeof( new.txt ) = 191.088 Bytes sizeof( saveFile.crypt ) = 191.488 Bytes << entschlüsselte Datei lastRowOf( org.txt ) = "Hallo 0" lastRowOf( new.txt ) = "RVac>IFhxBA][He$ O]d|-" lastRowOf( saveFile.crypt ) = "Hallo 0oliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliveroliv"
Wieso steht da das Codewort?
#define READSIZE 1024 [...] int decryptingText( FILE *file, char *key, FILE *dest ) //Diese Funktion verschlüsselt die Datei auf die file zeigt. key wird als verschlüsselungs-Hilfe genommen. //Vorerst wird der so enstehende Text in dest gespreicher. //Returnwert: Die anzahl der geschriebenen Bytes { char *buf; buf = malloc( sizeof(char) * ( READSIZE + 10 ) ); int textPos = 0, keyPos = 0, zahl = 0, encryptedChar = 0, end = 0; while( !feof( file ) && 0 == end ) { memset( buf, '\0', READSIZE ); fread( buf, sizeof(char), READSIZE, file ); textPos = 0; keyPos = 0; //Es wird solange entschlüsselt, bis das Stringende erreicht ist, oder die maximal zu lesende anzahl an chars erreicht ist, oder aber das Ende der Datei erreicht wird. while( '\0' != buf[textPos-1] && READSIZE > textPos && 0 == end ) { //Bei EOF wird aufgehört zu entschlüsseln if( EOF != buf[textPos] ) { encryptedChar++; //Verschlüsseln buf[textPos] = buf[textPos] ^ key[keyPos]; if( strlen( key )-1 == keyPos ) keyPos = -1; textPos++; keyPos++; } else end = 1; } zahl += fwrite( buf, sizeof(char), textPos, dest ); } free( buf ); return zahl; }
-
kann es sein, dass ich im grunde ein und die Selbe Funktion nutzen kann?
-
Ja, du kannst (und solltest) nur eine De/Encrypt-Funktion benutzen, denn (ab)b = a.
P.S: Du kannst dein Verfahren noch optimieren, indem du strlen( key ) nur einmalig vor der Schleife berechnest.
-
Th schrieb:
P.S: Du kannst dein Verfahren noch optimieren, indem du strlen( key ) nur einmalig vor der Schleife berechnest.
Dass würde nichts bringen da ich es ja nur einmal benutze, dass andere mal ist es strlen( buf ).
Ich bentutze jetzt nur eine funktion und nie wird die ganze Datei verschlüsselt:
so wies aussieht werden immer nur 1024 verschlüsselt...
Beim entschlüsseln macht er die wieder gerade, und bei den nächsten quasi auch, aber da er beim entschlüsseln ist, verschlüsselt er die...Wieso?:
int cryptingText( FILE *file, char *key ) //Diese Funktion ver- und entschlüsselt die Datei auf die file zeigt. key wird als verschlüsselungs-Hilfe genommen. //Returnwert: Die anzahl der geschriebenen Bytes { char *buf; buf = malloc( sizeof(char) * ( READSIZE + 10 ) ); int textPos = 0, keyPos = 0, zahl = 0, cryptedChar = 0, end = 0; long endOfFile = 0; fseek( file, 0, 2 ); endOfFile = ftell( file ); fseek( file, 0, 0 ); while( ftell( file ) < endOfFile && 0 == end ) { memset( buf, '\0', READSIZE ); fread( buf, sizeof(char), READSIZE, file ); textPos = 0; keyPos = 0; //Es wird solange verschlüsselt, bis das Stringende erreicht ist, oder die maximal zu lesende anzahl an chars erreicht ist, oder aber das Ende der Datei erreicht wird. while( '\0' != buf[textPos] && READSIZE > textPos && 0 == end ) { //Dass EOF wird nicht verschlüsselt, da beim entschlüsseln an dieser Stelle aufgehört werden muss. if( EOF != buf[textPos] ) { cryptedChar++; //Verschlüsseln buf[textPos] = buf[textPos] ^ key[keyPos]; if( strlen( key )-1 == keyPos ) keyPos = -1; textPos++; keyPos++; } else end = 1; } if( strlen( buf ) < READSIZE ) end = 1; fseek( file, zahl, 0 ); zahl += fwrite( buf, sizeof(char), textPos, file ); } free( buf ); return zahl; }
Versteh ich nich, wieso bleibt er nach dem ersten buffer stehen?
-
Das mit dem angehängten Schlüsselwort liegt wohl daran, daß fread() die gelesenen Daten nicht mit \0 abschließt. D.h. wenn du im letzten Schleifendurchlauf nur einen halb vollen Datenblock verschlüsselst, nimmst du den Inhalt der vorigen Ausgabe mit.
(btw, die verschlüsselten Dateien dürften keine erkennbare Zeilenstruktur haben, schließlich werden NewLines wie jedes andere Zeichen mit verschlüsselt)
-
#define cTF_CANT_READ_ALL -1 [...] int cryptingTextFile( FILE *file, char *key, int *failure ) //Diese Funktion ver- und entschlüsselt die Datei auf die file zeigt. key wird als verschlüsselungs-Hilfe genommen. //Returnwert: Die anzahl der geschriebenen Bytes { char *buf; buf = malloc( sizeof(char) * ( READSIZE + 10 ) ); int textPos = 0, keyPos = 0, zahl = 0, cryptedChar = 0, end = 0; long endOfFile = 0; fseek( file, 0, SEEK_END ); endOfFile = ftell( file ); fseek( file, 0, SEEK_SET ); while( ftell( file ) < endOfFile && 0 == end ) { memset( buf, '\0', READSIZE ); fread( buf, sizeof(char), READSIZE, file ); textPos = 0; keyPos = 0; //Es wird solange verschlüsselt, bis das Stringende erreicht ist, oder die maximal zu lesende anzahl an chars erreicht ist, oder aber das Ende der Datei erreicht wird. while( READSIZE > textPos && 0 == end && '\0' != buf[textPos] ) { //Dass EOF wird nicht verschlüsselt, da beim entschlüsseln an dieser Stelle aufgehört werden muss. if( EOF != buf[textPos] ) { if( '\0' == buf[textPos] ) ; else { cryptedChar++; //Verschlüsseln buf[textPos] = buf[textPos] ^ key[keyPos]; if( strlen( key )-1 == keyPos ) keyPos = -1; textPos++; keyPos++; } } else end = 1; } if( textPos < READSIZE && ftell( file ) < endOfFile ) { end = 1; *failure = cTF_CANT_READ_ALL; } fseek( file, zahl, SEEK_SET ); zahl += fwrite( buf, sizeof(char), textPos, file ); } free( buf ); return zahl; }
So also: Er verschlüsselt wunderbar, allerdings beim entschlüsseln, da bleibt es manchmal hängen, er entschlüsselt manche buchstaben nicht, lässt diese liegen...
Habe ich da irgendwo einen Logikfehler drinne?
Er macht dass ding immer voll (1024) schreibt also am Ende nicht das codewort, aber leerzeichen oder so... sehr komisch...
-
lippoliv schrieb:
Th schrieb:
P.S: Du kannst dein Verfahren noch optimieren, indem du strlen( key ) nur einmalig vor der Schleife berechnest.Dass würde nichts bringen da ich es ja nur einmal benutze, dass andere mal ist es strlen( buf ).
Du rufst es aber in jedem Schleifendurchgang auf und da der Key konstant ist, reicht es doch, wenn du die Länge einmalig berechnest und dann nur noch die Variable abfragst (und nicht jedesmal die Länge des Keys wieder und wieder zu berechnen - auch wenn der Key sicherlich nicht so groß ist -)
Aber du hast ja eher andere Probleme... benutze doch einfach den Debugger und steppe Schritt für Schritt durch dein Programm, dann sollten dir die Fehler auffallen -)