介绍
RC4是一种流密码,可实现短密钥到长密钥的转换,流密码的加密就是比特的异或,为了安全性,关键就是密钥的生成,RC4就是解决密钥生成问题的。
流密码结构:
流密码类似于”一次一密”,不同的是”一次一密”使用的是真正的随机数流,而流密码使用的是伪随机数流。
设计流密码的主要因素
1、加密序列的周期要长,若出现重复的周期过短,容易被破解
2、密钥流应该尽可能地接近真正随机数流的特征
3、密钥长度要长,以避免琼穷举攻击
步骤
1. 密钥编排,向量S和Y初始化
RC4的实现需要三个向量,初始向量S,密钥K,临时向量T
初始化向量S和T,将向量S填充为0到255的数值,根据密钥K,填充向量T。如果密钥K
比向量S短,就依次重复填充密钥K,如果与向量S等长,那么向量T与密钥K相同。
1 2 3 4 5 6
| S = [] T = []
for i in range(256): S.append(i) T.append(key[i % len(key)])
|
2. 向量S的初始置换,将原来有序的向量S重新排列
从0遍历到255,每次 j=(j+S[i]+ord(T[i]))%256,然后交换S[i] 和 S[j],这样S盒顺序就被打乱了
1 2 3 4 5 6
| j = 0 for i in range(256): j = (j + S[i] + ord(T[i])) % 256 S[i], S[j] = S[j], S[i]
|
3. 密钥生成,每加密一个字符,就需要生成一个字节的密钥
根据明文长度生成密钥流
1 2 3 4 5 6 7 8
| Ks = [] i = j = 0 for _ in range(len(M)): i = (i + 1) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] t = (S[i] + S[j]) % 256 Ks.append(t)
|
4. 循环明文长度,每一个字符跟向量S异或
1 2 3 4
| C = "" for i in range(len(M)): C += chr(ord(M[i]) ^ S[Ks[i]]) return C
|
解密也就是把密文当成明文再把加密执行一次
代码
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
| def KSA(key): S = [] T = [] for i in range(256): S.append(i) T.append(key[i % len(key)])
j = 0 for i in range(256): j = (j + S[i] + ord(T[i])) % 256 S[i], S[j] = S[j], S[i] return S
def generateKey(S, M): Ks = [] i = j = 0 for _ in range(len(M)): i = (i + 1) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] t = (S[i] + S[j]) % 256 Ks.append(t) return Ks
def Rc4_encode(M, key): C = "" S = KSA(key) Ks = generateKey(S, M) for i in range(len(M)): C += chr(ord(M[i]) ^ S[Ks[i]]) return C
def Rc4_decode(C, key): M = "" S = KSA(key) Ks = generateKey(S, C) for i in range(len(C)): M += chr(ord(C[i]) ^ S[Ks[i]]) return M
key = '123456789' m = 'hello'
C = Rc4_encode(m, key) print("加密后密文:", C)
M = Rc4_decode(C, key) print("解密后明文:", M)
|
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
| #include <iostream> #include <cstring>
using namespace std;
void rc4_init(unsigned char *S, char *key, int key_len) { unsigned char T[256] = {0}; for (int i = 0; i < 256; i++) { S[i] = i; T[i] = key[i % key_len]; } int j = 0; for (int i = 0; i < 256; i++) { j = (j + S[i] + T[i]) % 256; swap(S[i], S[j]); } }
void rc4_crypto(unsigned char *S, char *text, int text_len) { int i = 0, j = 0, t = 0; for (int k = 0; k < text_len; k++) { i = (i + 1) % 256; j = (j + S[i]) % 256; swap(S[i], S[j]); t = (S[i] + S[j]) % 256; text[k] ^= S[t]; } }
string rc4_main(char *text, int text_len, char *key) {
int key_len = sizeof key - 1; unsigned char S[256] = {0};
rc4_init(S, key, key_len); rc4_crypto(S, text, text_len);
printf("result => %s\n", text);
return text; }
int main() { char key[] = "12345"; char text[] = "hello"; int text_len = sizeof(text) - 1; string aa = rc4_main(text, text_len, key); cout<<aa<<endl; return 0; }
|