RC4加密算法

1.RC4加密算法

这是一种对称加密算法,它的密钥长度可变可变范围为1-256字节(8-2048比特)

2.加密(解密)原理

RC4由伪随机数生成器和异或运算组成。

RC4的密钥长度可变,范围是[1,255]。

RC4一个字节一个字节地加解密。

给定一个密钥,伪随机数生成器接受密钥并产生一个S盒。S盒用来加密数据,而且在加密过程中S盒会变化。

由于异或运算的对合性,RC4加密解密使用同一套算法。

3.RC4算法中的几个关键变量:

1:S-Box 也就是所谓的S盒,是一个256长度的char型数组,每个单元都是一个字节,算法运行的任何时候,S都包括0-255的8比特数的排列组合,只不过值的位置发生了变换。

2:密钥K char key[256] 密钥的长度keylen与明文长度、密钥流的长度没有必然关系

3:临时向量k 长度也为256,每个单元也是一个字节。如果密钥的长度是256字节,就直接把密钥的值赋给k,否则,轮转地将密钥的每个字节赋给k

4.RC4代码

初始化

1:初始化存储0-255字节的Sbox(其实就是一个数组)

2:填充key到256个字节数组中称为Tbox(你输入的key不满256个字节则初始化到256个字节)

3:交换s[i]与s[j] i 从0开始一直到255下标结束. j是 s[i]与T[i]组合得出的下标。

包含三个参数:

参数1是一个256长度的char型数组,定义为: unsigned char sBox[256];

参数2是密钥,其内容可以随便定义:char key[256];

参数3是密钥的长度,Len = strlen(key);

ef init_box(key):
	"""
	S盒
	"""
	s_box=list(range(256))	#这里没管秘钥小于256的情况,小于256应该不断重复填充即可,这里完成了 C 实现中的 for(i=0;i<256;i++) prc4->s_box[i] = i;
	j=0
	for i in range(256):
		j=(j+s_box[i] + ord(key[i % len(key)])) % 256	#这里把 C 实现中的 prc4->t_box[i] = key[i % keylen];和j=(j+prc4->s_box[i]+prc4->t_box[i])%256;合并在了一起。
		s_box[i],s_box[j] = s_box[j],s_box[i]
	#print(type(s_box)) #可以输出 s_box 来看是否随机混乱的
	return s_box
 

加密

遍历数据,将数据与sbox进行异或加密,而在此之前还需要交换一次sbox的数据

交换完之后 再把s[i] + s[j]的组合当做下标再去异或.

包含三个参数:

参数1是上边rc4_init函数中,被搅乱的S-box;

参数2是需要加密的数据data;

参数3是data的长度.

def ex_encrypt(plain,box,mode):
	"""
    利用PRGA生成秘钥流并与密文字节异或,加解密同一个算法
    """
	if mode == '2':
		while True:
			c_mode=input("输入你的解密模式:base64 or ordinary\n")
			if c_mode == 'base64':
				plain=base64.b64decode(plain)
				plain=bytes.decode(plain)				#因为返回的是解码过的  bytes,所以需要再用 decode 解码成字符串。
				break
			elif c_mode == 'ordinary':
				break
			else:
				print("输入不合法,请重新输入")
				continue
	
	res=[]
	i=j=0
	for s in plain:						
		i=(i+1)%256
		j=(j+box[i])%256
		box[i],box[j]=box[j],box[i]
		t=(box[i]+box[j]) % 256
		k=box[t]
		res.append(chr(ord(s)^k))
 
	cipher="".join(res)
    #print(cipher)

解析代码

PRGA算法利用伪随机生成器生成密钥流,并将密钥流与明文进行异或操作来进行加密或解密。

函数中根据传入的mode参数决定是加密还是解密操作。如果mode为'2',则需要进一步选择解密模式,可以选择'base64'或'ordinary'。如果选择'base64'解密模式,则将输入的plain进行base64解码;如果选择'ordinary'解密模式,则直接使用输入的plain

代码中使用了box列表来存储伪随机数生成器的状态,box列表的长度为256,初始值为0到255的连续整数。ij分别表示两个索引,每次循环根据当前索引的值从box中取出一个数,并根据PRGA算法进行交换和计算。最终得到的res列表存储了加密或解密后的字符。

