Home > Software design >  XOR only partially decrypts file
XOR only partially decrypts file

Time:10-14

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.

  •  Tags:  
  • c xor
  • Related