【问题标题】:How to encrypt a text file using bit-wise XOR?如何使用按位 XOR 加密文本文件?
【发布时间】:2015-06-12 12:22:36
【问题描述】:

我正在尝试通过对左右字符使用来自另一个文件 (keys.txt) 的两个特定密钥的按位异或运算来加密来自文本文件的消息,但我在前面收到不可读的代码原始文本文件(没有改变),这是不对的。我正在使用两个文本文件:

1) Input.txt - 包含要加密的消息

2) Keys.txt - 这包含对 input.txt 中的每个字符进行 XOR 运算的两个字符(字符 1 是键 1,字符 2 是键 2)

我的程序中的以下代码:

str[i]=str[i]^str2[2];
str[++i]=str[i]^str2[1];
break;

是假定执行 XOR 操作的代码行

注意我想要的输出应该是这样的:

m@#EmI(>9S(@)H#FmN# XGmmmmU,H!Gmr(DmI"VmD,F(S!XmU%DmM"C>U(S>,O)9I(9T?U! D>,M!,E;@#B(Gmu%D4,S(:@$U$O*"OmU%DmR%H#F!D`V$M!4N8.N Dm@#EmK"H# 9I(+mmmm)@#B(f

有人可以澄清我遇到的问题吗?

用户应输入:

gcc myProgram.c
./a.out e input.txt keys.txt

(e 代表加密)

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


int main(int args, char *argc[]){

int i;
int len=0;
char str[1024];
char str2[2];
FILE *finp;
FILE *keyFile;

if ( strcmp(argc[1], "e") == 0 )
{
  if ( (finp = fopen(argc[2],"r")) == NULL )
  {
    printf("Could Not Open file %s\n", argc[2]);
    exit(1);
  }

  if ( (keyFile = fopen(argc[3],"r")) == NULL )
  {
    printf("Could Not Open file %s\n", argc[3]);
    exit(1);
  }


  while((fgets(str,1024,finp)!=NULL)&(fgets(str2,2,keyFile)!=NULL))
  {
    printf("%c\n %c",str2[1],str2[2]);


    /* *** START CODE THAT USES INPUT.TXT FILE & KEYS.TXT *** */
    len = strlen(str);
    for(i=0;i<len;i++)
    {
      str[i]=str[i]^str2[2];
      str[++i]=str[i]^str2[1];
      break;
    }
  }

  printf("%s\n", str);
  fclose(finp);
  return 0;

}
else
{
  printf("SORRY!");
}

【问题讨论】:

  • 不要称之为加密。 :-)
  • 这是一种加密,尽管它很弱。它是移位密码(Caesar Cipher)。

标签: c encryption xor


【解决方案1】:

C 数组索引是从零开始的,那么你应该使用

str2[0],str2[1]

而不是

str2[1],str2[2]

在这个片段中

for(i=0;i<len;i++)
{
  str[i]=str[i]^str2[2];
  str[++i]=str[i]^str2[1];
  break;
}

break 语句在第一次迭代后停止循环。你应该删除它。然后你得到

for(i=0;i<len;i++)
{
  str[i]^=str2[1];
  str[++i]^=str2[0];
}

排队

while((fgets(str,1024,finp)!=NULL)&(fgets(str2,2,keyFile)!=NULL))

你需要逻辑与而不是按位

while((fgets(str,1024,finp)!=NULL)&&(fgets(str2,2,keyFile)!=NULL))

如果您的 input.txt 文件包含更多的 1024 字节来显示您需要移动 printf("%s\n", str); 的所有结果;进入while循环

while((fgets(str,1024,finp)!=NULL)&&(fgets(str2,2,keyFile)!=NULL))
{
    ...
    printf("%s\n", str);
}