# -*- coding: utf-8 -*-
import base64
 
def get_message():
	print("输入你的信息: ")
	s=input()
	return s
 
def get_key():
	print("输入你的密钥: ")
	key=input()
	if key=='':
		key="不要输入空的 key 值"
	return key
 
def init_box(key):
	"""
	S盒
	"""
	s_box=list(range(256))	#这里没管秘钥小于256的情况,小于256应该不断重复填充即可,这里完成了 C 实现中的 for(i=0;i<256;i++) prc4->s_box[i] = i;
	j=0
	for i in range(256):
		j=(j+s_box[i] + ord(key[i % len(key)])) % 256	#这里把 C 实现中的 prc4->t_box[i] = key[i % keylen];和j=(j+prc4->s_box[i]+prc4->t_box[i])%256;合并在了一起。
		s_box[i],s_box[j] = s_box[j],s_box[i]
	#print(type(s_box)) #可以输出 s_box 来看是否随机混乱的
	return s_box
 
def ex_encrypt(plain,box,mode):
	"""
    利用PRGA生成秘钥流并与密文字节异或,加解密同一个算法
    """
	if mode == '2':
		while True:
			c_mode=input("输入你的解密模式:base64 or ordinary\n")
			if c_mode == 'base64':
				plain=base64.b64decode(plain)
				plain=bytes.decode(plain)				#因为返回的是解码过的  bytes,所以需要再用 decode 解码成字符串。
				break
			elif c_mode == 'ordinary':
				break
			else:
				print("输入不合法,请重新输入")
				continue
	
	res=[]
	i=j=0
	for s in plain:						
		i=(i+1)%256
		j=(j+box[i])%256
		box[i],box[j]=box[j],box[i]
		t=(box[i]+box[j]) % 256
		k=box[t]
		res.append(chr(ord(s)^k))
 
	cipher="".join(res)
    #print(cipher)
 
#根据选择进行输出,至于是明文还是密文得看用户决定
	if mode == '1':
        # 化成可视字符需要编码
		print("加密后的输出(没经过任何编码)")
		print(cipher)
        # base64的目的也是为了变成可见字符
		print("base64后的编码")
		print(str(base64.b64encode(cipher.encode('utf-8')),'utf-8'))
	if mode == '2':
		print("解密后的密文")
		print(cipher)
 
def get_mode():
	print("请选择加密或者解密")
	print("1.Encrypt")
	print("2.Decrypt")
 
	mode = input()
 
	if mode == '1':			#加密解密虽同源,但是由于不能直接用 =='1' or '2',所以还是得分开写
		message = get_message()
		key = get_key()
		box = init_box(key)
		ex_encrypt(message,box,mode)
	elif mode == '2':			#由于异或运算的对合性,RC4加密解密使用同一套算法。
		message = get_message()
		key = get_key()
		box = init_box(key)
		ex_encrypt(message,box,mode)
	else:
		print("输入有误! ")
 
if __name__ == '__main__':
	while True:
		get_mode()

相关推荐

  1. RC4加密

    2024-04-01 12:08:02       22 阅读
  2. RC4加密解密逆向

    2024-04-01 12:08:02       37 阅读
  3. CTF 听说是rc4算法

    2024-04-01 12:08:02       11 阅读
  4. RC4系列

    2024-04-01 12:08:02       30 阅读
  5. RC2CryptoServiceProvider来加密解密

    2024-04-01 12:08:02       41 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-01 12:08:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-01 12:08:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-01 12:08:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-01 12:08:02       20 阅读

热门阅读

  1. 前端Get请求能在body上传参吗

    2024-04-01 12:08:02       19 阅读
  2. centos7安装单机模式kafka 2.12-3.5.2

    2024-04-01 12:08:02       23 阅读
  3. spark报错1

    2024-04-01 12:08:02       15 阅读
  4. linux 克隆更新 UUID方法

    2024-04-01 12:08:02       14 阅读
  5. 代码随想录 完结篇

    2024-04-01 12:08:02       12 阅读
  6. Fiddler实现android手机抓包

    2024-04-01 12:08:02       13 阅读
  7. 排查 Tomcat 启动时闪退的技巧

    2024-04-01 12:08:02       15 阅读