介绍
在密码学中,RC4(Rivest Cipher 4,也称为ARC4或ARCFOUR,意为所谓的RC4)是一种流密码。尽管它以简单性和软件速度着称,但在RC4中发现了多个漏洞,使其不安全。当不丢弃输出密钥流的开头或使用非随机或相关密钥时,它特别容易受到攻击。RC4的使用特别有问题,导致协议非常不安全,例如WEP。
参数介绍
参数名 | 说明 |
S | S-box,长度为256的char型数组,char S[256] |
K | 密钥Key,用户自定义,长度在1~256,用来打乱S-box |
T | 临时变量,长度为256的char型数组 |
D | 保存加密前/后数据 |
基本流程
- 初始化 S 和 T 数组。
- 初始化置换 S。
- 生成密钥流。
初始化S和T数组+初始化置换S
void RC4_Init(unsigned char* S, unsigned char* K, unsigned int len) { int i, j = 0; unsigned char ch_tmp, T[256] = { 0 };//临时变量 for (i = 0; i < 256; ++i) { S[i] = i;//初始化S-box T[i] = K[i % len];//密钥填充临时数组 } //打乱S-box for (i = 0; i < 256; ++i) { j = (j + S[i] + T[i]) % 256; ch_tmp = S[i]; S[i] = S[j]; S[j] = ch_tmp; } }
生成密钥流
void RC4_Crypt(unsigned char* S, unsigned char* D, unsigned int len) { int i = 0, j = 0, int_tmp; unsigned int n; unsigned char ch_tmp; for (n = 0; n < len; ++n) { i = (i + 1) % 256; j = (j + S[i]) % 256; ch_tmp = S[i]; S[i] = S[j]; S[j] = ch_tmp; int_tmp = (S[i] + S[j]) % 256; D[n] ^= S[n]; } }
完整代码实现
C语言
#include <bits/stdc++.h> #pragma warning(disable:4996) void RC4_Init(unsigned char* S, unsigned char* K, unsigned int len) { int i, j = 0; unsigned char ch_tmp, T[256] = { 0 };//临时变量 for (i = 0; i < 256; ++i) { S[i] = i;//初始化S-box T[i] = K[len % 256];//密钥填充临时数组 } //打乱S-box for (i = 0; i < 256; ++i) { j = (j + S[i] + T[i]) % 256; ch_tmp = S[i]; S[i] = S[j]; S[j] = ch_tmp; } } void RC4_Crypt(unsigned char* S, unsigned char* D, unsigned int len) { int i = 0, j = 0, int_tmp; unsigned int n; unsigned char ch_tmp; for (n = 0; n < len; ++n) { i = (i + 1) % 256; j = (j + S[i]) % 256; ch_tmp = S[i]; S[i] = S[j]; S[j] = ch_tmp; int_tmp = (S[i] + S[j]) % 256; D[n] ^= S[n]; } } int main(void) { unsigned char S_box[256] = { 0 }; unsigned char Key[] = { "helloworld" }; unsigned char Data[] = { "youareso" }; int i; printf("加密前数据:%s ", Data); printf("密钥:%s ", Key); RC4_Init(S_box, Key, strlen((char*)Key)); printf("S-box: "); for (i = 0; i < 256; ++i) { printf("%02x", S_box[i]); if ((i + 1) % 16 == 0) printf(" "); } RC4_Crypt(S_box, Data, strlen((char*)Data)); printf(" 加密后数据:%s ", Data); system("PAUSE"); return 0; }
RC4+Base64
不过在实际做题中,往往会将RC4与变表Base64结合起来考(先后顺序)
#include <bits/stdc++.h> #pragma warning(disable:4996) void RC4_Init(unsigned char* S, unsigned char* K, unsigned int len) { int i, j = 0; unsigned char ch_tmp, T[256] = { 0 };//临时变量 for (i = 0; i < 256; ++i) { S[i] = i;//初始化S-box T[i] = K[len % 256];//密钥填充临时数组 } //打乱S-box for (i = 0; i < 256; ++i) { j = (j + S[i] + T[i]) % 256; ch_tmp = S[i]; S[i] = S[j]; S[j] = ch_tmp; } } void RC4_Crypt(unsigned char* S, unsigned char* D, unsigned int len) { int i = 0, j = 0, int_tmp; unsigned int n; unsigned char ch_tmp; for (n = 0; n < len; ++n) { i = (i + 1) % 256; j = (j + S[i]) % 256; ch_tmp = S[i]; S[i] = S[j]; S[j] = ch_tmp; int_tmp = (S[i] + S[j]) % 256; D[n] ^= S[n]; } } unsigned char* base64_encode(unsigned char* str) { long len; long str_len; unsigned char* res = { 0 }; int i, j; unsigned char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; //unsigned char base64_table[] = "0123456789+/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; str_len = strlen((char*)str); if (str_len % 3 == 0) len = str_len / 3 * 4; else len = (str_len / 3 + 1) * 4; res = (unsigned char*)malloc(sizeof(unsigned char) * len + 1); res[len] = '