RC4

LinX Lv1

RC4加密

对称加密,加密解密一套密钥

补充:密钥流生成器根据相同的短种子,生成伪随机数列用于明文的加密和解密

  • 先初始化状态向量S,0~255
  • 初始密钥(由用户输入,如果长度小于256,则进行轮转,得到256个字节的向量T
  • 特征:有很多%256,多个循环次数为256
    最后处理数据为异或
  • 魔改:
    1.在初始化算法加可逆运算
    2.在最后异或时加可逆运算
  • 加密代码如下,用来对比题目是否有魔改
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
#include<stdio.h>
#include<string.h>
void rc4_init(unsigned char*s,unsigned char*key,unsigned long len)
{
int i=0;
int j=0;
unsigned char k[256]={0};
unsigned char temp = 0;
for(i=0;i<256;i++){
s[i]=i; //s为从0~255正序排列
k[i]=key[i%len]; //需要对密钥进行轮转
}
for(i=0;i<256;i++){
j=(j+s[i]+k[i])%256;
temp=s[i];
s[i]=s[j];
s[j]=temp;
} //此时s已经被打乱了
}
void rc4_crypt(unsigned char*s,unsigned char*data,unsigned char*key,unsigned long len){
int i=0,j=0,t=0;
unsigned long k=0;
unsigned char temp;
rc4_init(s,(unsigned char*)key,len-1);
for(k=0;k<len;k++){ //密钥流,i,j是不断变化的
i=(i+1)%256; //固定方式生成i
j=(j+s[i])%256; //固定方式生成j
temp=s[i];
s[i]=s[j];
s[j]=temp;
t=(s[i]+s[j])%256; //固定方式生成t
data[k]=data[k]^s[t]; //密文
}
}
  • 解密如下:
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
60
61
62
63
64
65
66
#include<stdio.h>
/*
RC4初始化函数
*/
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k)
{
int i = 0, j = 0;
char k[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i < 256; i++) {
s[i] = i;
k[i] = key[i % Len_k];
}
for (i = 0; i < 256; i++) {
j = (j + s[i] + k[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}

/*
RC4加解密函数
unsigned char* Data 加解密的数据
unsigned long Len_D 加解密数据的长度
unsigned char* key 密钥
unsigned long Len_k 密钥长度
*/
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{
unsigned char s[256];
rc4_init(s, key, Len_k);
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for (k = 0; k < Len_D; k++) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t = (s[i] + s[j]) % 256;
Data[k] = Data[k] ^ s[t];
}
}
void main()
{
//字符串密钥
unsigned char key[] = "wanyuanshenwande";
unsigned long key_len = sizeof(key) - 1;
//数组密钥
//unsigned char key[] = {};
//unsigned long key_len = sizeof(key);

//加解密数据
unsigned char data[] = "ba19a7116763ba8ba1c236c6bdc30187dcc8afb28c8fa5f266763880b74f5fff915613718f4d19c3baf4bbe24bd57303ce103d";
//加解密
rc4_crypt(data, sizeof(data), key, key_len);

for (int i = 0; i < sizeof(data); i++)
{
printf("%c", data[i]);
}
printf("\n");
return;
}

如果密文是hex

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* RC4初始化函数(修正符号位问题,k数组为unsigned char) */
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k)
{
int i = 0, j = 0;
unsigned char k[256] = { 0 }; // 避免char符号位导致的计算错误
unsigned char tmp = 0;
for (i = 0; i < 256; i++) {
s[i] = i;
k[i] = key[i % Len_k]; // 密钥循环填充
}
for (i = 0; i < 256; i++) {
j = (j + s[i] + k[i]) % 256;
// 交换s[i]和s[j]
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}

/* RC4加解密函数(对称算法,解密=再次加密) */
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k)
{
unsigned char s[256];
rc4_init(s, key, Len_k); // 初始化S盒
int i = 0, j = 0, t = 0;
unsigned long k_idx = 0;
unsigned char tmp;
for (k_idx = 0; k_idx < Len_D; k_idx++) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
// 交换S盒元素
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
// 生成伪随机数t
t = (s[i] + s[j]) % 256;
// 明文/密文异或伪随机数
Data[k_idx] = Data[k_idx] ^ s[t];
}
}

/* 十六进制字符串转字节数组(核心:将密文字符串转为RC4可处理的字节) */
int hex2bytes(const char* hex_str, unsigned char* byte_arr, int max_byte_len)
{
int hex_len = strlen(hex_str);
// 十六进制字符串必须是偶数长度(每2位对应1个字节)
if (hex_len % 2 != 0) {
printf("错误:十六进制字符串长度为奇数!\n");
return -1;
}
int byte_len = hex_len / 2; // 真实字节数
// 检查字节数组缓冲区是否足够
if (byte_len > max_byte_len) {
printf("错误:字节数组缓冲区不足!\n");
return -2;
}
// 逐2位解析十六进制字符为字节
for (int i = 0; i < byte_len; i++) {
// %2hhx:解析2位十六进制为unsigned char
sscanf(hex_str + 2 * i, "%2hhx", &byte_arr[i]);
}
return byte_len;
}

int main()
{
// 1. RC4密钥(与加密时一致)
unsigned char key[] = "thisiskey";
unsigned long key_len = sizeof(key) - 1; // 去掉字符串末尾的'\0'

// 2. 待解密的十六进制密文字符串(你提供的正确密文)
const char* hex_cipher = "c5e3effaeb2eca309a749cb8e5d3711909ceb5071b91";

// 3. 缓冲区:存储转换后的密文字节(足够大即可)
unsigned char cipher_bytes[1024] = {0};
// 转换十六进制字符串为字节数组
int cipher_len = hex2bytes(hex_cipher, cipher_bytes, sizeof(cipher_bytes));
if (cipher_len < 0) {
return -1; // 转换失败,退出
}

// 4. RC4解密(对称加密,解密=用相同密钥再次加密)
rc4_crypt(cipher_bytes, cipher_len, key, key_len);

// 5. 输出解密结果(UTF-8编码)
printf("=== 解密结果 ===\n");
printf("UTF-8字符串:");
for (int i = 0; i < cipher_len; i++) {
printf("%c", cipher_bytes[i]); // 直接输出UTF-8字符
}
printf("\n");

// 可选:输出解密后的十六进制(用于验证)
printf("十六进制形式:");
for (int i = 0; i < cipher_len; i++) {
printf("%02x", cipher_bytes[i]); // 补零输出两位十六进制
}
printf("\n");

return 0;
}
  • Title: RC4
  • Author: LinX
  • Created at : 2026-01-01 22:59:45
  • Updated at : 2026-01-02 03:07:30
  • Link: https://redefine.ohevan.com/2026/01/01/rc4/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
On this page
RC4