RC4加密出现空字符
来源:互联网 发布:类似金十数据的网站 编辑:程序博客网 时间:2024/05/16 07:24
最近做的竞赛用了RC4加密,网上COPY的代码(没兴趣自己研究密码学,而且我没有数学天分),整到MFC程序中,出了点小问题。
先上代码(做了点小修改)
#include<stdio.h>
#include<string.h>
/*-----------------------初始化函数定义--------------------------*/
void rc4_init(unsigned char *s, unsigned char *key, unsigned long Len) // s为S-box的地址,key是密钥字符串地址,Len是密钥的长度
{
int i=0,j=0;
char k[256] = {0};
unsigned char tmp = 0;
for(i=0;i<256;i++)
{
s[i]=i;
k[i]=key[i%Len];
}
for (i=0; i<256; i++)
{
j=(j+s[i]+k[i])%256;
tmp = s[i];
s[i] = s[j]; //交换s[i]和s[j]
s[j] = tmp;
}
}
/*-----------------------加解密函数定义--------------------------*/
void rc4_crypt(unsigned char *s, unsigned char *Data, unsigned long Len) // s是S-box的地址,Data是需要加(解)密字符串地址
{ // Len是需加(解)密字符串的长度
int i=0,j=0,t=0;
unsigned long k = 0;
unsigned char tmp;
for(k=0;k<Len;k++)
{
i=(i+1)%256;
j=(j+s[i])%256;
tmp = s[i];
s[i] = s[j]; //交换s[x]和s[y]
s[j] = tmp;
t=(s[i]+s[j])%256;
Data[k] ^= s[t];
}
}
/*-------------------------主函数-----------------------------*/
void main()
{
unsigned char s[256]={0}; //S-box
char key[256];
char pData[512];
unsigned long len;
printf("Input Message:");
gets(pData);
len=strlen(pData);
printf("Input Key:");
gets(key);
rc4_init(s,(unsigned char *)key,strlen(key));// 调用初始化函数用密钥对S-box进行初始化
rc4_crypt(s,(unsigned char *)pData,len);// 加密
printf("cipher text: \"%s\"\n\n",pData);// 输出密文
rc4_init(s,(unsigned char *)key, strlen(key));// 调用初始化函数对S-box进行初始化
rc4_crypt(s,(unsigned char *)pData,len);// 解密
printf("plain text: \"%s\"\n\n",pData);// 输出明文
}
你可以试验一下,输入明文SuperMan(注意大小写),输入密钥123。你发现了什么!密文是"",可是再次解密得到的明文却仍然是
"SuperMan"。当时我就震惊了。这是为什么呢?调试发现是在明文加密时,也就是第一次进入rc4_crypt函数时,
for(k=0;k<Len;k++)
{
i=(i+1)%256;
j=(j+s[i])%256;
tmp = s[i];
s[i] = s[j]; //交换s[x]和s[y]
s[j] = tmp;
t=(s[i]+s[j])%256;
Data[k] ^= s[t];//看这里看这里
}
经过一系列变换,s[t]是字符'S',而明文的第一个字符Data[0]刚好是'S',这个时候要进行异或(Data[k] ^= s[t])操作,就导致Data[0]的值变为0,也就是'\0',在后面输出密文的时候,printf函数把'\0'作为字符串结尾,于是输出的就是空的了。
但是解密为什么又能成功呢?因为解密的时候rc4_crypt函数是分别对pData的每个元素解密的,pData[0]不管是什么,它都给你解密出来。另外在对一个字符串进行加密的时候,i、j变量都是在变的,所以你输入"nSuperMan",这里的'S'就不会变成'\0'了。
既然解密出来是对的,那还有什么问题呢?当我把它用到MFC程序中就出问题了。我的MFC程序里用的都是CString类型的,CString很方便,我很喜欢,但是CString也是把'\0'当做字符串结尾的,于是我有些字符串加密出来就会信息不全,甚至向上面的"SuperMan"一样,完全给整没了。
那该怎么办呢?我就用了个最简单的方法:遇到s[t]和Data[k]相同的情况,那个字符直接不加密。Just like that:
if( Data[k] != s[t] )
Data[k] ^= s[t];
不管你喜不喜欢,我还是这样做了。我又懒又笨,不喜欢搞得太复杂。你有什么好的方法,欢迎交流。
具体的MFC代码,不管你需不需要,我也给上了吧。RC4源代码用s[256]、key[256]、pData[512],我也就用这些了,懒得去搞个纯MFC版本的RC4。
void CRC4Dlg::OnEncrypt() //用来加密的Button的消息响应函数
{
UpdateData();
unsigned char s[256]={0};
char pData[512] = {0};
int nLength = m_plain.GetLength();//这里m_plain是与一个EditBox相关联的CString类型的成员变量
for(int i = 0 ; i < nLength ; i++ )//nLength保存了m_plain的字符数
{
pData[i] = m_plain.GetAt(i);//对pData进行赋值
}
char key[256] = {OURKEY};//OURKEY 是个宏:#define OURKEY "123" // 你想要的密钥
rc4_init(s,(unsigned char *)key,strlen(key));//初始化S-box
rc4_crypt(s,(unsigned char *)pData,strlen(pData));//加密
m_cryption = pData;//m_cryption也是和一个EditBox相关联的CString类型的变量,用来保存密文
UpdateData(FALSE);
}
void CRC4Dlg::OnDecrypt() //用来解密的Button的消息响应函数
{
UpdateData();
int i;
unsigned char s[256]={0};
char pData[512] = {0};
int nLength;
length = m_cryption.GetLength();
for( i = 0 ; i < nLength ; i++ )
{
pData[i] = m_cryption.GetAt(i);
}
char key[256] = {OURKEY};
rc4_init(s,(unsigned char *)key,strlen(key));//初始化S-box
rc4_crypt(s,(unsigned char *)pData,strlen(pData));//解密
m_decryption = pData;//m_decryption是个和EditBox相关的CString类的变量,存放解密出的明文
UpdateData(FALSE);
}
还有别忘了在rc4_crypt中处理会出现'\0'的那段代码,否则加密后密文就没了。
这里还有个问题,你在加密的编辑框输入"SuperMan",按加密按钮,密文的编辑框上会显示密文,当你按下解密按钮的时候,出现在解密出的明文的编辑框上的"SuperMa",少了个字符,经常会出现这种情况。这可能是UpdateData从编辑框交换数据时候出的问题。这个问题我没有去研究,求大神指导。另外如果把密文存到一个文件中,再读取这个文件中的密文进行解密,貌似一点问题都没有。
- RC4加密出现空字符
- RC4 加密
- RC4加密
- RC4加密
- RC4加密
- RC4加密
- RC4加密
- RC4加密原理
- RC4加密解密
- php--rc4加密解密
- 加密(RC4,MD5)
- GoAgent设置RC4加密
- Java RC4 文件加密
- java RC4加密解密
- Rc4加密解密
- java RC4加密解密
- Java RC4 加密解密
- RC4对称加密技术
- nutch-2.0源码之GeneratorJob
- 【分享】大量android/iphone软件开发资料和实例代码
- DX11渲染引擎进展(二)
- ubuntu64位bash ./ 没有那个文件目录
- 正则表达式实例(1)
- RC4加密出现空字符
- VC界面开发
- 数据库并发
- NSString的retainCount
- 模式理解(待完善)
- 12306后来补的 检索注入 BUG修改 JS代码
- TCP keepAlive
- strlen返回值为size_t引起的bug
- i2c_msg一些标志的解释