如何使用按位 XOR 加密文本文件?
How to encrypt a text file using bit-wise XOR?
我正在尝试使用来自另一个文件 (keys.txt) 的两个特定密钥对左右字符使用按位异或运算来加密来自文本文件的消息,但我收到的消息无法读取原始文本文件前面的代码(没有改变),这是不对的。我正在使用两个文本文件:
1) Input.txt - 包含要加密的消息
2) Keys.txt - 这包含两个字符,它们对 input.txt 中的每个字符进行异或运算(字符 1 是键 1,字符 2 是键 2)
我程序中的代码如下:
str[i]=str[i]^str2[2];
str[++i]=str[i]^str2[1];
break;
是假设执行异或运算的代码行
注意我想要的输出应该类似于这样:
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!");
}
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);
}
您的代码存在多个问题:
while((fgets(str,1024,finp)!=NULL)&(fgets(str2,2,keyFile)!=NULL))
您应该使用逻辑与运算符 (&&) 而不是按位与 (&)
char str2[2];
str2只能容纳2个字符,所以str[2]是非法的。此外,它没有任何 space 来保存结尾的 NULL 字符。
for 循环不正确。这是一个替代方案:
for(i=0; i<len; i++) {
str[i] ^= str2[i%2];
}
最后,简单地对两个字符进行异或运算可能会产生无效的 ascii 字符值,因此无法正确打印。 'b'^'c' 是 1,它可能会在您的终端中打印为垃圾。考虑使用模运算来生成结果字符串。
扩展 Sourav 的回答:如果您使用 8 位代码,例如 ISO-8859-1,其中可打印字符为 32 到 126 和 160 到 255,给出 191 个不同的值。您可以不使用 XOR,而是将每个字符转换为 0 到 190 之间的索引,添加消息字符索引和相应的关键字符索引模数 191,然后将结果转换回字符。
从加密的角度来看,这是一种加密,尽管是一种非常弱的加密。它就是移位密码(凯撒密码)。请注意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
我正在尝试使用来自另一个文件 (keys.txt) 的两个特定密钥对左右字符使用按位异或运算来加密来自文本文件的消息,但我收到的消息无法读取原始文本文件前面的代码(没有改变),这是不对的。我正在使用两个文本文件:
1) Input.txt - 包含要加密的消息
2) Keys.txt - 这包含两个字符,它们对 input.txt 中的每个字符进行异或运算(字符 1 是键 1,字符 2 是键 2)
我程序中的代码如下:
str[i]=str[i]^str2[2];
str[++i]=str[i]^str2[1];
break;
是假设执行异或运算的代码行
注意我想要的输出应该类似于这样:
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!");
}
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);
}
您的代码存在多个问题:
while((fgets(str,1024,finp)!=NULL)&(fgets(str2,2,keyFile)!=NULL))
您应该使用逻辑与运算符 (&&) 而不是按位与 (&)
char str2[2];
str2只能容纳2个字符,所以str[2]是非法的。此外,它没有任何 space 来保存结尾的 NULL 字符。
for 循环不正确。这是一个替代方案:
for(i=0; i<len; i++) {
str[i] ^= str2[i%2];
}
最后,简单地对两个字符进行异或运算可能会产生无效的 ascii 字符值,因此无法正确打印。 'b'^'c' 是 1,它可能会在您的终端中打印为垃圾。考虑使用模运算来生成结果字符串。
扩展 Sourav 的回答:如果您使用 8 位代码,例如 ISO-8859-1,其中可打印字符为 32 到 126 和 160 到 255,给出 191 个不同的值。您可以不使用 XOR,而是将每个字符转换为 0 到 190 之间的索引,添加消息字符索引和相应的关键字符索引模数 191,然后将结果转换回字符。
从加密的角度来看,这是一种加密,尽管是一种非常弱的加密。它就是移位密码(凯撒密码)。请注意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