1. 程式人生 > >RC4加密演算法 解析及程式碼

RC4加密演算法 解析及程式碼

原文:http://www.aslike.net/showart.asp?id=147 RC4加密演算法是大名鼎鼎的RSA三人組中的頭號人物Ron Rivest在1987年設計的金鑰長度可變的流加密演算法簇。之所以稱其為簇,是由於其核心部分的S-box長度可為任意,但一般為256位元組。該演算法的速度可以達到DES加密的10倍左右,且具有很高級別的非線性。RC4起初是用於保護商業機密的。但是在1994年9月,它的演算法被髮布在網際網路上,也就不再有什麼商業機密了。RC4也被叫做ARC4(Alleged RC4——所謂的RC4),因為RSA從來就沒有正式釋出過這個演算法。

原理

RC4演算法的原理很簡單,包括初始化演算法(KSA)和偽隨機子密碼生成演算法(PRGA)兩大部分。假設S-box的長度為256,金鑰長度為Len。先來看看演算法的初始化部分(用C程式碼表示): 其中,引數1是一個256長度的char型陣列,定義為: unsigned char sBox[256]; 引數2是金鑰,其內容可以隨便定義:char key[256]; 引數3是金鑰的長度,Len = strlen(key); void rc4_init(unsigned char *s, unsigned char *key, unsigned long Len) { int i =0, j = 0, 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; } } 在初始化的過程中,金鑰的主要功能是將S-box攪亂,i確保S-box的每個元素都得到處理,j保證S-box的攪亂是隨機的。而不同的S-box在經過偽隨機子密碼生成演算法的處理後可以得到不同的子金鑰序列,將S-box和明文進行xor運算,得到密文,解密過程也完全相同。 再來看看演算法的加密部分(用C程式碼表示): 其中,引數1是上邊rc4_init函式中,被攪亂的S-box; 引數2是需要加密的資料data; 引數3是data的長度. void rc4_crypt(unsigned char *s, unsigned char *Data, unsigned long Len) { int x = 0, y = 0, t = 0, i = 0; unsigned char tmp; for(i=0;i<Len;i++) { x=(x+1)%256; y=(y+s[x])%256; tmp = s[x]; s[x] = s[y];     //交換s[x]和s[y] s[y] = tmp; t=(s[x]+s[y])%256; Data[i] ^= s[t]; } } 最後,在main函式中,呼叫順序如下: void main() { unsigned char s[256] = {0};//S-box char key[256] = {"just for test"}; char pData[512] = "這是一個用來加密的資料Data"; ULONG len = strlen(pData); printf("pData = %s\n",pData); printf("key = %s, length = %d\n",key,strlen(key)); rc4_init(s,(unsigned char *)key,strlen(key));//初始化 rc4_crypt(s,(unsigned char *)pData,len);//加密 printf("pData = %s\n\n",pData); rc4_crypt(s,(unsigned char *)pData,len);//解密 printf("pData = %s\n\n",pData); } 因此最終的完整程式是: //程式開始 #include<stdio.h> #include<string.h> typedef unsigned long ULONG; void rc4_init(unsigned char *s, unsigned char *key, unsigned long 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) //加解密 { 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},s2[256] = {0};    //S-box char key[256] = {"just for test"}; char pData[512] = "這是一個用來加密的資料Data"; ULONG len = strlen(pData); printf("pData = %s\n",pData); printf("key = %s, length = %d\n\n",key,strlen(key)); rc4_init(s,(unsigned char *)key,strlen(key));   //已經完成了初始化 printf("完成對S[i]的初始化,如下:\n\n"); for (int i=0; i<256; i++) { printf("%-3d ",s[i]); } printf("\n\n"); for(i=0;i<256;i++)//用s2[i]暫時保留經過初始化的s[i],很重要的!!! { s2[i]=s[i]; } printf("已經初始化,現在加密:\n\n"); rc4_crypt(s,(unsigned char *)pData,len);//加密 printf("pData = %s\n\n",pData); printf("已經加密,現在解密:\n\n"); rc4_init(s,(unsigned char *)key, strlen(key));   //初始化金鑰 rc4_crypt(s2,(unsigned char *)pData,len);//解密 printf("pData = %s\n\n",pData); } //程式完

漏洞

由於RC4演算法加密是採用的xor,所以,一旦子金鑰序列出現了重複,密文就有可能被破解。關於如何破解xor加密,請參看Bruce Schneier的Applied Cryptography一書的1.4節Simple XOR,在此我就不細說了。那麼,RC4演算法生成的子金鑰序列是否會出現重複呢?由於存在部分弱金鑰,使得子金鑰序列在不到100萬字節內就發生了完全的重複,如果是部分重複,則可能在不到10萬字節內就能發生重複,因此,推薦在使用RC4演算法時,必須對加密金鑰進行測試,判斷其是否為弱金鑰。其不足主要體現於,在無線網路中IV(初始化向量)不變性漏洞。 而且,根據目前的分析結果,沒有任何的分析對於金鑰長度達到128位的RC4有效,所以,RC4是目前最安全的加密演算法之一,大家可以放心使用!