RC4原理及其Python的实现

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)#输出密文

其加密的结果如下图所示:
在这里插入图片描述
其加密的结果如下图所示:
在这里插入图片描述

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZhInen丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值