Onetime-Pad-Verschlüsselung

jedi84

Grünschnabel
Hallo zusammen,

habe gerade ein Programm geschrieben, welches relativ simpel Dateien ver- und entschlüsselt. Da es mit Textdateien einwandfrei funktioniert und mit Binärdateien nicht, gehe ich davon aus, dass die Codierung byteweise erfolgt - egal ob ich bei fopen(...) rb und wb oder r und b als Parameter übergebe.

Die Codierung erfolgt mittels EXOR-Verknüpfung von Quelle und Schlüssel, wie gesagt, vermutlich byteweise.

Hier der entsprechende Code (ohne Fehlerüberprüfung):
Code:
main() {
FILE *source, *key, *out;
char a,b;
source=fopen(argv[1],"r");
key=fopen(argv[2],"r");
out=fopen(argv[3],"w");
Dann wird überprüft, ob der Schlüssel mindestens so lang ist wie die Quelldatei, funktioniert bei jeder Art von Datei...
Code:
while((a=fgetc(source)) != EOF) {
  b=fgetc(key);
  fputc(a^b,out);
}

fclose...
Das Problem: Übergebe ich beispielsweise eine GIF-Datei, ist die Output-Datei 11 Byte groß. Die while-Schleife stößt also zu meiner Verwunderung nach 11 Byte auf ein EOF.
Allerdings nicht, während überprüft wird, ob die Dateigrößen falsch sind. Da lasse ich einen Zähler mitlaufen und der zählt bis zur genauen Größe der Datei.

Edit: Um noch etwas Verwirrung zu stifen, zur Überprüfung der Dateigröße verwende ich folgenden Code:
Code:
while (a=fgetc(source) != EOF) {
  i++;
}
Dabei zählt der Counter bei Text- und Bilddateien bis zur tatsächlichen Größe.
Damit aber wenigstens die Verschlüsselung der Textdateien klappt, muss obige Schleife benutzt werden (man beachte die zusätzlichen Klammern). Lasse ich dort die Klammern ebenfalls weg, weiß ich nicht, was das Programm genau macht. Ein Text wird verschlüsselt und wenn ich das Verschlüsselte noch einmal verschlüsseln möchte, ändert sich nichts mehr.
Beispiel:
Klartext: ABCDE
verschlüsselt: !"§$%&
nochmal verschlüsselt: !"§$%&
Mit den Klammern führt eine nochmalige Verschlüsselung wieder zum Klartext (was bei EXOR auch logisch wäre).

Wenn jemand helfen kann: DANKE!
 
Zuletzt bearbeitet:
Wenn du Binärdateien auch so einließt:
EOF kann hier nicht als Dateiende genommen werden!
Nachdem du die Datei aufgemacht hast, könntest du mit filelength die Größe bestimmen.
Wenn die geöffnete FILE*-Variable jetzt source heißt:
int laenge=filelength(fileno(source));
Im laenge hast du jetzt die Byteanzahl, wie groß die Datei ist.
Das kannst du dann in einer for-Schleife etc durchgehen, ohne das EOF zu überprüfen.
Dass ist nämlich leider nicht ganz zuverlässig manchmal...
Wenn du Dateien im Gigabytebereich hast, musst du die 64bit-Variante von der Funktion anwenden, sag wenn du das brauchst

gruß
 
Danke für die schnelle Antwort.
In den Gigabyte-Bereich werde ich nicht kommen, allerdings kennt mein Compiler (gcc) die Funktion filelength() nicht.

Woanders habe ich jetzt folgende Funktion gefunden:
Code:
static long filelength(FILE *f)
{
	long buf, size;
	buf = ftell(f);
	if(buf < 0)
		return buf;
	size = fseek(f, 0, SEEK_END);
	if(size < 0)
		return size;
	size = ftell(f);
	if(size < 0)
		return size;
	fseek(f, buf, SEEK_SET);
	return size;
}
Funktioniert auch, natürlich beim Aufruf mit filelength(source) statt filelength(fileno(source)).
 
A ja hab ich vergessen :)
die funktion inst im <io.h>
einfach includieren!

die funktion die du da hast, ist schon in Ordnung, aber die fertige ist schneller,

ist ja auch egal, nimm was du brauchst

gruß
 
Zurück