# RC4 加密算法

在密码学中,RC4(Rivest Cipher 4)是一种流加密算法,密钥长度可变,它加解密使
用相同的密钥, 因此也属于对称加密算法,RC4 是有线等效加密(WEP)中采用的加
密算法,也曾经是 TLS 可采用的算法之一。
补充说明:序列密码(流密码):

 流密码也属于对称密码,但与分组加密算法不同的是,流密码不对明⽂数据进⾏分组,
 ⽽是⽤密钥⽣成与明⽂⼀样⻓短的密码流对明⽂进⾏加密,加解密使⽤相同的密钥。也
 就是说,RC4不是对明⽂进⾏分组处理,⽽是字节流的⽅式依次加密明⽂中的每⼀个字
 节,解密的时候也是依次对密⽂中的每⼀ 个字节进⾏解密。  

# (1)S 盒初始化

1
2
3
4
5
6
7
8
for i from 0 to 255
S[i] := i
endfor
j := 0
for i from 0 to 255
j := (j + S[i] + KEY[i mod key_len]) mod 256
swap(S[i], S[j])
endfor

# (2)密钥流生成

1
2
3
4
5
6
7
8
i := 0
j := 0
while GeneratingOutput
i := (i + 1) mod 256
j := (j + S[i]) mod 256
swap(S[i], S[j])
send(S[(S[i] + S[j]) mod 256]) to stream
endwhile

# (3)加密

1
2
3
for i from 0 to plain_len
plain[i] ^= stream[i]
endfor

# C 语言实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <stdio.h>
#include <stdint.h>
/**
* @brief 初始化 RC4 的 S 盒(密钥调度算法 KSA)
* @param s S 盒数组(长度 256)
* @param key 密钥
* @param key_len 密钥长度
*/
void rc4_init(uint8_t *s, const uint8_t *key, uint32_t key_len) {
uint8_t temp;
uint32_t i, j = 0;
// 1. 初始化 S 盒:S[0] = 0, S[1] = 1, ..., S[255] = 255
for (i = 0; i < 256; i++) {
s[i] = i;
}
// 2. 用密钥打乱 S 盒
for (i = 0; i < 256; i++) {
j = (j + s[i] + key[i % key_len]) % 256;
// 交换 S[i] 和 S[j]
temp = s[i];
s[i] = s[j];
s[j] = temp;
}
}
/**
* @brief RC4 加密/解密(伪随机生成算法 PRGA)
* @param s S 盒数组(需已初始化)
* @param data 输入数据(加密或解密)
* @param data_len 数据长度
*/
void rc4_crypt(uint8_t *s, uint8_t *data, uint32_t data_len) {
uint32_t i = 0, j = 0, k;
uint8_t temp;
for (k = 0; k < data_len; k++) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
// 交换 S[i] 和 S[j]
temp = s[i];
s[i] = s[j];
s[j] = temp;
// 生成密钥流字节并异或
data[k] ^= s[(s[i] + s[j]) % 256];
}
}
int main() {
uint8_t S[256]; // RC4 S 盒
const uint8_t key[] = "test_key"; // 密钥
uint8_t data[] = "Hello World!"; // 待加密数据
// 1. 初始化 S 盒
rc4_init(S, key, sizeof(key) - 1); // -1 排除末尾的 '\0'
// 2. 加密(或解密)
rc4_crypt(S, data, sizeof(data) - 1);
// 3. 打印加密后的十六进制结果
for (uint32_t i = 0; i < sizeof(data) - 1; i++) {
printf("%02X ", data[i]);
}
printf("\n");
return 0;
}

识别特征:
该算法在初始化 s 盒的时候有⼀个循环次数为 256 次的 for 循环,之后根据密钥打乱 s 盒
最后遍历输入明文的每个字节,从 s 盒中取⼀个字节与之异或,完成加密。
使用 Python 解密:
1
2
3
4
5
6
from Crypto.Cipher import ARC4
key = b"test_key"
cipher = bytes.fromhex("A0 E2 BA F4 B5 02 ED 9B 41 2F E6 23")
rc4 = ARC4.new(key)
plain = rc4.decrypt(cipher)
print(plain)

# python 实现 rc4 解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def rc4(key, data):
S = list(range(256))
j = 0
# 初始化状态数组 S
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i] # 交换 S[i] 和 S[j]
S[j]=S[j]
i = j = 0
output = []
# 加密过程
for byte in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i] # 交换 S[i] 和 S[j]
K = S[(S[i] + S[j]) % 256]
output.append(byte ^ K) # 生成密钥流并加密数据
return bytes(output)
# 示例使用
key = b"tallmewhy" # 密钥
plaintext =[ 0xF5, 0x8C, 0x8D, 0xE4, 0x9F, 0xA5, 0x28, 0x65, 0x30,
0xF4,
0xEB, 0xD3, 0x24, 0xA9, 0x91, 0x1A, 0x6F, 0xD4, 0x6A, 0xD7,
0x0B, 0x8D, 0xE8, 0xB8, 0x83, 0x4A, 0x5A, 0x6E, 0xBE, 0xCB,
0xF4, 0x4B, 0x99, 0xD6, 0xE6, 0x54, 0x7A, 0x4F, 0x50, 0x14,
0xE5, 0xEC]
#plaintext=b"\xe2\t\x1b\x8fp8\x96E\x11\xbf\x9a1i|\xfb-
\xaf\x99\x95\xe1\x94v"
# 解密(使用相同的函数)
decryptedtext = rc4(key, plaintext) #
print(decryptedtext)

# ida 动态 patch 代码

1
2
3
4
add=0x7FFF6EC6838  #输入地址
enc=[] #加密数据
for i in range(len(enc)):
patch_byte(add+i,enc[i])

更新于 阅读次数