Search code examples
cfgetsfread

Xor encryptor new line issue


I have created a simple program that gets an existing file as input (text content) encrypts its content and the outputs the encrypted content to a file with filename specified by the user (argv[2]). The problem is that whenever fgets tries to read a new line character it terminates. So i would like to use fread instead to solve this issue but then another problem came over. it doesn't stops at the ned of the string (\0). So how can implement fread to terminate at the end of the string? the source code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define Xor_key 0xCF

void xorInput(char *in, char *o) {
  FILE *fp;
  FILE *fp2;
  fp = fopen(in, "rb");
  if (fp==NULL) {
    printf("file isn't here...\n");
    exit(1);
  }
  char buf[1000];
  fgets(buf, sizeof(buf), fp);
  printf("file contents: %s\n", buf);
  int i;
  for (i=0; buf[i] != '\0'; ++i) {
    buf[i] ^= Xor_key;
  }
  printf("Encrypted input: %s\n", buf);
  fclose(fp);
  fp2 = fopen(o,"w");
  fprintf(fp2, "%s", buf);
  fclose(fp2);
}

int main(int argc, char *argv[]){
  if (argc != 3) {
    fprintf(stderr, "Usage: %s [file_name]  [file_output_name]\n", argv[0]);
    exit(1);
  }
  xorInput(argv[1], argv[2]);

  return 0;
}
  • If this post is considered duplicate or violates any other site rule leave a comment and i ll delete it. Thank you for your time
  • If you need any further informations let me now.

Solution

  • Adopting most of the suggestions from the comments, I created a file xr71.c:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define Xor_key 0xCF
    
    static
    void xorInput(char *in_name, char *out_name)
    {
        FILE *fp1 = fopen(in_name, "rb");
        if (fp1 == NULL)
        {
            fprintf(stderr, "failed to opn file %s for reading\n", in_name);
            exit(1);
        }
    
        FILE *fp2 = fopen(out_name, "wb");
        if (fp2 == NULL)
        {
            fprintf(stderr, "failed to open file %s for writing\n", out_name);
            exit(1);
        }
    
        char buffer[1024];
        size_t nbytes;
        while ((nbytes = fread(buffer, 1, sizeof(buffer), fp1)) > 0)
        {
            for (size_t i = 0; i < nbytes; ++i)
                buffer[i] ^= Xor_key;
            if (fwrite(buffer, 1, nbytes, fp2) != nbytes)
            {
                fprintf(stderr, "failed to write %zu bytes to %s\n", nbytes, out_name);
                exit(1);
            }
        }
    
        fclose(fp1);    // Error check omitted
        fclose(fp2);    // Error check omitted
    }
    
    int main(int argc, char *argv[])
    {
        if (argc != 3)
        {
            fprintf(stderr, "Usage: %s file_name file_output_name\n", argv[0]);
            exit(1);
        }
        xorInput(argv[1], argv[2]);
    
        return 0;
    }
    

    Note that all error messages are written to standard error. The static is there because of the compilation options I use (see below). Public functions must be declared before being defined; all functions must be declared or defined before being used — with the sole exception of main().

    Compilation and test:

    $ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
    >     -Wstrict-prototypes -Wold-style-definition xr71.c -o xr71  
    $ ./xr71 xr71 xr71.v1
    $ ./xr71 xr71.v1 xr71.v2
    $ cmp xr71 xr71.v2
    $ cmp xr71.v1 xr71.v2
    xr71.v1 xr71.v2 differ: char 1, line 1
    $ cmp -l xr71.v1 xr71.v2
       1   0 317
       2  65 372
       3  42 355
    …
    9034 252 145
    9035 275 162
    9036 317   0
    $ ./xr71
    Usage: xr71 file_name file_output_name
    $ ./xr71 in
    Usage: ./xr71 file_name file_output_name
    $ ./xr71 in out err
    Usage: ./xr71 file_name file_output_name
    $
    

    This is what should be expected. The output file xr71.v1 is different from the input file (that's good; it wouldn't be encrypted otherwise). The output file xr71.v2 is the same as the original input file (xr71), which is good; encryption plus decryption gives you back what you started with.