代码之家  ›  专栏  ›  技术社区  ›  John Vn

Xor加密机新线路问题

  •  2
  • John Vn  · 技术社区  · 8 年前

    我创建了一个简单的程序,它将现有文件作为输入( 文本内容 )对其内容进行加密,并将加密的内容输出到用户指定文件名的文件中( argv[2] ). 问题是,无论何时 fgets 尝试读取它终止的新行字符。所以我想用 fread \0 ). 那么如何实施 弗雷德 在字符串末尾终止?源代码:

    #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;
    }
    
    • 如果你需要进一步的信息,现在就告诉我。
    2 回复  |  直到 8 年前
        1
  •  3
  •   Jonathan Leffler    8 年前

    采纳评论中的大部分建议,我创建了一个文件 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 是因为我使用的编译选项(见下文)。公共职能必须在定义之前声明;所有函数在使用前都必须声明或定义,以下情况除外 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 ),这是好的;加密加解密将使您恢复最初的状态。

        2
  •  3
  •   chux    8 年前

    唯一要做的加密/解密是用密钥对每个字节进行互斥。

    不需要缓冲区(除了可能有助于提高性能外)。无需查找行尾或空字符。只需读取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);
    }