RC4加密原理
RC4算法是一种对称算法,这个算法最基本的原理通俗的说就是对一串字符串进行两次异或得到的结果还是其本身,下面看加密过程
RC4的加解密分为初始化、产生密钥流、加解密三部分
1、先初始化状态向量S(初始化S盒)
S盒中填充了256个字节,然后按照升序赋值:0,1,2,···,255;
2、输入初始密钥
这个密钥由作者输入,长度任意,但是如果小于256个字节,就会进行填充,例如:输入12345,那么密钥就会是12345 12345 12345···,这样得到的内容一般被规定为T
3、混淆s盒——KSA过程
将T填充到S盒中,将T中的字符转化为ASCII码,接着运用公式:
j = (j + s_box[i] + 当前密钥字符的ASCII值) % 256
例如:输入密钥为Key(ASCII码为75,101,121),初始S盒数据为s=[0,1,2,···,255],密钥为T=[K,e,y,K,e,···,e]
计算j
1.当i=0时
j = (0 + 0 + 75) % 256 = 75;
那么根据公式,就交换0和75的位置,那么S盒就变成了[75,1,2,···,0,76,···,255]
2.当i=1时
j = (75 + 1 + 101) % 256 = 177;
根据公式就是S盒中的1和177交换位置
以此类推,重复执行255次得到被打乱的S盒
4.计算密钥流字节——PRGA流程
当完成了混淆S盒后才会进入这个环节,会初始化i和j
i=0;j=0
这里用到了这个公式:
密钥流字节 = S[(S[i] + S[j]) % 8]
还是举例来说:
假设混淆后的S盒为(为了简化计算,假设s盒有8个字节)
[66,88,25,63,···,36]
对于第一个密钥流字节
更新i
i = (0 + 1) % 8 = 1
更新j
j = (0 + s_box[1]) % 8 = (0 + 88) % 8 = 0
交换i与j,那么就更新了S盒
[88,66,25,63,···,36]
接着就是用上面的那个公式
第一个字节=(88+66)%8=2,这个2对应s盒中的25,将其转化为16进制0x17,以此类推就完成对每一个字符的加密
尝试用Python实现RC4加解密
根据上面提到的原理便可以用python写一个这样的加解密脚本
def KSA(key):
key = key.encode('utf-8')
s_box = list(range(256)) # 初始化S盒
j = 0
for i in range(256):
j = (j + s_box[i] + key[i % len(key)]) % 256
s_box[i], s_box[j] = s_box[j], s_box[i] # 交换元素
return s_box
def PRGA(s_box):
i = 0
j = 0
while True:
i = (i + 1) % 256
j = (j + s_box[i]) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
yield s_box[(s_box[i] + s_box[j]) % 256] # 生成密钥流
def RC4_process(data: bytes, key: str) -> bytes:
"""RC4加密/解密函数"""
s_box = KSA(key)
key_stream = PRGA(s_box)
return bytes([byte ^ next(key_stream) for byte in data])
# 用户交互
mode = input("请选择模式(1加密/2解密):").strip()
key = input("输入密钥:").strip()
if mode == '1':
plaintext = input("输入明文:").strip()
cipher_bytes = RC4_process(plaintext.encode('utf-8'), key)
print("加密结果为:", cipher_bytes.hex())
elif mode == '2':
cipher_hex = input("输入密文:").strip()
try:
cipher_bytes = bytes.fromhex(cipher_hex)
decrypted_bytes = RC4_process(cipher_bytes, key)
print("解密结果:", decrypted_bytes.decode('utf-8', errors='replace'))
except ValueError:
print("错误:无效的十六进制格式!")
else:
print("无效的模式选择!")
验证:
例题
1.[SWPUCTF 2021 新生赛]简简单单的解密
这题就是单纯考察对RC4加密的认识,明文和密钥都给了,只需要使用脚本即可
2.[GHCTF 2025]FishingKit
先查壳,发现没壳,用ida打开查看主调函数。
可以看到,这里是比较了V4和一串字符,就去追踪与V4加密有关的那个函数sub_7FF7CABD1150
发现要求出a1的值,观察了一下出现了a1到a1[9],推断a由10个字节组成,我的理解是一个15元一次方程组联立求解得到每一个字节,根据查询搜索,得知可以用Z3数组约束法来求解
解得DeluxeBait
接着回去看主调函数,发现好像一直都是一个函数,就回去看汇编流程图看到strcmp()函数和str1,str2,感觉像是第二个判断条件,倒着追踪上去,发现sub_7FF7CABD2460函数是一个RC4加密
继续追踪
这里可以确定是RC4加密,但是是个变种,因为这里按照加密流程是先进行RC4加密,之后再与0x14进行异或
先找到str2的值
逆向的话需要将这个加密流程倒过来,先与0x14异或,再进行RC4解密
结果发现解了个寂寞,回去在比较处下了个断点,F7步入看看是怎么比较的,结果发现这里调用了jmp(无条件跳转),来到了sub_7FF7CABD1CE0
进去看看,发现是一个新的加密过程,发现24位密文是byte_7FF7CABD63C8,点进去没发现内容,发现是交叉引用,就用交叉引用看看
但是单纯用交叉引用也找不到,就采用在引用地址处下断点动调来找
这里可以发现,当步入这个函数时右边RCX里储存了密文,就可以在RCX里面直接读取密文,接下来去找加密思路
定位到加密函数地址sub_7FF6CF801CE0根据搜索和AI,得知是xtea加密算法