1063 字
5 分钟
RC4加密算法

简介#

RC4 算法是一种流密码,它与之前学习的 MD5,SHA,HMAC,DES 等有根本区别,先与分组加密 DES 做个对比吧:

特性分组加密(DES)流密码(RC4)
处理方式固定大小分组(如 64 位)逐位或逐字节
加密方式分组加密与伪随机密钥流异或
算法结构Feistel 网络/SPN伪随机数生成器
密钥流固定依赖于密钥和状态

核心思想:RC4 生成一个伪随机的密钥流,然后与明文进行逐字节异或操作得到密文

算法步骤#

下面以具体的例子来演示 RC4 加密:“password”,密钥:“secret” RC4 算法分为两个主要阶段:

密钥调度算法#

目的是用一个可变长度的密钥,初始化一个 256 字节的状态向量 S
先来看一下代码:

def KSA(key):
# 1. 初始化S盒:S = [0, 1, 2, ..., 255]
S = list(range(256))
j = 0
key_length = len(key)
# 2. 用密钥打乱S盒
for i in range(256):
j = (j + S[i] + key[i % key_length]) % 256
# 交换S[i]和S[j]
S[i], S[j] = S[j], S[i]
return S

具体到运算中是什么样子呢? 输入密钥:“secret”(ASCII: 115, 101, 99, 114, 101, 116)
初始化 S 盒

S[0] = 0, S[1] = 1, S[2] = 2, ..., S[255] = 255

打乱过程(演示一下前几步):

i=0: j = (0 + S[0] + key[0]) % 256 = (0 + 0 + 115) % 256 = 115
交换 S[0] 和 S[115]:S[0]=115, S[115]=0
i=1: j = (115 + S[1] + key[1]) % 256 = (115 + 1 + 101) % 256 = 217
交换 S[1] 和 S[217]:S[1]=217, S[217]=1
i=2: j = (217 + S[2] + key[2]) % 256 = (217 + 2 + 99) % 256 = 62
交换 S[2] 和 S[62]:S[2]=62, S[62]=2
...

最终就得到了打乱的 S 盒:

S = [115, 217, 62, 123, 245, ...] # 完全打乱的顺序

伪随机生成算法#

利用打乱后的 S 盒生成伪随机的密钥流

def PRGA(S):
i = 0
j = 0
while True:
i = (i + 1) % 256
j = (j + S[i]) % 256
# 交换S[i]和S[j]
S[i], S[j] = S[j], S[i]
# 生成密钥流字节
t = (S[i] + S[j]) % 256
key_byte = S[t]
yield key_byte

明文:“password”(ASCII: 70 61 73 73 77 6F 72 64)
生成密钥流(RGPA)

Terminal window
i = 0, j = 0
第1个密钥字节:
i = (0 + 1) % 256 = 1
j = (0 + S[1]) % 256 = (0 + 217) % 256 = 217
交换 S[1] S[217]:S[1]=1, S[217]=217
t = (S[1] + S[217]) % 256 = (1 + 217) % 256 = 218
密钥字节 = S[218] = (假设为)0x3A
第2个密钥字节:
i = (1 + 1) % 256 = 2
j = (217 + S[2]) % 256 = (217 + 62) % 256 = 23
交换 S[2] S[23]:S[2]=123, S[23]=62
t = (S[2] + S[23]) % 256 = (123 + 62) % 256 = 185
密钥字节 = S[185] = (假设为)0xF7
...

这就生成了一个完整的密钥流了

Terminal window
密钥流: 3A F7 85 2C 91 DE 4B 6C

加解密过程#

加密和解密是使用的相同的操作

def rc4_process(key, data):
# 初始化S盒
S = KSA(key)
# 生成密钥流
key_stream = PRGA(S)
# 逐字节异或
result = bytearray()
for byte in data:
key_byte = next(key_stream)
result.append(byte ^ key_byte)
return bytes(result)

加密:将得到的密钥流和明文进行异或

Terminal window
明文: 70 61 73 73 77 6F 72 64
密钥流: 3A F7 85 2C 91 DE 4B 6C
异或: 4A 96 F6 5F E6 B1 39 08

解密:同理,将得到的密文与密钥流进行异或,就能够得到明文

Terminal window
密文: 4A 96 F6 5F E6 B1 39 08
密钥流: 3A F7 85 2C 91 DE 4B 6C
异或: 70 61 73 73 77 6F 72 64

完整的代码实现#

class RC4:
def __init__(self, key):
"""用给定密钥初始化RC4"""
self.S = list(range(256))
self.i = 0
self.j = 0
self._ksa(key)
def _ksa(self, key):
"""密钥调度算法"""
j = 0
key_length = len(key)
for i in range(256):
j = (j + self.S[i] + key[i % key_length]) % 256
self.S[i], self.S[j] = self.S[j], self.S[i]
def _prga(self):
"""伪随机生成算法(生成一个字节)"""
self.i = (self.i + 1) % 256
self.j = (self.j + self.S[self.i]) % 256
self.S[self.i], self.S[self.j] = self.S[self.j], self.S[self.i]
t = (self.S[self.i] + self.S[self.j]) % 256
return self.S[t]
def process(self, data):
"""加密或解密数据"""
result = bytearray()
for byte in data:
key_byte = self._prga()
result.append(byte ^ key_byte)
return bytes(result)
def rc4_main():
# 测试数据
key = b"secret"
plaintext = b"password"
print(f"密钥: {key.hex()}")
print(f"明文: {plaintext.hex()}")
# 加密
rc4 = RC4(key)
ciphertext = rc4.process(plaintext)
print(f"密文: {ciphertext.hex()}")
# 解密(使用相同密钥重新初始化)
rc4_decrypt = RC4(key)
decrypted = rc4_decrypt.process(ciphertext)
print(f"解密: {decrypted.hex()}")
print(f"验证: {decrypted == plaintext}")
if __name__ == "__main__":
rc4_main()
RC4加密算法
https://819229.xyz/posts/rc4加密算法/
作者
0xnonce
发布于
2026-01-30
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类

换条路线

从其他文章中稳定抽取

评论

正在加载评论...
0/2000

    最后更新于 ,距今已过 212

    部分内容可能已过时