RC4加密

做逆向题遇到了RC4加密,学习一下相关知识。

RC4算法简介


RC4属于对称密码算法中的流密码加密算法,密钥长度可变(种子密钥),面向字节操作
由于RC4算法加密是采用的异或操作,一旦子密钥序列出现了重复,密文就有可能被破解。

对称密码的特点是加密解密使用同一个密钥,加解密过程可以表示为:
\(m \oplus k \rightarrow c\)
\(c \oplus k \rightarrow m\)
其中\(m\)代表明文,\(c\)代表密文,\(k\)代表密钥。

流密码指逐字节加密算法,相对应的是分组加密算法(快加密),例如DES加密。

密钥流的产生:以一个足够大的表S为基础,对表进行非线性变换,产生密钥流,非线性变换相较于线性变换更加复杂安全。
非线性指假设x为输入数据,y为经过变换后的输出数据,从x到y的映射不为线性函数(\(ax+b=y\))。


加密过程


1. 初始化S表

Step1:对S表进行线性填充,一般为256个字节。从\(S_0\)开始到\(S_{255}\),分别填入0~255
Step2:用种子密钥填充另一个256字节的K表。K表填满为止,如果种子密钥长度小于256,就循环填充(再把种子密钥填充一遍,直到填满)。
Step3:用K表对S表进行初始置换。

初始置换伪代码

j = 0;
for i = 0 to 255 do:
  j = (j + S[i] + K[i])mod 256;
  swap(S[i], S[j]);

这里为方便理解,设S表和K表长度为8,seed为234,相应的也应该模8,则有:

S S[0] S[1] S[2] S[3] S[4] S[5] S[6] S[7]
value 0 1 2 3 4 5 6 7
K K[0] K[1] K[2] K[3] K[4] K[5] K[6] K[7]
value 2 3 4 2 3 4 2 3

具体置换过程:


i = 0,j_0 = 0,j_1 = (0 + 0 + 2) % 8 = 2
S[0] <-> S[2]
S:2 1 0 3 4 5 6 7


i = 1,j_1 = 2,j_2 = (2 + 1 + 3) % 8 = 6
S[1] <-> S[6]
S:2 6 0 3 4 5 1 7


i = 2,j_2 = 6,j_3 = (6 + 2 + 4) % 8 = 2
S[2] <-> S[2]
S:2 6 0 3 4 5 1 7


i = 3,j_3 = 2,j_4 = (2 + 3 + 2) % 8 = 7
S[3] <-> S[7]
S:2 6 0 7 4 5 1 3


i = 4,j_4 = 7,j_5 = (7 + 4 + 3) % 8 = 6
S[4] <-> S[6]
S:2 6 0 7 1 5 4 3


i = 5,j_5 = 6,j_6 = (6 + 5 + 4) % 8 = 7
S[5] <-> S[7]
S:2 6 0 7 1 3 4 5


i = 6,j_6 = 7,j_7 = (7 + 6 + 2) % 8 = 5
S[6] <-> S[5]
S:2 6 0 7 1 4 3 5


i = 7,j_7 = 5,j_8 = (5 + 7 + 3) % 8 = 5
S[7] <-> S[5]
S:2 6 0 7 1 5 3 4

得到初始化后的S表:

S S[0] S[1] S[2] S[3] S[4] S[5] S[6] S[7]
value 2 6 0 7 1 5 3 4

python实现代码如下

import numpy as np

leng = 256   # S表和K表的长度

def int_to_list(seed):
    seed_list = []
    while seed > 0:
        seed_list.insert(0, seed % 10)
        seed = seed // 10
    return seed_list

seed_init = 234   # 输入种子密钥
seed = int_to_list(seed_init)


def cyclic_fill(seed, K):
    filled_K = []
    index = 0
    while len(filled_K) < len(K):
        filled_K.append(seed[index % len(seed)])
        index += 1
    return filled_K

K_init = [0] * leng  # 初始化一个长度为256的数组,全部元素为0
K = cyclic_fill(seed, K_init)


S = np.arange(0,leng,1)
tmp = 0
j = 0
for i in range(leng):
    j = (j + S[i] + K[i]) % leng
    tmp = S[i]
    S[i] = S[j]
    S[j] = tmp

print(S)

2. 生成密钥流并异或加密

给每个待加密的字节生成一个伪随机数,用来异或。伪随机数从S表中获取,找到随机数是S的第几个值(找到下标)。
当S表完成初始化后,不再使用种子密钥。

生成并加密的步骤伪代码

i = 0;
j = 0;
for r = 0 to length do: //r为明文长度,字节数
  i = (i + 1) mod 256;
  j = (j + S[i]) mod 256;
  swap(S[i], S[j]);
  t = (S[i] + S[j]) mod 256;
  k[r] = S[t];
  C[i] = M[i] ^ k[r];

其中k是伪随机数组成的用来与明文进行异或的数组,M为明文,C为密文。
k是再次打乱并选择的S元素,密文需要解密时再次逐位异或k就可以得到明文。

python实现代码如下(接上文代码)

M = "ctf_re"     # 明文
M_len = len(M)
M_list = [ord(c) for c in M]

i = 0
j = 0
tmp = 0
k = [0] * M_len
C_list = [0] * M_len
for r in range(M_len) :   # r为明文长度,字节数
    i = (i + 1) % leng
    j = (j + S[i]) % leng
    tmp = S[i]
    S[i] = S[j]
    S[j] = tmp
    t = (S[i] + S[j]) % leng
    k[r] = S[t]
    C_list[r] = M_list[r] ^ k[r]

C = ''.join(chr(c) for c in C_list)  # 密文
print(C)

3. 加密效果


本文参考视频:
【RC4加密算法| 流密码| 对称密码| 密码学 | 信息安全-哔哩哔哩】 https://b23.tv/TfMso1x

posted @ 2023-10-17 20:24  skdtxdy  阅读(40)  评论(0编辑  收藏  举报