关于最原始的RC4在ARM中的运用

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(初始化向量)不变性漏洞。
                                                                                                                                                                                                                         --------------------------------------------------------------海鱼

发布了54 篇原创文章 · 获赞 2 · 访问量 6万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章