RC4加密算法是大名鼎鼎的RSA三人组中的头号人物Ronald Rivest在1987年设计的密钥长度可变的流加密算法簇。之所以称其为簇,是由于其核心部分的S-box长度可为任意,但一般为256字节。该算法的速度可以达到DES加密的10倍左右,且具有很高级别的非线性。RC4起初是用于保护商业机密的。但是在1994年9月,它的算法被发布在互联网上,也就不再有什么商业机密了。RC4也被叫做ARC4(Alleged RC4——所谓的RC4),因为RSA从来就没有正式发布过这个算法。
RC4算法的原理很简单,包括初始化算法(KSA)和伪随机子密码生成算法(PRGA)两大部分。假设S-box的长度为256,密钥长度为Len。
在初始化的过程中,秘钥的主要功能是将S-box搅乱,i确保S-box的每个元素都得到处理,j保证S-box的搅乱是随机的。而不同的S-box在经过伪随机子密码生成算法的处理后可以得到不同的子秘钥序列,将S-box和明文进行xor运算,得到密文,解密过程也完全相同。
程序:(将ARM的指定文件的明文按行加密成密文,再次运行密文将按行解为明文)
#include<stdio.h>
#include<memory.h>
#include<string.h>
#include<stdlib.h>
#define buf_size 1024 //读取明文的最大字节数
typedef struct rc4_key //存放密钥序列
{
unsigned char state[256];
unsigned char x;
unsigned char y;
} rc4_key;
typedef struct rc4_mkey //备份密钥序列
{
unsigned char state[256];
unsigned char x;
unsigned char y;
} rc4_mkey;
#define swap_byte(x,y) t = *(x); *(x) = *(y); *(y) = t
void prepare_key(unsigned char *key_data_ptr, int key_data_len, rc4_key *key) //初始化函数
{
int i;
unsigned char t;
unsigned char swapByte;
unsigned char index1;
unsigned char index2;
unsigned char* state;
short counter;
state = &key->state[0];
for(counter = 0; counter < 256; counter++)
{
state[counter] = counter;
}
key->x = 0;
key->y = 0;
index1 = 0;
index2 = 0;
for(counter = 0; counter < 256; counter++)
{
index2 = (key_data_ptr[index1] + state[counter] + index2) % 256;
swap_byte(&state[counter], &state[index2]);
index1 = (index1 + 1) % key_data_len;
}
}
void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key) //加解密
{
unsigned char t;
unsigned char x;
unsigned char y;
unsigned char* state;
unsigned char xorIndex;
short counter;
x = key->x;
y = key->y;
state = &key->state[0];
for(counter = 0; counter < buffer_len; counter++)
{
x = (x + 1) % 256;
y = (state[x] + y) % 256;
swap_byte(&state[x], &state[y]);
xorIndex = (state[x] + state[y]) % 256;
buffer_ptr[counter] ^= state[xorIndex];
}
key->x = x;
key->y = y;
}
void coding_rc4()
{
char seed[256];
char data[512] = {"just123"}; //密钥
char fname[512] = {"/mnt/key.txt"}; //加密文件路径
char *tn;
char buf[buf_size];
char num[10];
char digit[5];
int hex, rd,i;
int n;
rc4_key key; //密钥序列结构体
rc4_mkey mkey; //备份密钥序列结构体
FILE *fp,*des;
n = strlen(data); //读取密钥长度
if(n>512) //对密钥进行处理使之更好的可是别
{
fprintf(stderr,"can't tolerate key longer than 512 characters./n");
exit(1);
}
if (n&1) //n is odd number
{
strcat(data,"0");
n++; //convert n to even number
}
n/=2;
memset(digit,0,5*sizeof(char));
strcpy(digit,"AA");
for (i=0;i<n;i++)
{
digit[2] = data[i*2];
digit[3] = data[i*2+1];
sscanf(digit,"%x",&hex); //characters in the file key.txt are better to be recognizable hex numbers
seed[i] = hex; //only reserve the two lower hex numbers in varible 'hex'
}
prepare_key(seed,n,&key); //将我们设定好的秘钥对state数组进行搅乱,得到秘钥序列。
strcpy(mkey.state,key.state); //备份密钥序列,后面加密时密钥序列将被打乱
mkey.x = key.x;
mkey.y = key.y;
if((fp=fopen(fname,"r"))==NULL) //打开加密文件
{
exit(1);
}
tn=strdup(fname);
strcat(fname,".en");
if((des=fopen(fname,"w"))==NULL) //打开备份加密文件
{
exit(1);
}
fgets(buf,60,fp); //读取明文第一行
rd = strlen(buf); //读取第一行长度,便于后面的处理
if(buf[rd-2]=='\r') //win7下换行为\r\n linux下为\n
{
rd = rd - 1;
}
buf[rd-1] = '\0';
rc4(buf,rd-1,&key); //加密第一行明文
fgets(num,60,fp); //读取第二行明文
rd = strlen(num);
if(num[rd-1]!='\n') //同上处理
{
rd = rd + 1;
}
num[rd-1] = '\0';
strcpy(key.state,mkey.state); //回复被打乱的密钥序列
key.x = mkey.x;
key.y = mkey.y;
rc4(num,rd-1,&key); //加密第二行明文
strcat(buf,"\n");
strcat(buf,num);
strcat(buf,"\n");
fwrite(buf,1,60,des); //将加密的一二行写入备份文件
fclose(fp);
fclose(des);
sprintf(fname,"rm %s",tn); //删除原明文文件,用密文文件替代
system(fname);
sprintf(fname,"mv %s.en %s",tn,tn);
system(fname);
}
int main()
{
coding_rc4();
}
要注意的是,如果用该程序的RC4()函数那秘钥序列要先进行备份,调用RC4()后秘钥序列将会被打乱,导致下次的秘钥序列和这次的不同,所以备份后下次再调用RC4()函数时进行恢复,使每次加密的秘钥序列相同。
按行加密要注意的是提取出行信息后要去掉换行符,换行符在win7下是\r\n、在linux下为\n。去掉换行符后对行里的内容进行加解密,这样才能更准确。
漏洞:(摘录于百度百科)
由于RC4算法加密是采用的xor,所以,一旦子密钥序列出现了重复,密文就有可能被破解。关于如何破解xor加密,请参看Bruce Schneier的Applied Cryptography一书的1.4节Simple XOR,在此我就不细说了。那么,RC4算法生成的子秘钥序列是否会出现重复呢?由于存在部分弱密钥,使得子密钥序列在不到100万字节内就发生了完全的重复,如果是部分重复,则可能在不到10万字节内就能发生重复,因此,推荐在使用RC4算法时,必须对加密密钥进行测试,判断其是否为弱密钥。其不足主要体现于,在无线网络中IV(初始化向量)不变性漏洞。
--------------------------------------------------------------海鱼