对称加密算法之RC4介绍及OpenSSL中RC4常用函数使用举例

2023-10-26

RC4是一种对称密码算法,它属于对称密码算法中的序列密码(streamcipher,也称为流密码),它是可变密钥长度,面向字节操作的流密码

RC4是流密码streamcipher中的一种,为序列密码。RC4加密算法是Ron Rivest在1987年设计出的密钥长度可变的加密算法簇。起初该算法是商业机密,直到1994年,它才公诸于众。由于RC4具有算法简单,运算速度快,软硬件实现都十分容易等优点,使其在一些协议和标准里得到了广泛应用。

流密码也属于对称密码,但与分组加密算法不同的是,流密码不对明文数据进行分组,而是用密钥生成与明文一样长短的密码流对明文进行加密,加解密使用相同的密钥

RC4算法特点:(1)、算法简洁易于软件实现,加密速度快,安全性比较高;(2)、密钥长度可变,一般用256个字节。

         对称密码的工作方式有四种:电子密码本(ECB, electronic codebook)方式、密码分组链接(CBC, cipherblock chaining)方式、密文反馈(CFB, cipher-feedback)方式、输出反馈(OFB, output-feedback)方式。

         RC4算法采用的是输出反馈工作方式,所以可以用一个短的密钥产生一个相对较长的密钥序列

         OFB方式的最大的优点是消息如果发生错误(这里指的是消息的某一位发生了改变,而不是消息的某一位丢失),错误不会传递到产生的密钥序列上;缺点是对插入攻击很敏感,并且对同步的要求比较高。

         RC4的执行速度相当快,它大约是分块密码算法DES的5倍,是3DES的15倍,且比高级加密算法AES也快很多。RC4算法简单,实现容易。RC4的安全保证主要在于输入密钥的产生途径,只要在这方面不出现漏洞,采用128bit的密钥是非常安全的。

         RC4算法加密流程:包括密钥调度算法KSA和伪随机子密码生成算法PRGA两大部分(以密钥长度为256个字节为例)。

         密钥调度算法:首先初始化状态矢量S,矢量S中元素的值被按升序从0到255排列,即S[0]=00, S[1]=1, …, S[255]=255.同时建立一个临时矢量T,如果密钥K的长度为256字节,则将K赋给T。否则,若密钥长度为keylen字节,则将K的值赋给T的前keylen个元素,并循环重复用K的值赋给T剩下的元素,直到T的所有元素都被赋值。这些预操作可概括如下:

         /*初始化*/

         fori = 0 to 255 do

                   S[i]= i;

                   T[i]= K[i mod keylen];

         然后用T产生S的初始置换,从S[0]到S[255],对每个S[i],根据由T[i]确定的方案,将S[i]置换为S中的另一字节:

         /*S的初始序列*/

         j= 0

         fori = 0 to 255 do

                   j= (j + S[i] + T[i]) mod 256

                   swap(S[i],S[j]);

         因为对S的操作仅是交换,所以惟一的改变就是顺序的改变。S仍然包含从0到255的所有元素,在初始化的过程中,密钥的主要功能是将S-box搅乱,代码中的变量i确保S-box的每个元素都得到处理,变量j保证S-box的搅乱是随机的。因此不同的S-box在经过伪随机子密码生成算法的处理后可以得到不同的子密钥序列,并且该序列是随机的。

         伪随机序列生成算法:矢量S一旦完成初始化,输入密钥就不再被使用。密钥流的生成是从S[0]到S[255],对每个S[i],根据当前S的值,将S[i]与S中的另一字节置换。当S[255]完成置换后,操作继续重复,从S[0]开始:

         /*密钥流的产生*/

         i,j = 0;

         while(true)

                   i= (i + 1) mod 256;

                   j= (j + S[i]) mod 256;

                   swap(S[i],S[j]);

                   t= (S[i] + s[j]) mod 256;

                   k= S[t]

         伪随机序列一旦生成,就得到子密码sub_k,把子密钥和明文进行异或运算,得到密文。解密过程也完全相同。加密中,只需将k的值与下一明文字节异或;相反解密中,将k的值与下一密文字节异或就可以还原出明文信息。算法描述为:

         for(i = 0; i < textlength; i ++)

                   ciphertext[i]= keystream[i] ^ plaintext[i]

         RC4算法存在的问题:因为RC4算法具有实现简单,加密速度快,对硬件资源耗费低等优点,使其跻身于轻量级加密算法的行列。但是其简单的算法结构也容易遭到破解攻击,RC4算法的加密强度完全取决于密钥,即伪随机序列生成,而真正的随机序列是不可能实现,只能实现伪随机。这就不可避免出现密钥的重复。RC4算法不管是加密还是解密,都只进行了异或运算,这就意味着,一旦子密钥序列出现了重复,密文就极有可能被破解。

         具体破解过程如下:若明文、密钥是任意长的字节,可以用重合码计数法(counting coincidence)找出密钥长度。把密文进行各种字节的位移,并与原密文进行异或运算,统计那些相同的字节。如果位移是密钥长度的倍数,那么超过60%的字节将是相同的;如果不是,则至多只有0.4%的字节是相同的,这叫做重合指数(index of coincidence)。找出密钥长度倍数的最小位移,按此长度移到密文,并且和自身异或。由于明文每字节有1.3位的实际信息,因此有足够的冗余度去确定位移的解密。对所有的密钥,输出密钥流的前几个字节不是随机的,因此极有可能会泄露密钥的信息。如果一个长期使用的密钥与一个随机数串联产生RC4算法密钥,那么可以通过分析大量由该密钥加密的密文得到这个长期使用的密钥。解决该问题的办法是:抛弃密钥流最初的那部分数据。

         RC4is a stream cipher with variable key length. Typically, 128 bit (16 byte) keys are used for strong encryption, butshorter insecure key sizes have been widely used due to export restrictions.

