手把手教你如何实现一个简单的数据加解密算法

本文,一口君带着大家自己实现一个简单但也很实用的加密方法,

让大家了解实际项目开发中数据加密的流程。

一、一种常见的网络通信的加密流程

关于加密的算法很多,实际实现过程千差万别,

下图是一个常见的网络通信加密的应用场景。

密码机的一些说明:

  • 客户端服务器端都可以设置密码机(可以是软件、也可以是一个硬件,可以在本地也可以在某个服务器上,只要能够产生密钥即可)
  • keygen和同步码都会影响到密码机生成的密钥序列
  • 密码机在keygen和同步码相同的情况下,会产生相同的密钥序列,加解密双方需要记住产生密钥的顺序,解密多少数据就申请多少密钥

 

如上图所示,基于C/S架构的服务器和客户端通信模型,

下面以客户端如果要发送一段加密的密文给服务器,C/S需要交互的流程。

1 服务器端发送密钥密文

首先服务器端、客户端都保存了一个默认的密钥

服务器端随机生成密钥keygen,并使用该默认密钥对keygen加密,生成密钥密文

客户端可以通过命令定期请求该密钥密文或者服务器定时下发

客户端收到密钥密文后,也可以通过默认密钥进行解密得到明文的keygen

2. 客户端对数据加密

客户端在发送数据之前,首先生成一个同步码

将同步码和keygen设置给密码机,然后向密码机申请一定长度的密钥

将明文和密钥通过一定的算法进行加密(通常是异或),生成数据密文

3. 客户端发送同步码和数据密文

客户端将数据密文和同步码明文一起发送给服务器

服务器提取出同步码

4. 服务器端接收数据并解密

服务器将keygen和同步码设置给密码机,同时申请一定数量的密钥

服务器根据密钥对密文进行解密,即得到对应的明文

因为服务器和客户端此时都使用了相同的keygen,和同步码,所以双方申请的密钥序列一定是一样的。

二、函数实现

下面是一口君实现的加密算法的一些函数原型以及功能说明,这些函数基本实现了第一节的功能。

1. 申请加密密钥函数request_key

  1. int request_key(int sync,int key_num,char key[]) 
  2. 功能: 
  3.  向密码机申请一定数量的用于加密数据的密钥,如果不设置新的keygen,那么生成的密码会顺序产生下去,每次申请密钥都会记录上次生成的密钥的偏移,下次在申请的时候,都会从上一位置继续分配密钥 
  4. 参数: 
  5.  sync:同步码,密码机依据此同步产生随机序列的密钥 
  6.  key_num:申请的密钥个数 
  7.  key:申请的密钥存储的缓存 
  8. 返回值: 
  9.  实际返回密钥个数 

