如何使用逐位XOR加密文本文件?

时间:2015-04-07 19:16:09

标签: c encryption xor

我试图通过使用来自另一个文件(keys.txt)的两个特定键的左右字符的逐位XOR操作来加密来自文本文件的消息,但是我在前面接收到不可读的代码原始文本文件(没有改变),这是不对的。我使用的是两个文本文件:

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!");
}

4 个答案:

答案 0 :(得分:3)

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

你需要逻辑AND而不是按位

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

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

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

答案 1 :(得分:3)

您的代码存在多个问题:

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

您应该使用逻辑和运算符(&amp;&amp;)代替按位和(&amp;)

char str2[2];

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

for循环不正确。这是另一种选择:

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

从加密的角度来看,这是加密,虽然是非常弱的。它是Shift Cipher(Caesar Cipher)。请注意,str [0] ^ str2 [1]是一个常量,并且XOR运算的顺序无关紧要,所以

 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