1.      RC4_set_key:sets up theB<RC4_KEY> B<key> using the B<len> bytes long key atB<data>.

2.      RC4: encrypts or decrypts the B<len>bytes of data at B<indata> using B<key> and places the result atB<outdata>.  Repeated RC4() callswith the same B<key> yield a continuous key stream. Since RC4 is a streamcipher (the input is XORed with a pseudo-random key stream to produce theoutput), decryption uses the same function calls as encryption.

以下是测试代码:

cryptotest.h:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifndef _CRYPTOTEST_H_  
  2. #define _CRYPTOTEST_H_  
  3.   
  4. #include <string>  
  5.   
  6. using namespace std;  
  7.   
  8. typedef enum {  
  9.     GENERAL = 0,  
  10.     ECB,  
  11.     CBC,  
  12.     CFB,  
  13.     OFB,  
  14.     TRIPLE_ECB,  
  15.     TRIPLE_CBC  
  16. }CRYPTO_MODE;  
  17.   
  18. string DES_Encrypt(const string cleartext, const string key, CRYPTO_MODE mode);  
  19. string DES_Decrypt(const string ciphertext, const string key, CRYPTO_MODE mode);  
  20.   
  21. string RC4_Encrypt(const string cleartext, const string key);  
  22. string RC4_Decrypt(const string ciphertext, const string key);  
  23.   
  24. #endif //_CRYPTOTEST_H_  

rc4test.cpp:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. #include <string>  
  4. #include <vector>  
  5. #include <openssl/rc4.h>  
  6. #include "cryptotest.h"  
  7.   
  8. using namespace std;  
  9.   
  10. string RC4_Encrypt(const string cleartext, const string key)  
  11. {  
  12.     RC4_KEY rc4key;  
  13.     unsigned char* tmp = new unsigned char[cleartext.length() + 1];  
  14.     memset(tmp, 0, cleartext.length() + 1);  
  15.   
  16.     RC4_set_key(&rc4key, key.length(), (const unsigned char*)key.c_str());  
  17.     RC4(&rc4key, cleartext.length(), (const unsigned char*)cleartext.c_str(), tmp);  
  18.   
  19.     string str = (char*)tmp;  
  20.   
  21.     delete [] tmp;  
  22.   
  23.     return str;  
  24. }  
  25.   
  26. string RC4_Decrypt(const string ciphertext, const string key)  
  27. {  
  28.     RC4_KEY rc4key;  
  29.     unsigned char* tmp = new unsigned char[ciphertext.length() + 1];  
  30.     memset(tmp, 0, ciphertext.length() + 1);  
  31.   
  32.     RC4_set_key(&rc4key, key.length(), (const unsigned char*)key.c_str());  
  33.     RC4(&rc4key, ciphertext.length(), (const unsigned char*)ciphertext.c_str(), tmp);  
  34.   
  35.     string str = (char*)tmp;  
  36.   
  37.     delete [] tmp;  
  38.   
  39.     return str;  
  40. }  

main.cpp:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include "stdafx.h"  
  2. #include "cryptotest.h"  
  3. #include "TestMemory.h"  
  4. #include <iostream>  
  5. #include <string>  
  6.   
  7. using namespace std;  
  8.   
  9. void test_RC4()  
  10. {  
  11.     string cleartext = "中国北京12345$abcde%ABCDE@!!!";  
  12.     string ciphertext = "";  
  13.     string key = "beijingchina1234567890ABCDEFGH!!!";  
  14.   
  15.     ciphertext = RC4_Encrypt(cleartext, key);  
  16.     string decrypt = RC4_Decrypt(ciphertext, key);  
  17.   
  18.     cout<<"src cleartext: "<<cleartext<<endl;  
  19.     cout<<"genarate ciphertext: "<<ciphertext<<endl;  
  20.     cout<<"src ciphertext: "<<ciphertext<<endl;  
  21.     cout<<"genarate cleartext: "<<decrypt<<endl;  
  22.   
  23.     if (strcmp(cleartext.c_str(), decrypt.c_str()) == 0)  
  24.         cout<<"RC4 crypto ok!!!"<<endl;  
  25.     else  
  26.         cout<<"RC4 crypto error!!!"<<endl;  
  27. }  

RC4理论摘自:《RFID中轻量级加密算法及实现技术的研究》

http://blog.csdn.net/fengbingchun/article/details/42929883


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对称加密算法之RC4介绍及OpenSSL中RC4常用函数使用举例 的相关文章

  • js——网址动态拼接参数

    案例 你可以使用字符串拼接的方式来动态拼接参数到网址上 在这种情况下 你可以使用加号运算符来连接字符串 并使用变量来表示参数的值 下面是一个示例代码 let aaa http www baidu com let xxx 1 let yyy

