1. 背景与历史
RC4是一种流加密法,这意味着,其加密是逐个字节进行的,但也可以改为逐位加密或者是除字节/位之外的大小。
RC4已经成为某些被广泛使用的加密技术和标准的一部分,包括无线设备隐私、用于无线卡与TLS的WPA。它之所以能被这么广泛部署,是因为它的速度及设计的简单性。它可以用软件和硬件来实现,而且不用消耗太多的资源。
2. 算法描述
RC4生成一个称为密钥流的伪随机流。加密时,这是使用XOR的明文组合。解密也是以类似的方式进行的。
有一个由1~ 256个字节的组成的变长密钥。该密钥 用于初始化一个256字节的状态向量,其元素用S[0],S[1],…,S[255]标识。要进行解密或者解密操作,选取S中的256个字节之一来进行。我们称这个结果输出为K。之后将S的项重新排列一次。这里包含两个处理过程:S的初始化,以及流的生成。
2.1 S的初始化
这个过程处理是由以下步骤组成:
(1)选取一个长度为1~ 256个字节的密钥K。
(2)设置状态向量S的值等于0~ 255(以递增的顺序),也就是说S[0]=0,S[1]=1,…,S[255]=255。
(3)创建临时数组,如果密钥K的长度是256个字节,那么把K复制到S。否则,在把K复制到临时数组后,临时数组的剩余位置再次用K的值进行填充,最后,临时数组必须完全填满。此步骤可以用如下逻辑:
T=bytes(key,encoding='utf-8')#将utf-8的字节码解码成Python默认的unicode的字符串
T=list(T)#转换成列表类型
print('private key:',T)#输出密钥
len_key=len(T)#确定密钥的长度
R=[T[i%len_key] for i in range(256)]#对T进行复制和填充,并保存在R数组中
S=[x for x in range(256)]#列表推导式,初始化状态向量S
j=0
#进行初始置换,位于S[i]的字节与S数组中的另一个字节(由R[i]决定)进行交换
for i in range(256):
j = (j+S[i]+R[i]) % 256
#进行值交换
temp=S[i]
S[i]=R[i]
R[i]=temp
2.2 流的生成
经过以上的初始化和置换以后,S已经准备好了,初始的密钥数组K可以丢弃了。现在我们需要另一个循环。在每一步中,我们把S[i]与S的另一个字节进行交换,每次交换的方法由S的实现来决定。一旦用完了256个位置后,在从S[i]开始,其逻辑代码如下:
i=0
j=0
Sh=[]
length=int(length)
for i in range(length):
i=(i+1)%256
j=(j+S[i])%256
S[i],S[i]=S[j],S[j]
h=(S[j]+S[i])%256
k=S[h]
然后,对于加密,k与明文的下一个字节进行XOR运行。对于解密,k与密文的下一个字节进行XOR运算。
3. 算法实现
其算法的加密和解密的python代码如下:
#RC4的Python实现
def ini_S(R): #初始化S
S=[x for x in range(256)]#列表推导式,初始化状态向量S
j=0
#进行初始置换,位于S[i]的字节与S数组中的另一个字节(由R[i]决定)进行交换
for i in range(256):
j = (j+S[i]+R[i]) % 256
#进行值交换
temp=S[i]
S[i]=R[i]
R[i]=temp
return S
def gen_R(key): #生成辅助表R
T=bytes(key,encoding='utf-8')#将utf-8的字节码解码成Python默认的unicode的字符串
T=list(T)#转换成列表类型
print('private key:',T)#输出密钥
len_key=len(T)#确定密钥的长度
R=[T[i%len_key] for i in range(256)]#对T进行复制和填充,并保存在R数组中
return R
def stream_k(S,length):
i=0
j=0
Sh=[]#Sh保存流
length=int(length)#保存明文的长度或者密文长度的一半
for i in range(length):
i=(i+1)%256#如果用完256个位置,再从S[i]开始
j=(j+S[i])%256#选择S[i]与S的另一个字节
#对S[i]和s的另一字节进行交换
temp=S[i]
S[j]=S[j]
S[i]=temp
h=(S[j]+S[i])%256#防溢出操作
k=S[h]
Sh.append(k)#将k在Sh的末尾添加新的对象
return Sh
choose=input('choose 1--encryption, 2--decryption:')#1为加密,2为解密
#加密操作
if choose=='1':
key=input('input the key:')#key保存密钥
R=gen_R(key)#R保存key的辅助表
S=ini_S(R)#S的初始化
plaintext=input('input the plaintext:')#plaintext保存明文
ciphertext=''#ciphertext保存密文
Sh=stream_k(S,len(plaintext))#生成明文的流
#Sh与明文的下一个字节进行异或运算
for i in range(len(plaintext)):
ciphertext = ciphertext + '%02x'%(Sh[i] ^ ord(plaintext[i]))#进行异或运算并保存在ciphertext
print('ciphertext:',ciphertext)#输出密文
#解密操作
if choose=='2':
key=input('input the key:')#key保存密钥
K=gen_R(key)#K保存key的辅助表
S=ini_S(K)#S的初始化
ciphertext=input('input the ciphertext:')#ciphertext保存密文
plaintext=''#plaintext保存明文
Sh=stream_k(S,len(ciphertext)/2)#生成密文的流
#Sh与密文的下一个字节进行异或运算
for i in range(int(len(ciphertext)/2)):
plaintext = plaintext + chr(int(ciphertext[0:2],16) ^ Sh[i])#进行异或运算并保存在plaintext
ciphertext=ciphertext[2:]
print('plaintext:',plaintext)#输出密文
其加密的结果如下图所示:
其加密的结果如下图所示: