rc4学习

感觉打了这么就得逆向,没AI感觉就不中了,啥也干不了,于是从现在开始学习原理知识。

开始rc4的学习以后碰到rc4就放到这个里面来。开始全栈之逆向之路。

标准rec4加密

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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_INPUT_LEN 1024

typedef struct {
unsigned char S[256];
unsigned char i; // 改为 unsigned char 避免转换问题
unsigned char j; // 改为 unsigned char 避免转换问题
} RC4_CTX;

/* 初始化函数 */
void rc4_init(RC4_CTX* ctx, const unsigned char* key, size_t key_len) {
int i; // 使用 int 避免 size_t 转换警告
unsigned char j = 0;
unsigned char temp;

for (i = 0; i < 256; i++) {
ctx->S[i] = (unsigned char)i;
}

ctx->i = 0;
ctx->j = 0;

for (i = 0; i < 256; i++) {
j = (unsigned char)(j + ctx->S[i] + key[i % key_len]); // 显式转换
temp = ctx->S[i];
ctx->S[i] = ctx->S[j];
ctx->S[j] = temp;
}
}

/* 生成密钥流字节 */
unsigned char rc4_generate_byte(RC4_CTX* ctx) {
unsigned char temp;
ctx->i = (unsigned char)(ctx->i + 1);
ctx->j = (unsigned char)(ctx->j + ctx->S[ctx->i]);
temp = ctx->S[ctx->i];
ctx->S[ctx->i] = ctx->S[ctx->j];
ctx->S[ctx->j] = temp;
return ctx->S[(ctx->S[ctx->i] + ctx->S[ctx->j]) & 0xFF]; // 使用位操作避免转换
}

/* 加密函数 */
void rc4_crypt(RC4_CTX* ctx, const unsigned char* input,
unsigned char* output, size_t len) {
size_t n;
for (n = 0; n < len; n++) {
output[n] = input[n] ^ rc4_generate_byte(ctx);
}
}

/* 二进制转十六进制 */
char* bin2hex(const unsigned char* bin, size_t len) {
if (len == 0) return NULL;

char* hex = (char*)malloc(len * 2 + 1);
if (!hex) return NULL;

for (size_t i = 0; i < len; i++) {
sprintf_s(hex + i * 2, 3, "%02X", bin[i]); // 使用安全的 sprintf_s
}
hex[len * 2] = '\0';
return hex;
}

/* 安全获取输入 */
void get_input(const char* prompt, char* buffer, size_t max_len) {
printf("%s", prompt);
if (fgets(buffer, (int)max_len, stdin) == NULL) { // 显式转换
buffer[0] = '\0';
return;
}

// 移除换行符
size_t len = strlen(buffer);
if (len > 0 && buffer[len - 1] == '\n') {
buffer[len - 1] = '\0';
}
}

int main() {
char key[MAX_INPUT_LEN];
char plaintext[MAX_INPUT_LEN];

printf("=== RC4 加密工具 ===\n");

// 获取用户输入
get_input("请输入密钥: ", key, sizeof(key));
get_input("请输入明文: ", plaintext, sizeof(plaintext));

size_t len = strlen(plaintext);
if (len == 0) {
printf("错误: 明文不能为空\n");
return 1;
}

// 分配内存
unsigned char* ciphertext = (unsigned char*)malloc(len);
if (!ciphertext) {
fprintf(stderr, "错误: 内存分配失败\n");
return 1;
}

// 加密过程
RC4_CTX ctx;
rc4_init(&ctx, (const unsigned char*)key, strlen(key));
rc4_crypt(&ctx, (const unsigned char*)plaintext, ciphertext, len);

// 转换为十六进制
char* hex_cipher = bin2hex(ciphertext, len);
if (!hex_cipher) {
fprintf(stderr, "错误: 十六进制转换失败\n");
free(ciphertext);
return 1;
}

// 输出结果
printf("\n加密结果:\n");
printf("密钥: %s\n", key);
printf("明文: %s\n", plaintext);
printf("密文(HEX): %s\n", hex_cipher);

// 清理内存
free(ciphertext);
free(hex_cipher);

printf("\n按 Enter 键退出...");
getchar(); // 忽略返回值
return 0;
}

标准rec4解密

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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define MAX_INPUT_LEN 2048

typedef struct {
unsigned char S[256];
unsigned char i; // 改为 unsigned char 避免转换问题
unsigned char j; // 改为 unsigned char 避免转换问题
} RC4_CTX;

/* 初始化函数 */
void rc4_init(RC4_CTX* ctx, const unsigned char* key, size_t key_len) {
int i; // 使用 int 避免 size_t 转换警告
unsigned char j = 0;
unsigned char temp;

for (i = 0; i < 256; i++) {
ctx->S[i] = (unsigned char)i;
}

ctx->i = 0;
ctx->j = 0;

for (i = 0; i < 256; i++) {
j = (unsigned char)(j + ctx->S[i] + key[i % key_len]); // 显式转换
temp = ctx->S[i];
ctx->S[i] = ctx->S[j];
ctx->S[j] = temp;
}
}

/* 生成密钥流字节 */
unsigned char rc4_generate_byte(RC4_CTX* ctx) {
unsigned char temp;
ctx->i = (unsigned char)(ctx->i + 1);
ctx->j = (unsigned char)(ctx->j + ctx->S[ctx->i]);
temp = ctx->S[ctx->i];
ctx->S[ctx->i] = ctx->S[ctx->j];
ctx->S[ctx->j] = temp;
return ctx->S[(ctx->S[ctx->i] + ctx->S[ctx->j]) & 0xFF]; // 使用位操作避免转换
}

/* 解密函数 */
void rc4_crypt(RC4_CTX* ctx, const unsigned char* input,
unsigned char* output, size_t len) {
size_t n;
for (n = 0; n < len; n++) {
output[n] = input[n] ^ rc4_generate_byte(ctx);
}
}

/* 十六进制转二进制 */
unsigned char* hex2bin(const char* hex, size_t* len) {
size_t hex_len = strlen(hex);

// 检查十六进制长度
if (hex_len % 2 != 0) {
fprintf(stderr, "错误: 无效的十六进制长度\n");
return NULL;
}

*len = hex_len / 2;
if (*len == 0) {
return NULL;
}

unsigned char* bin = (unsigned char*)malloc(*len);
if (!bin) return NULL;

for (size_t i = 0; i < *len; i++) {
char hex_byte[3] = { 0 };
hex_byte[0] = hex[i * 2];
hex_byte[1] = hex[i * 2 + 1];

char* endptr;
unsigned long value = strtoul(hex_byte, &endptr, 16);

if (*endptr != '\0' || value > 255) {
fprintf(stderr, "错误: 无效的十六进制字节 '%s'\n", hex_byte);
free(bin);
return NULL;
}

bin[i] = (unsigned char)value;
}

return bin;
}

/* 安全获取输入 */
void get_input(const char* prompt, char* buffer, size_t max_len) {
printf("%s", prompt);
if (fgets(buffer, (int)max_len, stdin) == NULL) { // 显式转换
buffer[0] = '\0';
return;
}

// 移除换行符
size_t len = strlen(buffer);
if (len > 0 && buffer[len - 1] == '\n') {
buffer[len - 1] = '\0';
}
}