随机推荐

  • 对于一个采用字符数组存放的字符串str,设计一个递归算法StrLength(char *str)求其字符个数(长度)。递归求字符串长度

    递归求字符串长度 需要的就是将数组看成指针 一步一步走下去 int StrLength char str char p str if p 0 return 0 else return StrLength p 1 努力加油a啊 o
  • 走出软件作坊

    这本书 对于小开发者真的是实用手册 关于如何与老板相处 如何做人 如何做技术 对于在小企业工作的人来说 真的不错 2014 7 11
  • c#自定义消息事件

    自定义消息 public class CustomEventArgs EventArgs public readonly string msg public CustomEventArgs string msg this msg msg 自
  • 设计模式之桥接模式(Bridge模式)

    一 模式动机 设想如果要绘制矩形 圆形 椭圆 正方形 我们至少需要4个形状类 但是如果绘制的图形需要具有不同的颜色 如红色 绿色 蓝色等 此时至少有如下两种设计方案 第一种设计方案是为每一种形状都提供一套各种颜色的版本 第二种设计方案是根据
  • 云服务器搭建神器JupyterLab(多图)

    云服务器搭建神器JupyterLab 多图 JupyterLab是一个交互式的开发环境 其用于应对包含着notebook 代码以及数据的工作场景 1 前言 如果说vim是编辑器之神 那么JupyterLab就是笔记本之神 从2017年开始我
  • 极端天气下的目标检测与测距算法

    更多视觉额自动驾驶项目请见 小白学视觉 自动驾驶项目 本文主要工作 科技的发展与进步促使自动驾驶车辆逐渐成为全球汽车产业发展的重要战略 方向 但自动驾驶车辆面对如 大雨 大雾 大雪等极端环境时 智能汽车图像 采集与处理系统将面临巨大挑战 并
  • 基于Python的socket库实现通信功能

    目录 1 前言 2 技术介绍 1 socket 2 Python的socket库 3 系统实现 1 服务端 server py 2 客户端1 client1 py 3 客户端2 client2 py 4 系统功能演示 1 启动服务端和客户端
  • idea配置maven教程

    1 下载maven 下载地址 官网地址点击进入 2 配置环境变量 解压到自己想要放置的路径后 配置系统用户的环境变量 新增系统变量 MAVEN HOME C Program Files JetBrains apache maven 3 8
  • 二维码 ThoughtWorks.QRCode 之 index was outside bounds of the array

    最近在使用ThoughtWorks QRCode过程中 单独生成一个二维码没有出现过问题 在重复利用QRCodeEncoder生成二维码的过程中 会出现index was outside bounds of the array错误 经过调试
  • JS 作用域

    var和let的比较 var是老版JavaScript中定义变量的标识符 let是新版JavaScript中定义变量的标识符 let的出现是为了解决var定义变量的一些遗留问题而推出的 在同一个作用域下 var允许重复声明 let不允许重复
  • SpringBoot整合Minio

    1 引入依赖 POM文件如下
  • 【Linux虚拟机】VirtualBox搭建linux虚拟机

    Linux从虚拟机创建到程序运行 ubuntu版 实际工作中 总是需要开发环境 测试环境和生产环境 但是很多小伙伴是没有这么多可供使用的服务器的 尤其是学习使用阶段 可能因为不熟悉服务器的配置 重复的重启 安装 卸载等 我们需要有自己可以随
  • 聊天相关表结构及业务逻辑

    表结构 CREATE TABLE t chat record id bigint 20 NOT NULL send user id bigint 20 DEFAULT NULL COMMENT 发送人 receive user id big
  • mysql视图的应用场景_MySQL视图适用于哪些场景?

    MySQL视图适用于哪些场景 答 1 视图能简化用户操作 视图机制使用户可以将注意力集中在所关心的数据上 如果这些数据不是直接来自基本表 则可以通过定义视图 使数据库看起来结构简单 清晰 并且可以简化用户的数据查询操作 例如 那些定义了若干
  • 服务器virsh不显示虚机,KVM之virsh常用命令

    沙发 1121644742 Post 2016 04 19 下午5 40 help 打印帮助 attach device 从一个XML文件附加装置 attach disk 附加磁盘设备 attach interface 获得网络界面 aut
  • Java创建student类

    目录 创建包 包名可以自拟 在包中创建student类 创建Penpal类继承student类 在HelloWorld中实现测试 创建一个叫做Student的类 对象属性 姓名 年龄 性别 身高 对象方法 说话 计算加法 年龄长一岁 类属性
  • 数据库应用:Mycat+HAProxy+Keepalived实现高可用

    目录 一 理论 1 高可用 2 部署高可用 二 实验 1 Mycat HAProxy Keepalived实现高可用 三 问题 1 开启HA Proxy失败 2 VMware 克隆linux 网卡UUID重复问题 3 keepalived状
  • 从零开始搭建Kafka集群遇到的问题

    文章目录 安装kafka 下载kafka 2 12 3 1 0 tgz 使用Xshell将文件传入虚拟机 解压 启动kafka 使用kakfa自带的zookeeper 修改kafka配置 启动kafka 使用kafka 创建主题 查看主题
  • 考试系统服务器考试机,网络考试系统——服务器考试管理系统

    内容介绍 原文档由会员 快乐浪子 发布 网络考试系统 服务器考试管理系统 内容丰富 建议下载阅览 页数 32 字数 12157 摘要 在网络技术逐渐渗入社会生活各个层面的今天 传统的考试方式也面临着变革 而网络考试则是一个很重要的方向 基于
  • 对称加密算法之RC4介绍及OpenSSL中RC4常用函数使用举例

    RC4是一种对称密码算法 它属于对称密码算法中的序列密码 streamcipher 也称为流密码 它是可变密钥长度 面向字节操作的流密码 RC4是流密码streamcipher中的一种 为序列密码 RC4加密算法是Ron Rivest在19