RC4 的算法原理
RC4算法的特点是算法简单,运行速度快,而且密钥长度是可变的,可变范围为1-256字节(8-2048比特),在如今技术支持的前提下,当密钥长度为128比特时,用暴力法搜索密钥已经不太可行,所以可以预见 RC4的密钥范围任然可以在今后相当长的时间里抵御暴力搜索密钥的攻击。实际上,如今也没有找到对于128bit密钥长度的RC4加密算法的有效攻击方法。
基本概念
RC4算法有4个关键的变量
密钥流:RC4 算法的关键是根据明文和密钥生成相应的密钥流,密钥流的长度和明文的长度是对应的,也就是说明文的长度是 500 字节,那么密钥流也是 500 字节。当然,加密生成的密文也是 500 字节,因为密文第 i 字节 = 明文第 i 字节 ^ 密钥流第 i 字节;
状态向量 S:长度为 256Byte,S[0],S[1]…S[255]。每个单元都是一个 Byte,算法运行的任何时候,S 都包括 0-255 的 8Bit 的排列组合,只不过值的位置发生了变换;
临时向量 T:长度也为 256Byte,每个单元也是一个 Byte。如果密钥的长度是 256Byte,就直接把密钥的值赋给 T,否则,轮转地将密钥的每个 Byte 赋给 T;
密钥 K:长度为 1-256Byte,注意密钥的长度(keylen)与明文长度、密钥流的长度没有必然关系,通常密钥的长度为 16Byte(128Bit)。
加密原理
1.初始 S 和 T
先初始化状态向量 S(256 个字节,用来作为密钥流生成的种子 1):按照升序,给每个字节赋值 0,1,2,3,4,5,6…,254,255。
再初始化临时向量 T(初始密钥 K,由用户输入):长度任意,如果输入长度小于 256Byte,则进行轮转,直到填满。例如:输入密钥的是 1,2,3,4,5,那么填入的是 1,2,3,4,5,1,2,3,4,5,1,2,3,4,5…。由上述轮转过程得到 256 个字节的临时向量 T(用来作为密钥流生成的种子 2)
2.初始排列S
开始对状态向量 S 进行置换操作(用来打乱初始种子 1),按照下列规则进行,从第零个字节开始,执行 256 次,保证每个字节都得到处理这样处理后的状态向量 S 几乎是带有一定的随机性了。
3.产生密钥流
算法实现
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
| #include<stdio.h> #include<string.h>
typedef unsigned longULONG;
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len) { int i = 0, j = 0; char k[256] = { 0 }; unsigned char tmp = 0; 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(unsigned char* s, unsigned char* Data, unsigned long Len) { int i = 0, j = 0, t = 0; unsigned long k = 0; unsigned char 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; Data[k] ^= s[t]; } }
int main() { unsigned char s[256] = { 0 }, s2[256] = { 0 }; char key[256] = { "justfortest" }; char pData[512] = "这是一个用来加密的数据 Data"; unsigned long len = strlen(pData); int i;
printf("pData=%s\n", pData); printf("key=%s, length=%zu\n\n", key, strlen(key));
rc4_init(s, (unsigned char*)key, strlen(key)); printf("完成对 S[i] 的初始化,如下:\n\n"); for (i = 0; i<256; i++) { printf("%02X", s[i]); if (i && (i + 1) % 16 == 0)putchar('\n'); } printf("\n\n"); for (i = 0; i<256; i++) { s2[i] = s[i]; }
printf("已经初始化,现在加密: \n\n"); rc4_crypt(s, (unsigned char*)pData, len); printf("pData=%s\n\n", pData);
printf("已经加密,现在解密: \n\n"); rc4_crypt(s2, (unsigned char*)pData, len); printf("pData=%s\n\n", pData);
return 0; }
|
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
| def S_box(R): S = [x for x in range(256)] j = 0 for i in range(256): j = (j + S[i] + K[i]) % 256 S[i], S[j] = S[j], S[i] return S
def gen_K(key): temp = list(bytes(key, encoding='utf-8')) len_key = len(temp) K = [temp[i % len_key] for i in range(256)] return K
def key_box(S, length): j = 0 keys = [] length = int(length) for i in range(length): i = (i + 1) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] t = (S[j] + S[i]) % 256 k = S[t] keys.append(k) return keys
while(1): choose = input('加密输入1,解密输入2,退出输入3:') if choose == '1': key = input('请输入密钥:') K = gen_K(key) S = S_box(K) message = input('输入明文:') secret = '' keys = key_box(S, len(message)) print("十进制密钥流:",keys) for i in range(len(message)): secret = secret + '%02x' % (keys[i] ^ ord(message[i])) print('加密后十六进制密文为:', secret) if choose == '2': key = input('请输入密钥:') K = gen_K(key) S = S_box(K) secret = input('请输入密文:') message = '' keys = key_box(S, len(secret) / 2) for i in range(int(len(secret) / 2)): message = message + chr(int(secret[0:2], 16) ^ keys[i]) secret = secret[2:] print('解密后明文为:', message)
|