RC4算法对文件进行加密解密

在密码学中,RC4(来自Rivest Cipher 4的缩写)是一种流加密算法,密钥长度可变。它加解密使用相同的密钥,因此也属于对称加密算法。RC4是有线等效加密(WEP)中采用的加密算法,也曾经是TLS可采用的算法之一。

RC4序列密码是美国RSA数据安全公司设计的一种序列密码。其实最开始这家公司并没有公布RC4算法的设计细节,在人们已经通过逆向分析得到了算法之后,在97年RSA公司才公布了RC4密码算法。
RC4算法的优点就是算法简单、高效,适合软件实现。

RC4算法的加密解密流程

RC4加解密相当于是对合运算,所以只要输入密钥相同,那么执行相同的操作即可对数据实现加密和解密。
而RC4和基于以为寄存器的序列密码不同,它是基于非线性数据表变换的序列密码,它以一个足够大的数据表为基础,对表进行非线性变化,从而产生非线性的密钥序列。
基本流程如下:
首先,RC4取一个256字节构成的S表,并引入一个256字节的辅助表R

  1. 对S表进行线性填充
    即初始化S表,另,S[n] = n; (0<=n<=255)

       for(int i = 0;i < ROOM;i++)//初始化S表S[i] = i;
    
  2. 用种子密钥填充R表,如果种子密钥的长度小于R表的长度(256),则依次重复填充,直至将R表填满
    其实依次重复填充的弊端十分明显:

    例如用户输入了密钥a,那么重复填充之后R表中全部为a
    而用户输了密钥aa,那么重复填充之后R表也是全部为a
    这样显然不是一个好的结果

    还有一种做法是做Padding,即若密钥长度小于R表长度时,用固定格式的 padding来填充剩下的部分。

  3. 用R表对S表进行随机化处理
    其操作算法如下:
    ①J = 0;
    ②对于I = 0 : 255
    J = J + S[i] + R[j] mod 256;
    swap(S[i],S[j]);//交换S[i]与S[j]
    代码实现:

       void random(unsigned char *S,std::string R,int length)//随机化S表 {int i;unsigned char temp;unsigned char j = 0;   //R表长度肯定小于等于256,注意模其长度使得不超过其下标并达到重复效果 for( i = 0 ; i < ROOM ; i++ ){j = j + S[i] + R[i % length];temp = S[j];S[j] = S[i];S[i] = temp; }}
    
  4. 加密解密核心功能
    生成了随机化S表之后,就可以对数据执行加密或解密算法了。
    RC4在加密解密时可以看成一个有限状态自动机,通过不断产生新的状态来产生出密钥字节。
    RC4的下一状态函数定义如下:
    ①I = 0 ,J = 0;//初始化状态
    ②I = I + 1 mod 256;
    ③J = J + S[i] mod 256
    ④swap(S[i],S[j]);//交换S[i]与S[j]
    而RC4的输出函数定义为:
    ①h = S[i] + S[j] mod 256;
    ②k = S[h];
    输出函数的输出k即产生出的密钥字节,让RC4有限状态自动机一个一个运转,便输出密钥字节序列。

    在加密时,将密钥字节k与明文字节模二加便完成了加密,解密时将密钥字节k与密文字节模二加就完成了解密。

    代码实现:

      for( num = 0 , i = 0 , j = 0 ; num < size ; num++ ) //逐位生成序列 {          temp = S[i];j = j + temp;S[i] = S[j];S[j] = temp;temp = temp + S[i];data[num] ^= S[temp];//data即加密或解密出的结果i += 1;}
    

总结

通过以上流程,RC4算法就基本完成了,而我们对一些功能和流程进行稍许加工,例如读取文件大小,满足用户加密解密的流程控制等。
最后一个小demo如下:

