I'm learning C, and it's going slowly because I'm teaching myself. I'm trying to create a small function that reads a file, XOR encrypts it byte by byte, and spits it back out. It seems to work for encryption, but when I decrypt only half of it is legible, the rest is gibberish.
int encrypt_file(void)
{
//declare variables used
FILE *src_file_ptr;
FILE *dst_file_ptr;
char infilename[96];
char key[50];
char outfilename[96];
char temp_store[50];
int plen;
printf("Please enter the name of the file to encrypt: ");
scanf("%s", infilename);
printf("Please enter the name of the output file: ");
scanf("%s", outfilename);
printf("Please enter the key to encrypt the file: ");
scanf("%s", key);
plen = strlen(key);
//test for existence of input file
src_file_ptr = fopen(infilename, "r");
if (src_file_ptr == NULL)
{
printf("File does not exist!");
return 1;
}
dst_file_ptr = fopen(outfilename, "a");
//read and process file 50 bytes at a time
while(fgets(temp_store, 50, src_file_ptr) != NULL)
{
int i;
//XOR n bytes with key
for ( i = 0; i < strlen(temp_store); i )
{
temp_store[i] = temp_store[i] ^ key[i%plen];
fprintf(dst_file_ptr,"%c",temp_store[i]);
}
}
fclose(dst_file_ptr);
fclose(src_file_ptr);
return 0;
}
int main(void)
{
encrypt_file();
return 0;
}
I've researched extensively here on stack overflow, and everything I've found is for XOR encrypting / decrypting set value strings. I'm trying to get it to work dynamically by reading in a file and asking for a password (key) from the user. Any help would be greatly appreciated.
CodePudding user response:
Use "w"
flag for writing, instead "a"
to append. Open the files in binary mode if this is running on Window.
Use fread
and fwrite
instead of fgets
and fprintf
. This will read in binary and informs how many bytes were read, you can write back the exact number of encrypted bytes. You may want to rewrite your code so you don't have to enter input names each time you test the code.
int encrypt_file(const char *key, char *infilename, char *outfilename)
{
FILE* src_file_ptr = fopen(infilename, "rb");
if (!src_file_ptr) { perror(infilename); return 1; }
FILE* dst_file_ptr = fopen(outfilename, "wb");
char temp_store[50];
int plen = strlen(key);
while (1)
{
size_t count = fread(temp_store, 1, sizeof(temp_store), src_file_ptr);
if (!count)
break;
for (size_t i = 0; i < count; i )
temp_store[i] = temp_store[i] ^ key[i % plen];
fwrite(temp_store, 1, count, dst_file_ptr);
}
fclose(dst_file_ptr);
fclose(src_file_ptr);
return 0;
}
int main(void)
{
encrypt_file("key", "test.txt", "test.bin");
encrypt_file("key", "test.bin", "test2.txt");
return 0;
}
CodePudding user response:
So after much more painful head against the wall, and help from folks here I found the solution.
int encrypt_file(void)
{
//declare variables used
FILE *src_file_ptr;
FILE *dst_file_ptr;
char infilename[96];
char key[50];
char outfilename[96];
char temp_store[50];
int plen;
printf("Please enter the name of the input file: ");
scanf("%s", infilename);
printf("Please enter the name of the output file: ");
scanf("%s", outfilename);
printf("Please enter the key to perform encrypt / decrypt: ");
scanf("%s", key);
plen = strlen(key);
//test for existence of input file
src_file_ptr = fopen(infilename, "rb");
if (src_file_ptr == NULL)
{
printf("File does not exist!");
return 1;
}
dst_file_ptr = fopen(outfilename, "wb");
//create and initialize iterator
int i = 0;
do
{
//variable for new byte
char nb;
// check for end of file and exit if found
if (feof(src_file_ptr))
break;
//check where iterator is at. If same length as password, reset it.
if (i == plen)
{
i = 0;}
//read single character from file, in binary mode
char c = fgetc(src_file_ptr);
// combine file character with password character using XOR
nb = c ^ key[i];
//write new character to file as byte
fputc(nb, dst_file_ptr);
//increment to next letter in password
i ;
} while(1);
fclose(dst_file_ptr);
fclose(src_file_ptr);
return 0;
}
int main(void)
{
encrypt_file();
return 0;
}
This works perfectly for text files, haven't tried binaries yet but all I needed was for plaintext so far.