int main() {
char key[MAX_INPUT_LEN];
char hex_cipher[MAX_INPUT_LEN];

printf("=== RC4 解密工具 ===\n");

// 获取用户输入
get_input("请输入密钥: ", key, sizeof(key));
get_input("请输入密文(HEX): ", hex_cipher, sizeof(hex_cipher));

// 验证十六进制输入
for (size_t i = 0; hex_cipher[i]; i++) {
if (!isxdigit((unsigned char)hex_cipher[i])) { // 显式类型转换
fprintf(stderr, "错误: 无效的十六进制字符 '%c'\n", hex_cipher[i]);
return 1;
}
}

// 转换为二进制
size_t cipher_len;
unsigned char* ciphertext = hex2bin(hex_cipher, &cipher_len);
if (!ciphertext || cipher_len == 0) {
fprintf(stderr, "错误: 十六进制转换失败\n");
return 1;
}

// 分配解密缓冲区
unsigned char* decrypted = (unsigned char*)calloc(cipher_len + 1, 1);
if (!decrypted) {
fprintf(stderr, "错误: 内存分配失败\n");
free(ciphertext);
return 1;
}

// 解密过程
RC4_CTX ctx;
rc4_init(&ctx, (const unsigned char*)key, strlen(key));
rc4_crypt(&ctx, ciphertext, decrypted, cipher_len);

// 确保字符串终止
decrypted[cipher_len] = '\0';

// 输出结果
printf("\n解密结果:\n");
printf("密钥: %s\n", key);
printf("密文(HEX): %s\n", hex_cipher);
printf("解密文本: %s\n", decrypted);

// 清理内存
free(ciphertext);
free(decrypted);

printf("\n按 Enter 键退出...");
getchar(); // 忽略返回值
return 0;
}

这里来详细了解一下标准rc4

算法概述:RC4(Rivest Cipher 4)是由Ron Rivest在1987年设计的流密码算法,被广泛应用于SSL/TLS、WEP等协议中。它是一种对称

加密算法,使用相同的密钥进行加密和解密。

核心组件

  1. S盒(State Box)
  • 256字节的数组(0-255)
  • 初始化为顺序值:S[0]=0, S[1]=1, ..., S[255]=255
  1. 密钥调度算法(KSA)
  • 使用密钥初始化S盒
  • 伪代码:
1
2
3
4
j = 0
for i from 0 to 255:
j = (j + S[i] + key[i % key_length]) % 256
swap(S[i], S[j])
  1. 伪随机生成算法(PRGA)
  • 生成密钥流字节
  • 伪代码:
1
2
3
4
5
i = (i + 1) % 256
j = (j + S[i]) % 256
swap(S[i], S[j])
K = S[(S[i] + S[j]) % 256]
return K
  1. 加密/解密过程

    • 明文/密文与密钥流字节异或
    • ciphertext_byte = plaintext_byte XOR K
    • plaintext_byte = ciphertext_byte XOR K

详细加密流程

  1. 步骤1: 密钥调度(KSA)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void rc4_init(RC4_CTX *ctx, const unsigned char *key, size_t key_len) {
unsigned char j = 0;
// 初始化S盒
for (int i = 0; i < 256; i++) {
ctx->S[i] = (unsigned char)i;
}

// 重置索引
ctx->i = 0;
ctx->j = 0;

// 使用密钥打乱S盒
for (int i = 0; i < 256; i++) {
j = (j + ctx->S[i] + key[i % key_len]) % 256;
// 交换S[i]和S[j]
unsigned char temp = ctx->S[i];
ctx->S[i] = ctx->S[j];
ctx->S[j] = temp;
}
}

KSA简而言之就是先初始化S盒在用key打乱S盒。

  1. 步骤2: 生成密钥流字节(PRGA)
1
2
3
4
5
6
7
8
9
10
11
12
13
unsigned char rc4_generate_byte(RC4_CTX *ctx) {
// 更新索引
ctx->i = (ctx->i + 1) % 256;
ctx->j = (ctx->j + ctx->S[ctx->i]) % 256;

// 交换S[i]和S[j]
unsigned char temp = ctx->S[ctx->i];
ctx->S[ctx->i] = ctx->S[ctx->j];
ctx->S[ctx->j] = temp;

// 计算密钥流字节
return ctx->S[(ctx->S[ctx->i] + ctx->S[ctx->j]) % 256];
}

PRGA简而言之生成密钥流

  1. 步骤3: 加密数据
1
2
3
4
5
6
7
void rc4_crypt(RC4_CTX *ctx, const unsigned char *input, 
unsigned char *output, size_t len) {
for (size_t n = 0; n < len; n++) {
// 生成密钥流字节并与输入字节异或
output[n] = input[n] ^ rc4_generate_byte(ctx);
}
}

总结:我可以发现只要得到秘钥流就可以通过密文和秘钥流异或得到明文,当然这个用的时候得保证这个异或没有被魔改。