RC4详解
过程视频:https://www.bilibili.com/video/BV1z94y1C79p/?spm_id_from=333.337.search-card.all.click&vd_source=08f1bcaf25b9455e6a042db518c3b0db
简介
RC4是**对称密码(即加密和解密用的是同一个密钥)**算法中的流密码加密算法,密钥长度可变,面向字节操作
它以一个足够大的表S-box为基础,对表进行非线性变换(即函数f(x)的曲线在平面上不是直线,如指数、对数等),产生密钥流
即 明文+密钥=>密文 密文+密钥=>明文
加解密过程
加密过程
1、先初始化状态向量S(256个字节,用来作为密钥流生成的种子1)按照升序,给每个字节赋值0,1,2,3,4,5,6…,254,255
2、初始密钥(由用户输入),长度任意。如果输入长度小于256个字节,则进行轮转,直到填满。例如输入密钥的是1,2,3,4,5,那么填入的是1,2,3,4,5,1,2,3,4,5,1,2,3,4,5……由上述轮转过程得到256个字节的向量T(用来作为密钥流生成的种子2)
3、最后是根据向量S和T生成秘钥流与明文进行加密
代码通常的结构(以C语言为例):
//1、初始化S表,K表
for(i=0;i<256;i++){
S[i]=i;
T[i]=K[i % keylen];
}
//初始排列S
int j=0;
for(int i=0;i<256;i++){
j=(j+S[i]+K[i])%256;
swap(S[i],S[j]);//交换
}
//产生密钥流key[]
int i=0,j=0;
for(int r=0;r<strlen(M);i++){ //M是明文
i=(i+1)%256; //固定的
j=(j+S[i])%256; //固定的
swap(S[i],S[j]); //交换
t=(S[i]+S[j])%256; //
key[r]=S[t]; //生成密钥流
M[r]^=key[r] //解密明文
}
解密过程
通过对加密过程的了解我们可以知道RC4的关键点在 密钥流的生成和对明文的异或
所以在做题时我们应该找到:
1、填充K表的key
2、明文
所以:解密代码与加密代码雷同
特征识别
1、在加密过程中使用了==%256(取余)==
2、==交换(swap)==在加密过程中可以看到
tmp = s[i];
s[i] = s[j];//交换s[x]和s[y]
s[j] = tmp;
魔改
1、可能会对S表修改,原来是0~255可以改为0 ~124等等
2、会对初始化S表增加可逆操作如
for(i=0;i<256;i++)
{
j=(j+s[i]+k[i])%256;
temp=s[i];
s[i]=s[j];
s[j]=temp ^ 0x37;
}
3、在对明文异或时操作如
flag[k]=flag[k] ^ key[k] ^ 0x628;
注:具体查看具体分析,以上说的是本人遇到的一些魔改
源代码
由于 RC4 的加密和解密过程相同,因此可以使用同一个函数。
C语言
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void RC4_init(unsigned char *S, const unsigned char *key, int key_length) {
int i, j = 0;
unsigned char temp;
// 初始化状态数组 S
for (i = 0; i < 256; i++) {
S[i] = i;
}
// 根据密钥打乱状态数组 S
for (i = 0; i < 256; i++) {
j = (j + S[i] + key[i % key_length]) % 256;
// 交换 S[i] 和 S[j]
temp = S[i];
S[i] = S[j];
S[j] = temp;
}
}
void RC4_encrypt(const unsigned char *data, unsigned char *output, const unsigned char *key, int data_length, int key_length) {
unsigned char S[256];
int i, j = 0, k = 0;
unsigned char temp;
// 初始化状态数组 S
RC4_init(S, key, key_length);
// 加密过程
for (i = 0; i < data_length; i++) {
j = (j + 1) % 256;
k = (k + S[j]) % 256;
// 交换 S[j] 和 S[k]
temp = S[j];
S[j] = S[k];
S[k] = temp;
// 生成密钥流并加密数据
output[i] = data[i] ^ S[(S[j] + S[k]) % 256];
}
}
int main() {
const char *key = "mysecretkey"; // 密钥
const char *plaintext = "Hello, World!"; // 明文
int key_length = strlen(key);
int data_length = strlen(plaintext);
unsigned char *ciphertext = (unsigned char *)malloc(data_length);
unsigned char *decryptedtext = (unsigned char *)malloc(data_length);
// 加密
RC4_encrypt((unsigned char *)plaintext, ciphertext, (unsigned char *)key, data_length, key_length);
printf("Ciphertext: ");
for (int i = 0; i < data_length; i++) {
printf("%02X ", ciphertext[i]); // 以十六进制输出密文
}
printf("\n");
// 解密(使用相同的函数)
RC4_encrypt(ciphertext, decryptedtext, (unsigned char *)key, data_length, key_length);
printf("Decrypted text: %s\n", decryptedtext);
// 释放内存
free(ciphertext);
free(decryptedtext);
return 0;
}
python
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]
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'mysecretkey' # 密钥
plaintext = b'Hello, World!' # 明文
# 加密
ciphertext = rc4(key, plaintext) #
print(ciphertext.hex().upper()) # 以十六进制输出密文
# 解密(使用相同的函数)
decryptedtext = rc4(key, ciphertext) #
print(decryptedtext.decode())