电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
手把手教你如何实现一个简单的数据加密算法
分 享
扫描二维码分享
手把手教你如何实现一个简单的数据加密算法
C语言
一口Linux
关注
发布时间: 2021-11-30
丨
阅读: 793
## 0. 前言 之前写过一篇关于MD5摘要算法的文章,很多老铁说能否出一篇关于加密的文章吗? 《[C语言实现MD5,竟如此简单!](https://mp.weixin.qq.com/s?__biz=MzUxMjEyNDgyNw==&mid=2247492215&idx=1&sn=ec2f39e7750220855dce51758f6ff0ff&chksm=f96b9083ce1c1995c6443705cf283d25e776dd8b6f3971050f24a1ed3abe049fe8a97d9ee480&scene=21&token=1206659739&lang=zh_CN#wechat_redirect)》 一口君的字典里没有"不行"这两个字!必须安排! 关于加密的一些基本概念,大家可以参考下面这一篇文章: 《[公钥密码学简介](https://mp.weixin.qq.com/s?__biz=MzUxMjEyNDgyNw==&mid=2247498406&idx=1&sn=d344df3eede3fa6c4d14a327da0570a0&chksm=f96b8852ce1c0144ace9bae8fe1426c2c1b8fa83faede3e4bc2d7942bac51cd525e9d64ee646&scene=21&token=1206659739&lang=zh_CN#wechat_redirect)》 本文,一口君带着大家自己实现一个简单但也很实用的加密方法, 让大家了解实际项目开发中数据加密的流程。 ## 一、一种常见的网络通信的加密流程 关于加密的算法很多,实际实现过程千差万别, 下图是一个常见的网络通信加密的应用场景。 密码机的一些说明: * 客户端服务器端都可以设置密码机(可以是软件、也可以是一个硬件,只要能够产生密钥即可) * keygen和同步码都会影响到密码机生成的密钥序列 * 密码机在keygen和同步码相同的情况下,会产生相同的密钥序列,加解密双方需要记住产生密钥的顺序,解密多少数据就申请多少密钥 ![ ](https://img-blog.csdnimg.cn/cce646864df548dba9158f600e9ed1cc.png) 如上图所示,基于C/S架构的服务器和客户端通信模型, 下面以客户端如果要发送一段加密的密文给服务器,C/S需要交互的流程。 ### 1 服务器端发送密钥密文 * 首先服务器端、客户端都保存了一个默认的密钥 * 服务器端随机生成密钥keygen,并使用该默认密钥对keygen加密,生成密钥密文 * 客户端可以通过命令定期请求该密钥密文或者服务器定时下发 * 客户端收到密钥密文后,也可以通过默认密钥进行解密得到明文的keygen ### 2. 客户端对数据加密 * 客户端在发送数据之前,首先生成一个同步码 * 将同步码和keygen设置给密码机,然后向密码机申请一定长度的密钥 * 将明文和密钥通过一定的算法进行加密(通常是异或),生成数据密文 ### 3. 客户端发送同步码和数据密文 * 客户端将数据密文和同步码明文一起发送给服务器 * 服务器提取出同步码 ### 4. 服务器端接收数据并解密 * 服务器将keygen和同步码设置给密码机,同时申请一定数量的密钥 * 服务器根据密钥对密文进行解密,即得到对应的明文 因为服务器和客户端此时都使用了相同的keygen,和同步码,所以双方申请的密钥序列一定是一样的。 ## 二、函数实现 下面是一口君实现的加密算法的一些函数原型以及功能说明,这些函数基本实现了第一节的功能。 ### 1. 申请加密密钥函数request_key ```c int request_key(int sync,int key_num,char key[]) 功能: 向密码机申请一定数量的用于加密数据的密钥,如果不设置新的keygen,那么生成的密码会顺序产生下去,每次申请密钥都会记录上次生成的密钥的偏移,下次在申请的时候,都会从上一位置继续分配密钥 参数: sync:同步码,密码机依据此同步产生随机序列的密钥 key_num:申请的密钥个数 key:申请的密钥存储的缓存 返回值: 实际返回密钥个数 ``` ### 2. 设置密钥序列函数set_keygen ```c void set_keygen(int key) 功能: 向密码机设置keygen,设置后会影响产生的随机密钥序列 参数: key:密钥 返回值: 无 ``` ### 3. 产生随机数born_seed ```c int born_seed(int sync,int key) 功能: 根据同步码和keygen生成随机密钥种子 参数: sync:同步码 key:密钥 返回值: 种子 ``` ### 4. 重置keygen reset_keygen() ```c void reset_keygen() 功能: 重置keygen,会影响生成的随机数序列 ``` ## 三、测试代码实例 最终文件如下: ```c key.c key.h main.c ``` ### 示例1 检测产生的随机序列 ```c int main(int argc, char *argv[]) { int i; unsigned int len; int j, r, key_num; unsigned int sync = 0; unsigned char key[MAX_KEY_REQUEST]; key_num = 10; printf("\n--------------采用默认keygen 同步码=0 产生密文----------------\n"); reset_keygen(); memset(key,0,sizeof(key)); len = request_key(sync,key_num,key); print_array("密钥0-9:",key,len); memset(key,0,sizeof(key)); len = request_key(sync,key_num,key); print_array("密钥10-19:",key,len); printf("\n--------------采用keygen=1234 同步码=0 产生密文----------------\n"); set_keygen(1234); memset(key,0,sizeof(key)); len = request_key(sync,key_num,key); print_array("密钥0-9:",key,len); memset(key,0,sizeof(key)); len = request_key(sync,key_num,key); print_array("密钥10-19:",key,len); } ``` 执行结果: ```c --------------采用默认keygen 同步码=0 产生密文---------------- 密钥0-9: ----[10] a5 52 c8 14 5d f7 46 5b 89 42 密钥10-19: ----[10] 38 69 6f a6 08 d2 69 39 cd 29 --------------采用keygen=1234 同步码=0 产生密文---------------- 密钥0-9: ----[10] 0e 83 0b 73 ec f5 4b 4a 74 35 密钥10-19: ----[10] e7 f1 06 41 c8 6b aa df 0c 3d ``` 可以看到采用不同的keygen产生的随机序列是不一样的。 如果设置不同的同步码,仍然序列还会不一样。 ### 示例2 用默认keygen,加解密 ```c char data0[10]={ 0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0x10, }; int main(int argc, char *argv[]) { int i; unsigned int len; int j, r, key_num; unsigned int sync = 0; unsigned char key[MAX_KEY_REQUEST]; char buf[120]={0}; key_num = 10; printf("\n--------------采用默认keygen开始加密----------------\n"); reset_keygen(); print_array("\n明文:",data0,key_num); memset(key,0,sizeof(key)); len = request_key(sync,key_num,key); print_array("密钥:",key,len); for(i=0;i
\n", argv[0]); exit(EXIT_FAILURE); } sync = atoi(argv[1]); key_num = atoi(argv[2]); mykeygen = atoi(argv[3]); printf("\n--------------采用自定义的keygen、同步码开始加密----------------\n"); set_keygen(mykeygen); print_array("\n明文:",data0,key_num); memset(key,0,sizeof(key)); len = request_key(sync,key_num,key); print_array("密钥:",key,len); for(i=0;i
int rand(void); ``` 函数rand() 虽然可以产生随机序列,但是每次产生的序列其实顺序是一样的。 ```c #include
main() { int i = 0; for(i=0;i<10;i++) { printf("%d ",rand()); } putchar('\n'); } ``` 运行结果如下: ```bash peng@peng-virtual-machine:/mnt/hgfs/peng/rand/code$ ./a.out 1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421 peng@peng-virtual-machine:/mnt/hgfs/peng/rand/code$ ./a.out 1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421 ``` 要想每次都产生不一样的随机序列应该怎么办呢? 需要借助srand()函数 ```c void srand(unsigned int seed); ``` 只需要通过该函数设置一个种子,那么产生的序列,就会完全不一样, 通常我们用time()返回值作为种子, 在此我们随便写入几个数据,来测试下该函数 ```c #include
main() { int i = 0; srand(111); for(i=0;i<10;i++) { printf("%d ",rand()); } putchar('\n'); srand(1111); for(i=0;i<10;i++) { printf("%d ",rand()); } putchar('\n'); } ``` 执行结果如下: ```c peng@peng-virtual-machine:/mnt/hgfs/peng/rand/code$ ./a.out 1629905861 708017477 1225010071 14444113 324837614 2112273117 1166384513 1539134273 1883039818 779189906 1383711924 882432674 1555165704 1334863495 1474679554 676796645 154721979 534868285 1892754119 100411878 ``` 可见输入不同的种子就会产生不同的序列。 函数原型如下: ![](https://img-blog.csdnimg.cn/264a9009ebfc4e648eec8d74bfd3ec95.png) 本例原理比较简单,没有考虑太复杂的应用(比如多路密钥的管理)和数据安全性, 只阐述加解密的流程,仅作为学习理解加解密流程用,此种加密算法属于对称加密,相对比较简单,还是比较容易破解。 目前市场上都是由专业的公司和团队实现加解密功能。 一口君之前曾写过聊天室的一个小项目, 《[从0实现基于Linux socket聊天室](https://mp.weixin.qq.com/s?__biz=MzUxMjEyNDgyNw==&mid=2247487625&idx=1&sn=dc9ac657a9440abade9110d1c0fd92c0&chksm=f968627dce1feb6b03b07f3fbb427f1b3b962f88064f1d04bdcd382b5a9677340a3089d9bb23&scene=21&token=1206659739&lang=zh_CN#wechat_redirect)》 后面一口君会基于该加密机制,将聊天室所有客户端与服务器所有交互数据进行加密处理,请大家持续关注:一口Linux。 本文完整代码下载地址: 链接:https://pan.baidu.com/s/1VvGNlNGEUWWZHQZ1_gYU7A 提取码:o9se 后台回复:数据加密,即可获得全部源码
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
一口Linux
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交