#include <string>
#include <stdlib.h>
#include <iostream>
#include <windows.h> #define ROOM 256void random(unsigned char *S,std::string R,int length);//随机化S表
bool Encryption(unsigned char *S,long size,char *file_name,int mode);
//加解密文件 因为是对合运算,所以只需要一个函数,用mode控制加密还是解密
long file_size(char* filename);              //读取文件长度int main (int argc, char *argv[])
{int Option;       //功能选择 unsigned char S[ROOM];      //S核心表 long file_length; //文件字节大小char R_temp[ROOM + 1];  //R表的备份表,预留一个'\0' std::string R;           //R表  while(1){R.clear();        //清空数据 file_length = 0; R_temp[0] = '\0';Option = -1;std::cout << "Welcome! Please choose the Option below:" << std::endl;//模式选择 std::cout << "input 1:encrption;" << std::endl;std::cout << "input 2:decrption;" << std::endl;std::cout << "input 0:exit." << std::endl;std::cin >> Option;while( std::cin.fail() )//输入出错处理 {std::cin.clear();   //复位标志位std::cout << "数据类型不对,请重新输入:";    fflush(stdin);      //清空缓冲区 std::cin >> Option;        }if(Option == 0) break;  //0则直接退出else if(Option != 1 && Option != 2){ std::cout << "输入选择有误,请重新输入:" << std::endl; //其他数字continue;}for(int i = 0;i < ROOM;i++)//初始化S表S[i] = i;std::cout << "请输入您的种子密钥" <<std::endl;fflush(stdin);             //清空之前的输入缓冲区std::cin.get(R_temp,ROOM); //保证忽略输入中的空格R = R_temp; int R_length = R.length(); //定义length为R表中字符个数 random(S,R,R_length);      //随机化S表 if(Option == 1){char file_name[16];         //定义加密文件名 std::cout << "请输入您要加密的文件" << std::endl;fflush(stdin);              //清空之前的输入缓冲区std::cin.get(file_name,16); //保证忽略输入中的空格file_length = file_size(file_name);//计算文件字节大小 if(Encryption(S,file_length,file_name,Option))   //加密成功 {std::cout << "退出请输入0,输入其他将回到初始界面" << std::endl; std::cin >> Option; }else                                            //加密失败,3s后返回主页面{std::cout << "加密失败!" << std::endl;for( int temp = 3 ; temp > 0 ; temp-- ){std::cout << temp << "s后将回到初始界面" << std::endl; Sleep(1000);}}}else if(Option == 2){char file_name[16];         //定义解密文件名 std::cout << "请输入您要解密的文件" <<std::endl;fflush(stdin);              //清空之前的输入缓冲区std::cin.get(file_name,16); //保证忽略输入中的空格file_length = file_size(file_name);//计算文件字节大小 if(Encryption(S,file_length,file_name,Option))   //解密成功 {std::cout << "退出请输入0,输入其他将回到初始界面" << std::endl; std::cin >> Option; }else                                         //解密失败,3s后返回主页面 {std::cout << "解密失败!" << std::endl;for( int temp = 3 ; temp > 0 ; temp-- ){std::cout << temp << "s后将回到初始界面" << std::endl; Sleep(1000);}}}if(Option == 0)break; }std::cout << "Thanks" << std::endl;return 0;
}void random(unsigned char *S,std::string R,int length)//随机化S表
{int i;unsigned char temp;unsigned char j = 0; //R表长度肯定小于等于256,注意模其长度使得不超过其下标并达到重复效果 for( i = 0 ; i < ROOM ; i++ ){j = j + S[i] + R[i % length];temp = S[j];S[j] = S[i];S[i] = temp; }
}bool Encryption(unsigned char *S,long size,char *file_name,int mode)//加解密文件 因为是对合运算,所以只需要一个函数,用mode控制加密还是解密
{FILE *pr;                      //定义读文件指针pr pr = fopen(file_name,"rb");    //只读  if(pr == NULL)                 //如果打开文件错误,则退出{std::cout << "用户输入文件打开失败!" << std::endl;return false;} FILE *pw;                      //定义写文件指针pwunsigned char *data;                      //存储原始文件数据,并在运算过程中充当输出序列与原序列的异或结果    unsigned char i,j,temp;             long num;data = (unsigned char *)malloc(size * sizeof(unsigned char));//分配内存 if(mode == 1)pw = fopen("encryption.txt","wb");    //模式为只写且刷新文件 elsepw = fopen("decryption.txt","wb");    //模式为只写且刷新文件if(pw == NULL)                            //如果打开文件错误,则退出{std::cout << "输出文件时出错!" << std::endl;return false;} fread(data,sizeof(char),size,pr);//读取二进制流(需要加/解密的文件) for( num = 0 , i = 0 , j = 0 ; num < size ; num++ ) //逐位生成序列 {           temp = S[i];j = j + temp;S[i] = S[j];S[j] = temp;temp = temp + S[i];data[num] ^= S[temp];i += 1;}if(mode == 1)std::cout << "功能完成,生成encryption.txt文件" << std::endl;elsestd::cout << "功能完成,生成decryption.txt文件" << std::endl;fwrite(data,sizeof(unsigned char),size,pw);//写入二进制流 fclose(pw);//关闭文件流 fclose(pr);free(data);//释放内存 return true;
} long file_size(char *filename) //读取文件长度
{    FILE *fp = fopen(filename,"r");   if(!fp) return -1;    fseek(fp,0L,SEEK_END);    //利用fseek函数将指针定位在文件结尾的位置long size = ftell(fp);    //利用ftell函数返回指针相对于文件开头的位置,以字节计算 fclose(fp);        return size;
}