2. 设置密钥序列函数set_keygen

  1. void set_keygen(int key
  2. 功能: 
  3.  向密码机设置keygen,设置后会影响产生的随机密钥序列 
  4. 参数: 
  5.  key:密钥 
  6. 返回值: 
  7.  无 

3. 产生随机数born_seed

  1. int born_seed(int sync,int key
  2. 功能: 
  3.  根据同步码和keygen生成随机密钥种子 
  4. 参数: 
  5.     sync:同步码  
  6.  key:密钥 
  7. 返回值: 
  8.  种子 

4. 重置keygen reset_keygen()

  1. void reset_keygen() 
  2. 功能: 
  3.  重置keygen,会影响生成的随机数序列 

三、测试代码实例

最终文件如下:

  1. key.c key.h main.c 

示例1 检测产生的随机序列

  1. int main(int argc, char *argv[]) 
  2.  int i; 
  3.  unsigned int len; 
  4.  int j, r, key_num; 
  5.  unsigned int sync = 0; 
  6.  unsigned char key[MAX_KEY_REQUEST]; 
  7.  
  8.  
  9.  key_num = 10; 
  10.  
  11.  printf("\n--------------采用默认keygen 同步码=0 产生密文----------------\n"); 
  12.  reset_keygen(); 
  13.  
  14.  memset(key,0,sizeof(key)); 
  15.  len = request_key(sync,key_num,key); 
  16.  
  17.  print_array("密钥0-9:",key,len); 
  18.  
  19.  memset(key,0,sizeof(key)); 
  20.  len = request_key(sync,key_num,key); 
  21.  
  22.  print_array("密钥10-19:",key,len); 
  23.  
  24.  printf("\n--------------采用keygen=1234 同步码=0 产生密文----------------\n"); 
  25.  set_keygen(1234); 
  26.  
  27.  memset(key,0,sizeof(key)); 
  28.  len = request_key(sync,key_num,key); 
  29.  
  30.  print_array("密钥0-9:",key,len); 
  31.  
  32.  memset(key,0,sizeof(key)); 
  33.  len = request_key(sync,key_num,key); 
  34.  
  35.  print_array("密钥10-19:",key,len); 

执行结果:

  1. --------------采用默认keygen 同步码=0 产生密文---------------- 
  2. 密钥0-9: ----[10] 
  3. a5 52 c8 14 5d f7 46 5b 89 42  
  4. 密钥10-19: ----[10] 
  5. 38 69 6f a6 08 d2 69 39 cd 29  
  6.  
  7. --------------采用keygen=1234 同步码=0 产生密文---------------- 
  8. 密钥0-9: ----[10] 
  9. 0e 83 0b 73 ec f5 4b 4a 74 35  
  10. 密钥10-19: ----[10] 
  11. e7 f1 06 41 c8 6b aa df 0c 3d  

可以看到采用不同的keygen产生的随机序列是不一样的。

如果设置不同的同步码,仍然序列还会不一样。

示例2 用默认keygen,加解密

  1. char data0[10]={ 
  2.  0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0x10, 
  3. }; 
  4. int main(int argc, char *argv[]) 
  5.  int i; 
  6.  unsigned int len; 
  7.  int j, r, key_num; 
  8.  unsigned int sync = 0; 
  9.  unsigned char key[MAX_KEY_REQUEST]; 
  10.  char buf[120]={0}; 
  11.  
  12.  key_num = 10; 
  13.  printf("\n--------------采用默认keygen开始加密----------------\n"); 
  14.  reset_keygen(); 
  15.  print_array("\n明文:",data0,key_num); 
  16.  
  17.  memset(key,0,sizeof(key)); 
  18.  len = request_key(sync,key_num,key); 
  19.  
  20.  print_array("密钥:",key,len); 
  21.  for(i=0;i<len;i++) 
  22.  { 
  23.   buf[i] = data0[i]^key[i]; 
  24.  } 
  25.  print_array("\n密文:",buf,len); 
  26.   
  27.  printf("\n--------------------开始解密--------------------\n"); 
  28.  reset_keygen(); 
  29.  
  30.  memset(key,0,sizeof(key)); 
  31.  len = request_key(sync,key_num,key); 
  32.  
  33.   
  34.  for(i=0;i<len;i++) 
  35.  { 
  36.   buf[i] = buf[i]^key[i]; 
  37.  } 
  38.  
  39.  print_array("\n明文:",buf,len); 

测试结果

  1. --------------采用默认keygen开始加密---------------- 
  2.  
  3. 明文: ----[10] 
  4. 01 02 03 04 05 06 07 08 09 10  
  5. 密钥: ----[10] 
  6. a5 52 c8 14 5d f7 46 5b 89 42  
  7.  
  8. 密文: ----[10] 
  9. a4 50 cb 10 58 f1 41 53 80 52  
  10.  
  11. --------------------开始解密-------------------- 
  12.  
  13. 明文: ----[10] 
  14. 01 02 03 04 05 06 07 08 09 10  

示例3 用不同的keygen和同步码加解密

  1. int main(int argc, char *argv[]) 
  2.  int i; 
  3.  unsigned int len; 
  4.  int j, r, key_num; 
  5.  unsigned int sync = 0; 
  6.  unsigned char key[MAX_KEY_REQUEST]; 
  7.  char buf[120]={0}; 
  8.  unsigned int mykeygen; 
  9.  
  10.  
  11.  if (argc != 4) { 
  12.   fprintf(stderr, "Usage: %s <seed> <key num> <keygen>\n", argv[0]); 
  13.   exit(EXIT_FAILURE); 
  14.  } 
  15.  
  16.  sync = atoi(argv[1]); 
  17.  key_num = atoi(argv[2]); 
  18.  mykeygen = atoi(argv[3]); 
  19.  
  20.  printf("\n--------------采用自定义的keygen、同步码开始加密----------------\n"); 
  21.  set_keygen(mykeygen); 
  22.  print_array("\n明文:",data0,key_num); 
  23.  
  24.  memset(key,0,sizeof(key)); 
  25.  len = request_key(sync,key_num,key); 
  26.  print_array("密钥:",key,len); 
  27.  
  28.  for(i=0;i<len;i++) 
  29.  { 
  30.   buf[i] = data0[i]^key[i]; 
  31.  } 
  32.  print_array("\n密文:",buf,len); 
  33.   
  34.  
  35.  printf("\n--------------------开始解密--------------------\n"); 
  36.  set_keygen(mykeygen); 
  37.  
  38.  memset(key,0,sizeof(key)); 
  39.  len = request_key(sync,key_num,key); 
  40.  for(i=0;i<len;i++) 
  41.  { 
  42.   buf[i] = buf[i]^key[i]; 
  43.  } 
  44.  print_array("\n明文:",buf,len); 
  45.  exit(EXIT_SUCCESS); 

执行结果如下:

  1. --------------采用自定义的keygen、同步码开始加密---------------- 
  2.  
  3. 明文: ----[10] 
  4. 01 02 03 04 05 06 07 08 09 10  
  5. 密钥: ----[10] 
  6. 53 00 29 cd 27 eb cc 80 1a d7  
  7.  
  8. 密文: ----[10] 
  9. 52 02 2a c9 22 ed cb 88 13 c7  
  10.  
  11. --------------------开始解密-------------------- 
  12.  
  13. 明文: ----[10] 
  14. 01 02 03 04 05 06 07 08 09 10  

可见我们的确实现了数据的加密和解密。

四、数据加密的实际使用

假定我们使用上述实例代码,把对应的功能移植到C/S两端,

那么一次完整的数据加密以及数据的传输参考流程如下:

记住一点,只要双方设置相同的keygen和同步码,那么密码机吐出来的密钥就是相同序列,

客户端发送每发送一个报文,就把自己的明文同步码一起发送给服务器,

服务器根据提前发送给客户端的keygen和同步码就可以实现解密操作,

虽然你可以看到明文的同步码,

但是还需要破解密码机算法、服务器下发的keygen密文。

五、 原理

实现加密算法的主要问题是如何产生随机序列作为密钥。

本例是借用库函数rand() 原型如下:

  1. #include 
  2.  
  3. int rand(void); 

函数rand() 虽然可以产生随机序列,但是每次产生的序列其实顺序是一样的。

  1. #include <stdio.h> 
  2.  
  3. main() 
  4.  int i = 0; 
  5.  
  6.  for(i=0;i<10;i++) 
  7.  { 
  8.   printf("%d ",rand()); 
  9.  } 
  10.  putchar('\n'); 

运行结果如下:

  1. peng@peng-virtual-machine:/mnt/hgfs/peng/rand/code$ ./a.out  
  2. 1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421  
  3. peng@peng-virtual-machine:/mnt/hgfs/peng/rand/code$ ./a.out  
  4. 1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421  

要想每次都产生不一样的随机序列应该怎么办呢?需要借助srand()函数

  1. void srand(unsigned int seed); 

只需要通过该函数设置一个种子,那么产生的序列,就会完全不一样,

通常我们用time()返回值作为种子,

在此我们随便写入几个数据,来测试下该函数

  1. #include <stdio.h> 
  2.  
  3. main() 
  4.  int i = 0; 
  5.  
  6.  srand(111); 
  7.  for(i=0;i<10;i++) 
  8.  { 
  9.   printf("%d ",rand()); 
  10.  } 
  11.  putchar('\n'); 
  12.  srand(1111); 
  13.  for(i=0;i<10;i++) 
  14.  { 
  15.   printf("%d ",rand()); 
  16.  } 
  17.  putchar('\n'); 

执行结果如下:

  1. peng@peng-virtual-machine:/mnt/hgfs/peng/rand/code$ ./a.out  
  2. 1629905861 708017477 1225010071 14444113 324837614 2112273117 1166384513 1539134273 1883039818 779189906  
  3. 1383711924 882432674 1555165704 1334863495 1474679554 676796645 154721979 534868285 1892754119 100411878  

可见输入不同的种子就会产生不同的序列。

函数原型如下:

图片本例原理比较简单,没有考虑太复杂的应用(比如多路密钥的管理)和数据安全性,

只阐述加解密的流程,仅作为学习理解加解密流程用,此种加密算法属于对称加密,相对比较简单,还是比较容易破解。

目前市场上都是由专业的公司和团队实现加解密功能。

本文转载自微信公众号「一口Linux」,可以通过以下二维码关注。转载本文请联系一口Linux公众号。

 

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/130992.html<

(0)
运维的头像运维
上一篇2025-02-26 08:19
下一篇 2025-02-26 08:20

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注