RC4加密算法是一种对称加密算法

一、对称加密算法

  对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算法,就是加密密钥能够从解密密钥中推算出来,同时解密密钥也可以从加密密钥中推算出来。而在大多数的对称算法中,加密密钥和解密密钥是相同的,所以也称这种加密算法为秘密密钥算法或单密钥算法。它要求发送方和接收方在安全通信之前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信的安全性至关重要。

二、RC4加密算法

1、预备知识

(1)异或

  学习RC4加密算法之前,首先要知道:对明文使用同一个密钥异或两次最后是得到原文的

(2)流密码

① 定义

  流密码是对称密码算法,从明文输入流逐位或逐字节产生密文输出。

  流密码类似于“一次一密”,不同的是“一次一密”使用的是真正的随机数流,而流密码使用的是伪随机数流。

② 实例

  使用最广泛的流密码是RC4

③ 流密码结构

img

④ 设计流密码的主要因素

  1. 加密序列的周期要长,若出现重复的周期过短,容易被破解

  2. 密钥流应该尽可能地接近真正随机数流的特征

  3. 密钥长度要长,以避免穷举攻击

2、RC4算法介绍

  RC4算法是Ron Rivest为RSA公司在1987年设计的一种流密码,作为RSA的商业机密直到1994年才被匿名公布于Internet。

  该算法是一个可变密钥长度、面向字节操作的流密码。该算法以随机置换作为基础,其密码周期很可能大于10100,且该算法的运行速度很快。

  RC4被用于为网络浏览器和服务器间通信而制定的SSL/TLS(安全套接字协议/传输层安全协议)标准中,以及作为IEEE 801.11无线局域网标准一部分的WEP(Wired Equivalent Privacy)协议和新的WiFi受保护访问协议(WPA)中。从这些应用来看,RC4构成了当今网络通信的非常重要的部分,因此这个算法非常重要。

  RC4算法的特点是算法简单,运行速度快,而且密钥长度是可变的,可变范围为1-256字节(8-2048比特),在如今技术支持的前提下,当密钥长度为128比特时,用暴力法搜索密钥已经不太可行,所以可以预见RC4的密钥范围任然可以在今后相当长的时间里抵御暴力搜索密钥的攻击。实际上,如今也没有找到对于128bit密钥长度的RC4加密算法的有效攻击方法。

3、RC4加密原理

img

img

  RC4算法的原理很简单,包括初始化算法(KSA)和**伪随机子密码生成算法(PRGA)**两大部分。

(1)初始化算法(KSA)

① 初始化状态向量S(256字节,用来作为密钥流生成的种子1)

  按照升序,给每个字节赋值0,1,2,3,4,5,6……,254,255

② 初始密钥(由用户输入),长度任意

  建立一个临时向量T。将密钥的值循环复制到T向量如果输入长度小于256个字节,则进行轮转,直到填满

  • 例如输入密钥的是1,2,3,4,5,那么填入的是1,2,3,4,5,1,2,3,4,5,1,2,3,4,5……

  由上述轮转过程得到256个字节的向量T(用来作为密钥流生成的种子2)

③ 开始对状态向量S进行置换操作(用来打乱初始种子1)

  按照下列规则进行,从第零个字节开始,执行256次,保证每个字节都得到处理

j=0;
for(i=0;i<256;i++){
j = (j + S[i] + T[i]) mod 256;
swap(S[i],S[j]);

  因为对S的操作仅是交换,S仍然包含所有值为0-255的元素。

(3)密钥流的生成与加密

  假设我的明文字节数是datalength=1024个字节(当然可以是任意个字节)

i=0;
j=0;
while(datalength--){ // 相当于执行1024次,这样生成的密钥流也是1024个字节
i = (i+1)mod256;
j = (j+S[i])mod256;
swap(S[i],S[j]);
t = (S[i]+S[j])mod256;
k = S[t]; 这里的k就是当前生成的一个密钥流中的一位
// 可以直接在这里进行加密,当然也可以将密钥流保存在数组中,最后进行异或就ok
data[] = data[]^k; // 进行加密,^是异或运算符

  解密按照前面写的,异或两次就是原文,所以只要把密钥流重新拿过来异或一次就能得到原文了

三、完整算法实现

1、C

//程序开始
#include<stdio.h>
#include<string.h>
typedef unsigned longULONG;

/*初始化函数*/
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];
}
}

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;
}

//程序完

2、Python

# rc4.py
import base64


def rc4_init_sbox(key):
s_box = list(range(256)) # 没管秘钥小于256的情况,小于256不断重复填充即可
length = len(key)
# print("原来的 s 盒:%s" % s_box)
T = []
for i in range(256):
T.append(key[i % length])
j = 0
for i in range(256):
j = (j + s_box[i] + ord(T[i])) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
print("混乱后的 s 盒:%s"% s_box)
return s_box


def rc4_encrypt(s_box, data):
res = []
i = j = 0
length = len(data)
for k in range(length):
i = (i + 1) % 256
j = (j + s_box[i]) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
t = (s_box[i] + s_box[j]) % 256
s = s_box[t]
res.append(chr(ord(data[k]) ^ s))
result = "".join(res)
print("RC4加密后的字符串是:%s" % result)
print("RC4加密后(Base64编码)的字c符串是:" + str(base64.b64encode(result.encode('utf-8')), 'utf-8'))
return str(base64.b64encode(result.encode('utf-8')), 'utf-8')


def rc4_decrypt(s_box, data):
data = base64.b64decode(data.encode('utf-8'))
data = bytes.decode(data)
res = []
i = j = 0
length = len(data)
for k in range(length):
i = (i + 1) % 256
j = (j + s_box[i]) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
t = (s_box[i] + s_box[j]) % 256
s = s_box[t]
res.append(chr(ord(data[k]) ^ s))
result = "".join(res)
print("RC4解密后的字符串是:%s" % result)
return result
# main.py
from rc4 import rc4_init_sbox, rc4_encrypt, rc4_decrypt

if __name__ == "__main__":
while True:
function = input("E to encrypt or D to decrypt for rc4:")
if function.upper() == 'E':
data = input("请输入你要进行RC4加密的数据:")
key = input("请输入RC4加密密钥:")
s_box = rc4_init_sbox(key)
rc4_encrypt(s_box, data)
elif function.upper() == 'D':
data = input("请输入你要进行RC4解密的数据:")
key = input("请输入RC4解密密钥:")
s_box = rc4_init_sbox(key)
rc4_decrypt(s_box, data)
else:
print("请输入正确的功能")

参考链接: