Xor 加密器换行问题

Xor encryptor new line issue

我创建了一个简单的程序,它获取现有文件作为输入(文本内容)加密其内容并将加密的内容输出到用户指定文件名的文件(argv[2])。问题是每当 fgets 试图读取一个换行符时它就会终止。所以我想用 fread 来解决这个问题,但后来又出现了另一个问题。它不会在字符串的 ned ([=14=]) 处停止。那么如何实现 fread 在字符串末尾终止呢?源代码:

#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] != '[=10=]'; ++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;
}

采纳了评论中的大部分建议,我创建了一个文件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;
}

请注意,所有错误消息都写入标准错误。 static 是因为我使用的编译选项(见下文)。 Public 函数必须在定义前声明;所有函数都必须在使用前声明或定义——唯一的例外是 main().

编译测试:

$ 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
$

这是意料之中的事情。输出文件 xr71.v1 与输入文件不同(这很好;否则不会加密)。输出文件xr71.v2与原始输入文件(xr71)相同,很好;加密加解密让你回到你开始的时候。

唯一的 encryption/decryption 是用密钥对每个字节进行异或运算。

不需要缓冲区(除非它可能有助于提高性能)。无需查找行尾或空字符。简单地读取1个字节,^它,然后再写入。重复直到所有数据都被读取。

void xorInput(const char *in, const char *o) {
  FILE *fp = fopen(in, "rb");
  if (fp==NULL) {
    printf("file '%s' isn't here...\n", in);
    exit(1);
  }
  // Open in binary
  FILE *fp2 = fopen(o,"wb");
  if (fp2==NULL) {
    fclose(in);
    printf("file '%s' isn't here...\n", o);
    exit(1);
  }

  int ch;
  while ((ch = fgetc(fp)) != EOF) {
    ch ^= Xor_key;
    fputc(ch, fp2);
  }

  fclose(fp);
  fclose(fp2);
}