原理很简单,包括初始化算法(KSA)和伪随机子密码生成算法(PRGA)两大部分。
关键在于密钥流生成器的理解,个人认为该加密手段是通过生成密钥对256取模后得到下标的不确定性从而达到混乱和扩散的目的。
先放上一张原理图:
在初始化的过程中,密钥的主要功能是将S-box搅乱,i确保S-box的每个元素都得到处理,j保证S-box的搅乱是随机的。而不同的S-box在经过伪随机子密码生成算法的处理后可以得到不同的子密钥序列,将S-box和明文进行xor运算,得到密文,解密过程也完全相同。
/*初始化函数*/ void rc4_init(unsigned char*s,unsigned char*key, unsigned long Len) { int i=0,j=0; unsigned char T[256]={0}; unsigned char tmp=0; for(i=0;i<256;i++) { s[i]=i;//s_box初始化为[0,255] T[i]=key[i%Len];//key如果没到256位,就循环输入进T数组 } for(i=0;i<256;i++) { j=(j+s[i]+T[i])%256;//得到一个随机下标 swap(s[i],s[j]);//打乱s数组 } }
加解密过程比较简单
/*加解密*/ 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; swap(s[i],s[j]);//进一步打乱s_box t=(s[i]+s[j])%256;//得到一个随机下标t,s[t]其实就是生成的密钥流中的一位 Data[k]^=s[t];//异或加密,那么解密过程就是再异或一次 } }
int main() { unsigned char s[256] = { 0 }, s2[256] = { 0 };//S-box char key[256] = { "justfortest" };//我的理解是key不要有重复字节,否则s_box会不够乱 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],因为加密函数会进一步对s_box进行置换 { 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; }
总的来说RC4并不难,也比较好看懂,解密脚本写起来也很方便,但是只要保证密钥不是若密钥,那么该算法具有很高的安全性,据分析128位的密钥已经足够安全,没有任何分析对该算法有效,因此可以放心使用。
参考文章:
RC4_百度百科 (baidu.com)
RC4加密算法原理简单理解 - 沉默的赌徒 - 博客园 (cnblogs.com)