RC4加密演算法與逆向方法簡析(未完)
參考文章:
https://www.cnblogs.com/zibility/p/5404478.html
https://www.52pojie.cn/thread-800115-1-1.html
演算法分析
基本介紹
RC4 是一種流加密演算法,金鑰長度可變。它加解密使用相同的金鑰,因此也屬於對稱加密演算法。RC4 是有線等效加密(WEP)中採用的加密演算法,也曾經是 TLS 可採用的演算法之一。
加解密原理
RC4 由偽隨機數生成器和異或運算組成(由於異或運算的對合性,RC4 加密解密使用同一套演算法)。RC4 的金鑰長度可變,範圍是[1,255]。RC4 一個位元組一個位元組地加解密。給定一個金鑰,偽隨機數生成器接受金鑰併產生一個 S 盒。S 盒用來加密資料,而且在加密過程中 S 盒會變化。
C程式碼表示
幾個基本變數:
- S-Box 也就是所謂的 S 盒,是一個 256 長度的 char 型陣列,每個單元都是一個位元組,演算法執行的任何時候,S 都包括 0-255 的 8 位元數的排列組合,只不過值的位置發生了變換。
- 金鑰K char key[256] 金鑰的長度 keylen 與明文長度、金鑰流的長度沒有必然關係
- 臨時向量 k 長度也為 256,每個單元也是一個位元組。如果金鑰的長度是 256 位元組,就直接把金鑰的值賦給 k,否則,輪轉地將金鑰的每個位元組賦給 k
初始化部分
引數 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; 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; } }
初始化長度為 256 的 S 盒。第一個 for 迴圈將 0 到 255 的互不重複的元素裝入 S 盒。第二個 for 迴圈根據金鑰打亂 S 盒,i 確保 S-box 的每個元素都得到處理,j 保證 S-box 的攪亂是隨機的。而不同的 S-box 在經過偽隨機子密碼生成演算法的處理後可以得到不同的子金鑰序列,將 S-box 和明文進行 xor 運算,得到密文,解密過程也完全相同。
加密部分
引數 1 是上邊 rc4_init 函式中,被攪亂的 S-box
引數 2 是需要加密的資料 data
引數 3 是 data 的長度
/*加解密*/
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];
}
}
每收到一個位元組,就進行迴圈。通過一定的演算法定位 S 盒中的一個元素,並與輸入位元組異或,得到 k。迴圈中還改變了 S 盒。如果輸入的是明文,輸出的就是密文;如果輸入的是密文,輸出的就是明文。
主函式
int main()
{
unsigned char s[256] = { 0 }, s2[256] = { 0 };//S-box
char key[256] = { "justfortest" };
char pData[512] = "這是一個用來加密的資料Data";
unsigned long len = strlen(pData);
int i;
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 (i = 0; i<256; i++)
{
printf("%02X", s[i]);
if (i && (i + 1) % 16 == 0)putchar('\n');
}
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,(unsignedchar*)key,strlen(key));//初始化金鑰
rc4_crypt(s2, (unsigned char*)pData, len);//解密
printf("pData=%s\n\n", pData);
return 0;
}
逆向分析
題目待補充