概念:
在密码学中,RC4(Rivest Cipher 4)是一种流加密算法,密钥长度可变,它加解密使用相同的密钥,因此也属于对称加密算法,RC4是有线等效加密(WEP)中采用的加密算法,也曾经是TLS可采用的算法之一。
补充说明:序列密码(流密码):
流密码也属于对称密码,但与分组加密算法不同的是,流密码不对明文数据进行分组,而是用密钥生成与明文一样长短的密码流对明文进行加密,加解密使用相同的密钥。也就是说,RC4不是对明文进行分组处理,而是字节流的方式依次加密明文中的每一个字节,解密的时候也是依次对密文中的每一个字节进行解密
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 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
| #include <stdio.h>
#include <stdint.h>
void rc4_init(uint8_t*s,uint8_t*key,uint32_t len)
{
int i;
int j=0;
char k[256];
uint8_t tmp;
for(i=0;i<256;i++)
{
s[i]=i;
k[i]=key[i%len];
}
for (i=0;i<256;i++)
{
j=(j+s[i]+k[i])%256;
tmp=s[i];
s[i]=s[j];
s[j]=tmp;
}
}
void rc4_crypt(uint8_t*s,uint8_t*buf,uint32_t len)
{
int i=0,j=0,t=0;
uint32_t k=0;
uint8_t tmp;
for (k=0;k<len;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;
buf[k]^=s[t];
}
}
|
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 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
| def KSA(key):
key_length = len(key)
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % key_length]) % 256
S[i], S[j] = S[j], S[i]
return S
def PRGA(S):
i = 0
j = 0
while True:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
K = S[(S[i] + S[j]) % 256]
yield K
def RC4(key, data):
S = KSA(key)
keystream = PRGA(S)
res = []
for c in data:
res.append(c ^ next(keystream))
return bytes(res)
key = b'密钥'
encrypted_data = b'数据'
decrypted_data = RC4(key, encrypted_data)
print(decrypted_data)
|
识别特征:
该算法在初始化s盒的时候有一个循环次数为256次的for循环
之后根据密钥打乱s盒
最后遍历输入明文的每个字节,从s盒中取一个字节与之异或,完成加密
RC4的加密操作和解密操作一致,因此有时候在动调可以直接下断点在rc4加密之后实现
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
| int __fastcall main(int argc, const char **argv, const char **envp) {
n10 = 0LL; v14[0] = 0x79656B74736574LL; v4 = 0; n256_1 = 0; n256 = 256LL; do { n256_2 = n256_1; *(&v14[34] + n256_1) = n256_1; n256_3 = n256_1; v9 = n256_1 / 7; ++n256_1; *(&v14[2] + n256_2) = *(v14 + n256_3 - 7 * v9); } while ( n256_1 < 256 );
v10 = 0LL; do { v11 = *(&v14[34] + v10); v4 = (v11 + *(&v14[2] + v10) + v4) % 256; v12 = &v14[34] + v4; *(&v14[34] + v10++) = *v12; *v12 = v11; --n256; } while ( n256 );
do { sub_140001010("%02x "); ++n10; } while ( n10 < 10 );
sub_140001010("\n"); return 0; }
|
这里是ida里呈现的伪代码
像在学这种对称密码时,我们可以直接用c实现一下,其次托ida里分析它的反汇编以及伪代码,以此来寻找他们的特征
python解密:
1 2 3 4 5 6 7 8 9 10 11 12 13
| from Crypto.Cipher import ARC4
key=b''
cipher=bytes.fromhex("")
rc4=ARC4.new(key)
plain=rc4.decrypt(cipher)
print(plain)
|
由于CTF比赛里rc4经常出变种
因而大多用不到库函数,所以就要自己写rc4,因此建议各位去学习如何写rc4变种的解密(就从加密中学习就行)