RC4 是一种流加密算法,用于数据的加密和解密,由Ron Rivest于1987年发明。它的名字即“Rivest Cipher 4”的缩写,发明者Ron Rivest 的姓氏以及它是一种流加密算法,被称为RC4。
RC4 算法的核心是一种伪随机数生成器,被称为伪随机数字发生器(PRNG),它使用一个 256 字节的密钥来生成密钥流。RC4 的加密和解密算法都是同一套算法。
RC4 算法操作原理:
1. 首先,使用密钥来初始化生成 RC4 算法的内部状态。如果密钥长于 256 个字节,则将其散列成 256 字节,并使用散列值来初始化内部状态。
2. 然后使用内部状态生成伪随机数流,它是由内部状态和输入密钥流生成的。
3. 最后,将明文与伪随机数流进行异或运算,得到密文。
解密过程与加密过程类似,只需将密文与伪随机数流异或即可得到明文。
本程序是用C语言开发了一个RC4算法的加密工具,开发环境:vs2022.
具体代码如下:
#pragma warning(disable:4996)//不加vs2022会一直报错4996!
#include <stdio.h>
#include <string.h>
void rc4(char* data, int length, const unsigned char* key, int keyLength) /*确保函数key指针指向的数据不被修改*/ {
int i = 0, j = 0;
unsigned char S[256];
for (int k = 0; k < 256; ++k) {
S[k] = k;
}//初始化s盒
for (int k = 0; k < 256; ++k) /*使用循环变量 k 遍历 S 盒的每个元素,从 0 到 255。*/ {
j = (j + S[k] + key[k % keyLength]) % 256;//计算 S 盒中每个元素的新位置。其中,j 表示一个动态变化的下标,S[k] 表示 S 盒中当前位置的值,key[k % keyLength] 表示用密钥序列循环填充的数组。根据 RC4 的算法,每个下标 j 的生成,都和之前 j 的值、S[k] 值以及 key[] 相关,确保了下标 j 的高度随机性。
unsigned char temp = S[k];
S[k] = S[j];
S[j] = temp;//交换 S 盒中 k 和 j 位置的元素。由于 j 的值是随机变化的,因此每个位置的交换是随机的,从而进一步增加了算法的安全性。
}//生成S盒
i = j = 0;
for (int k = 0; k < length; ++k) /*对要加密/解密的数据逐个进行操作,进行 length 次循环(每个字节循环一次)。*/ {
i = (i + 1) % 256;//将变量i加1,保证每次加密/解密的数据不同。
j = (j + S[i]) % 256;//将变量j加上 S[i] 的值,然后对256取模,获取对应的S盒中新的字节。
unsigned char temp = S[i];
S[i] = S[j];
S[j] = temp;将S[i]和S[j]进行交换,每次交换都改变S盒的顺序。
unsigned char t = (S[i] + S[j]) % 256;
data[k] ^= S[t];//计算 S[i] + S[j] 的值并对256取模,获得新的字节,用新的字节与要加密/解密的数据中的对应字节进行异或操作。
}
}
int main() {
int operation;//操作选择标量
char FileName_yuan[260] = { 0 };//源文件
char FileName_mubiao[260] = { 0 };//目标文件
FILE* fp_yuan, * fp_mubiao, * fp_jiami, * fp_jiemi;//打开源文件、写入目标文件、打开已加密问价、写入解密后文件
char key[256], Key2[256], file_cun[1024];//创建存放密钥的数组,用于存储文件内容的数组;
int Bytes_duqu;//创建该变量用于存储读取文件中的每一字节
while (1) {
printf("——————————————欢迎使用本加密工具————————————————\n");
printf("**************请选择要执行的操作:***************\n");
printf("***************1. 文件加密***********************\n");
printf("***************2. 文件解密***********************\n");
printf("***************3. 字符串加密解密******************\n");
printf("***************4. 退出***************************\n");
printf("——————————————————————————————————————————————————\n");
scanf("%d", &operation);
switch (operation) {
case 1:
printf("请输入加密前文件名:");
scanf("%s", FileName_yuan);
printf("请输入加密后文件名:");
scanf("%s", FileName_mubiao);
fp_yuan = fopen(FileName_yuan, "rb");//读取源文件
fp_mubiao = fopen(FileName_mubiao, "wb");//写入目标文件
if (NULL == fp_yuan || NULL == fp_mubiao) {
printf("打开文件失败\n");
break;
}
printf("请输入密钥:");
scanf("%s", key);
while ((Bytes_duqu = fread(file_cun, 1, sizeof(file_cun), fp_yuan)) > 0)/*逐字节读取源文件内容读入到目标文件*/ {
rc4(file_cun, Bytes_duqu, (const unsigned char*)key, strlen(key));/*调用RC4算法对文件内容进行逐字节加密*/
fwrite(file_cun, 1, Bytes_duqu, fp_mubiao);/*将加密后的内容写入目标文件*/
}
fclose(fp_yuan);//关闭文件
fclose(fp_mubiao);
printf("加密成功!\n");
break;
case 2:
printf("请输入已加密文件名:");
scanf("%s", FileName_mubiao);
fp_jiami = fopen(FileName_mubiao, "rb");//读取目标文件成为源文件
fp_jiemi = fopen("已解密文件.txt", "wb");//创建解密后的目标文件
if (NULL == fp_jiami || NULL == fp_jiemi) {
printf("打开文件失败\n");
break;
}
while (1) {
printf("请输入解密密钥:");
scanf("%s", Key2);
// 密钥验证过程
char check_Key1[256];
int Times = 3;
while (Times > 0) {
printf("请再次输入密钥以确认:");
scanf("%s", check_Key1);
if (strcmp(key, check_Key1) == 0) {
break;
}
else {
printf("密钥不正确,请重新输入,您还有%d次机会\n", Times - 1);
Times--;
}
}
if (Times == 0) {
printf("三次输入均不正确,已退出文件加密\n");
break;
}
int decrypted = 0;
while ((Bytes_duqu = fread(file_cun, 1, sizeof(file_cun), fp_jiami)) > 0) {
rc4(file_cun, Bytes_duqu, (const unsigned char*)Key2, strlen(Key2));
fwrite(file_cun, 1, Bytes_duqu, fp_jiemi);
decrypted = 1;
}
if (decrypted) {
fclose(fp_jiami);
fclose(fp_jiemi);
printf("解密完成!\n");
break;
}
else {
printf("密钥错误,请重新输入\n");
}
}
break;
case 3:
printf("请输入要加密的字符串:");
scanf("%s", file_cun);
printf("请输入密钥:");
scanf("%s", key);
rc4(file_cun, strlen(file_cun), (const unsigned char*)key, strlen(key));//调用Rc4进行加密操作
printf("加密后的字符串:%s\n", file_cun);
while (1) {
printf("请输入密钥进行解密:");
scanf("%s", Key2);
//密钥验证过程
char check_Key2[256];
int Times2= 3;
while (Times2 > 0) {
printf("请再次输入密钥以确认:");
scanf("%s", check_Key2);
if (strcmp(key, check_Key2) == 0) {
break;
}
else {
printf("密钥不正确,请重新输入,您还有 % d次机会\n", Times2- 1);
Times2--;
}
}
if (Times2 == 0) {
printf("三次输入均不正确,已退出字符串解密\n");
break;
}
rc4(file_cun, strlen(file_cun), (const unsigned char*)Key2, strlen(Key2));
printf("解密成功!\n解密后的字符串:%s\n", file_cun);
break;
}
break;
case 4:
printf("程序已退出,谢谢使用!\n");
return 0;
default:
printf("无效的选择,请重新输入\n");
break;
}
}
return 0;
}
程序展示:
1.功能列表
2.文件加解密
3.
ps:个人觉得该工具优化的差不多了(能实现字符串和文件加密),最近期末复习考试,呃.....剩下文件分割加密和shell编程实在不想肝了,C++实现RC4等考完试有时间写,欢迎大佬补充。