【讨论】:

    【解决方案2】:

    您的代码存在多个问题:

    while((fgets(str,1024,finp)!=NULL)&(fgets(str2,2,keyFile)!=NULL))
    

    您应该使用逻辑与运算符 (&&) 而不是按位与 (&)

    char str2[2];
    

    str2 只能容纳 2 个字符,因此 str[2] 是非法的。此外,它没有任何空间来保存结束 NULL 字符。

    for 循环不正确。这是一个替代方案:

    for(i=0; i<len; i++) {
     str[i] ^= str2[i%2];
    }
    

    最后,简单地对两个字符进行异或运算会产生无效的 ascii 字符值,因此无法正确打印。 'b'^'c' 为 1,它可能会在您的终端中打印为垃圾。考虑使用模运算来生成结果字符串。

    【讨论】:

      【解决方案3】:

      扩展 Sourav 的答案:如果您使用 8 位代码,例如 ISO-8859-1,其中可打印字符为 32 到 126 和 160 到 255,给出 191 个不同的值。您可以不使用 XOR,而是将每个字符转换为 0 到 190 之间的索引,将消息字符索引和相应的键字符索引模数 191 相加,然后将结果转换回字符。

      【讨论】:

      • 你能给我们举个例子吗?
      • 见下文。我认为它太大了,无法发表评论。
      【解决方案4】:

      从加密的角度来看,这就是加密,尽管它很弱。它是移位密码(Caesar Cipher)。请注意 str[0]^str2[1] 是一个常数,异或运算的顺序无关紧要,所以

       str[i]^=str2[1];
       str[++i]^=str2[0];
      

      相当于:

       char str12=str2[0]^str2[1]; // Outside of the loop
      ...
       str[++i]^=str12;
      

      用保留可读性的方法替换 XOR 是我的解决方案:

      #include<stdio.h>
      #include<stdlib.h>
      #include<string.h>
      
      int index(int c)
      {
          int i;
          if ((c >= 32) && (c <= 126)) {
              i = c - 32; 
          } else if ((c >= 160) && (c <= 255)) {
              i = c - 65; 
          } else {
              i = 63; // Question mark
          }
          return i;
      }
      
      char unindex(int i)
      {
          if (i <= 94) {
              return (char)(i + 32);
          } else {
              return (char)(i + 65);
          }
      }
      
      char encrypt(char a, char b)
      {
          int aa = index(a & 255);
          int bb = index(b & 255);
          int cc = (aa + bb) % 191;
          return unindex(cc);
      }
      
      char decrypt (char a, char b){
          int aa = index(a & 255);
          int bb = index(b & 255);
          int cc = (191 + aa - bb) % 191;
          return unindex(cc);
      }
      
      int main(int args, char *argc[]){
      
          char e;
      
          printf("test\n");
      
          e = encrypt('a',' ');
          printf ("encrypt('a',' ') = %c\n" , e);
          printf ("decrypt('a',' ') = %c\n" , decrypt (e, ' '));
      
          e = encrypt('a','!');
          printf ("encrypt('a','!') = %c\n" , e);
          printf ("decrypt('a','!') = %c\n" , decrypt (e, '!'));
      
          e = encrypt('ב',' ');
          printf ("encrypt('ב',' ') = %c\n" , e);
          printf ("decrypt('ב',' ') = %c\n" , decrypt(e,' '));
      
          printf("(char) 255 = %c\n", (char) 255);
          e = encrypt((char) 255,' ');
          printf ("encrypt(255,' ') = %c\n" , e);
          printf ("decrypt(255,' ') = %c\n" , decrypt(e,' '));
      
          e = encrypt('A',(char) 255);
          printf ("encrypt('A',255) = %c\n" , e);
          printf ("decrypt('A',255) = %c\n" , decrypt(e,(char) 255));
      
          e = encrypt((char) 255,(char) 255);
          printf ("encrypt(255,255) = %c\n" , e);
          printf ("decrypt(255,255) = %c\n" , decrypt(e,(char) 255));
      
          printf("end test\n");
      
          return;
      }es
      

      【讨论】:

        猜你喜欢
        • 2014-03-10
        • 2021-06-23
        • 1970-01-01
        • 2019-03-11
        • 2012-07-28
        • 2016-06-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多