RC4概述

以下为维基百科的描述:

密码学中,RC4(来自Rivest Cipher 4的缩写)是一种串流加密法密钥长度可变。它加解密使用相同的密钥,因此也属于对称加密算法。RC4是有线等效加密(WEP)中采用的加密算法,也曾经是TLS可采用的算法之一。

RC4是由美国密码学家罗纳德·李维斯特(Ronald Rivest)在1987年设计的。由于RC4算法存在弱点,2015年2月所发布的 RFC 7465 规定禁止在TLS中使用RC4加密算法[1]

RC4由伪随机数生成器和异或运算组成。RC4的密钥长度可变,范围是[1,255]。RC4一个字节一个字节地加解密。给定一个密钥,伪随机数生成器接受密钥并产生一个S盒。S盒用来加密数据,而且在加密过程中S盒会变化。

由于异或运算对合性,RC4加密解密使用同一套算法。

运算过程

原理很简单,包括初始化算法(KSA)和伪随机子密码生成算法(PRGA)两大部分

由于是异或运算,加解密同操作—对明文使用同一个密钥异或两次最后得到的是原文

解密脚本

Python:

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
import urllib.parse
import base64

enc = '\0' # enc 中保存密文

key = "HereIsFlagggg" # 密钥

# 生成(搅乱) S-box --- KSA
s_box = list(range(256))
j = 0
for i in range(256):
j = (j + s_box[i] + ord(key[i % len(key)])) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]

# 利用S盒生成密钥流 --- The pseudo-random generation algorithm(PRGA)
# 同时直接进行解密
i = j = 0
res = []
for s in enc:
i = (i + 1) % 256
j = (j + s_box[i]) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
t = (s_box[i] + s_box[j]) % 256
k = s_box[t]
res.append(chr(ord(s) ^ k))

for i in res:
print(i, end="")

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
60
61
62
63
64
65
66
67
68
69
//RC4
#include <stdio.h>
#include <stdint.h>
#include <string.h>

//交换函数
void swap(uint8_t *a, uint8_t *b) {
uint8_t temp = *a;
*a = *b;
*b = temp;
}

//生成的256长度的sbox
uint8_t sbox[256];

//初始化s表
void init_sbox(unsigned char *key) {
unsigned int i, j, k;
int tmp;

for (i = 0; i < 256; i++) {
sbox[i] = i;
}

j = k = 0;
for (i = 0; i < 256; i++) {
tmp = sbox[i];
j = (j + tmp + key[k]) % 256;
sbox[i] = sbox[j];
sbox[j] = tmp;
if (++k >= strlen((char *) key))k = 0;
}
}

void RC4_decode(uint8_t *dec, uint8_t *enc, int len) {
int j = 0, k = 0;
//len为flag长度
for (int i = 0; i < len; ++i) {
j = (j + 1) % 256;
k = (k + sbox[j]) % 256;
swap(sbox + j, sbox + k);
dec[i] = enc[i] ^ (sbox[((int) sbox[j] + sbox[k]) % 256]);
}
}

int main() {
// scanf("%s",s3);
int len;
uint8_t dec[100] = {0};

//需要解密的字节串
uint8_t enc[] = {
'\n', '+', 181, '*', 225, ':', 244, 147, '\'', 182, 'J', 250, '-',
25, 135, 4, 188, '-', 230, '[', 'Q', '5', 'c', 22, 220, 25
};
char key[] = "55667788";
init_sbox((unsigned char *) key);
len = sizeof(enc) / sizeof(enc[0]);
for (int i = 0; i < len; ++i) {
enc[i] -= 1;
}
RC4_decode(dec, enc, len);
// printf("\n");
for (int i = 0; i < len; ++i) {
printf("%c", dec[i]);
}
return 0;
}