RC4算法对文件进行加密解密相关推荐

  1. C#实现AES算法对文件的加密解密

    本文实现了C#内置的AES算法对文件进行加密解密.有关AES的介绍不再赘述,主要讲如何实现文件的加密解密.项目工程源代码下载 网上的实现基本上都是要16,24或32位密码,密钥向量也要16位,都固定死 ...

  2. java 文件 加解密_Java实现文件的加密解密功能示例

    Java实现文件的加密解密功能示例 发布时间:2020-10-05 22:05:15 来源:脚本之家 阅读:86 作者:FC WORLD!!! 本文实例讲述了Java实现文件的加密解密功能分享给大家供 ...

  3. java对sha1的解密_Java实现文件的加密解密功能示例

    本文实例讲述了java实现文件的加密解密功能分享给大家供大家参考,具体如下: package com.copy.encrypt; import java.io.file; import java.io ...

  4. java实现文件加密与解密_Java实现文件的加密解密功能示例

    本文实例讲述了Java实现文件的加密解密功能分享给大家供大家参考,具体如下: package com.copy.encrypt; import java.io.File; import java.io ...

  5. java 文件进行加密解密_java使用异或对文件进行加密解密

    本文实例为大家分享了java使用异或对文件进行加密解密的具体代码,供大家参考,具体内容如下 1.使用异或的方式加密文件的原理 一个数异或另一个数两次,结果一定是其本身 2.使用异或的原理加密文件 /* ...

  6. java开发文件夹加密解密程序_Java应用开发:文件加密解密

    本人记性不是很好,总是忘记些重要信息,特别是密码,很多时间登录都要试好几个密码才成功.所以想到了把 这些容易忘记的重要信息记录到一个文本文件上,再对其加密(不易忘记的密码).对文件的加密,自己写了个小 ...

  7. AES128-ECB对文件进行加密解密验证

    AES128-ECB对文件进行加密解密验证 一.源码函数讲解 源码下载地址 #ifndef __AES_H__ #define __AES_H__#include <stdint.h>/* ...

  8. 关于文件透明加密解密

    1.windows文件系统概述 硬盘文档加密系统驱动原理一般有两种:通过HOOK一些底层的系统内核调用对文件目录的访问权限进行控制,在文件系统输入输出驱动上层直接建立一个驱动对文件目录的数据进行加密. ...

  9. RSA实现对文件的加密解密

    很多示例只能加密小文件 这个可以加密大点的文件 文件越大加解密时间越长 package com.harp.oa.utils;import org.bouncycastle.jce.provider.B ...

最新文章

  1. 2021-2027全球与中国奶牛冻精市场现状及未来发展趋势
  2. linux项目课程设计,LINUX课程设计项目需求解析.doc
  3. 利用 Anderson-Darling Test 安德森-达令检验样本数据是否来自特定分布(包括分布:‘norm‘, ‘expon‘, ‘gumbel‘, ‘extreme1‘ or ‘logisti
  4. element表格多列排序_Excel表格在工作中的经典用法,建议收藏!
  5. 玩转OpenVswitch:简介
  6. PHP(一) 开发环境搭建
  7. Ubuntu关闭anaconda自动进入base虚拟环境
  8. Linux系统中/dev/mtd与/dev/mtdblock的区别
  9. 量子计算机模型机,物理科学:量子计算机上实现了量子人工生命模型!
  10. mysql与缓存脏读_MySQL 事务的隔离级别问题 之 脏读
  11. 测试需要的的linux命令,(面试必备)软件测试人员必备Linux命令操做(初级基础)...
  12. CentOS下FastDFS+Nginx(单点部署)事例
  13. .net mysql 类库_在VBnet中连接MySql类库
  14. list add java_list.add()和list.addAll()的区别
  15. 矩阵的逆和矩阵的转置运算公式对比
  16. 【禁止重复造轮子Day01】省市级连的递归
  17. 方法教程 | Python爬虫:爬取美女图片,看到了意想不到的场景美女图片
  18. python 画椭圆_一篇文章教会你使用SVG ellipse 画椭圆
  19. MySQL不等于判断时,null空值处理问题
  20. JAVA--利用Filter和session防止页面重复提交

热门文章

  1. 十八、Rsync 远程同步数据
  2. 双像立体测图基础与立体测图
  3. fdfs_client
  4. 王菊与周星驰画风迥异跨次元合作
  5. IDEA自定义Generate POJOs.groovy数据表批量生成实体类
  6. 【Numpy金融领域的应用】伽玛分布和贝塔分布随机抽样——以债券违约率与回收率为分析对象
  7. response响应
  8. scrapy-splash java,scrapy-splash简单使用详解
  9. Transformers文本分类微调和TensorRT推理加速
  10. 程序员拥有哪些特质才不会被淘汰?