自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

手把手教你如何實現(xiàn)一個簡單的數(shù)據(jù)加解密算法

安全 數(shù)據(jù)安全 算法
密碼機在keygen和同步碼相同的情況下,會產(chǎn)生相同的密鑰序列,加解密雙方需要記住產(chǎn)生密鑰的順序,解密多少數(shù)據(jù)就申請多少密鑰.

本文,一口君帶著大家自己實現(xiàn)一個簡單但也很實用的加密方法,

讓大家了解實際項目開發(fā)中數(shù)據(jù)加密的流程。

一、一種常見的網(wǎng)絡(luò)通信的加密流程

關(guān)于加密的算法很多,實際實現(xiàn)過程千差萬別,

下圖是一個常見的網(wǎng)絡(luò)通信加密的應(yīng)用場景。

密碼機的一些說明:

  • 客戶端服務(wù)器端都可以設(shè)置密碼機(可以是軟件、也可以是一個硬件,可以在本地也可以在某個服務(wù)器上,只要能夠產(chǎn)生密鑰即可)
  • keygen和同步碼都會影響到密碼機生成的密鑰序列
  • 密碼機在keygen和同步碼相同的情況下,會產(chǎn)生相同的密鑰序列,加解密雙方需要記住產(chǎn)生密鑰的順序,解密多少數(shù)據(jù)就申請多少密鑰

 

如上圖所示,基于C/S架構(gòu)的服務(wù)器和客戶端通信模型,

下面以客戶端如果要發(fā)送一段加密的密文給服務(wù)器,C/S需要交互的流程。

1 服務(wù)器端發(fā)送密鑰密文

首先服務(wù)器端、客戶端都保存了一個默認的密鑰

服務(wù)器端隨機生成密鑰keygen,并使用該默認密鑰對keygen加密,生成密鑰密文

客戶端可以通過命令定期請求該密鑰密文或者服務(wù)器定時下發(fā)

客戶端收到密鑰密文后,也可以通過默認密鑰進行解密得到明文的keygen

2. 客戶端對數(shù)據(jù)加密

客戶端在發(fā)送數(shù)據(jù)之前,首先生成一個同步碼

將同步碼和keygen設(shè)置給密碼機,然后向密碼機申請一定長度的密鑰

將明文和密鑰通過一定的算法進行加密(通常是異或),生成數(shù)據(jù)密文

3. 客戶端發(fā)送同步碼和數(shù)據(jù)密文

客戶端將數(shù)據(jù)密文和同步碼明文一起發(fā)送給服務(wù)器

服務(wù)器提取出同步碼

4. 服務(wù)器端接收數(shù)據(jù)并解密

服務(wù)器將keygen和同步碼設(shè)置給密碼機,同時申請一定數(shù)量的密鑰

服務(wù)器根據(jù)密鑰對密文進行解密,即得到對應(yīng)的明文

因為服務(wù)器和客戶端此時都使用了相同的keygen,和同步碼,所以雙方申請的密鑰序列一定是一樣的。

二、函數(shù)實現(xiàn)

下面是一口君實現(xiàn)的加密算法的一些函數(shù)原型以及功能說明,這些函數(shù)基本實現(xiàn)了第一節(jié)的功能。

1. 申請加密密鑰函數(shù)request_key

  1. int request_key(int sync,int key_num,char key[]) 
  2. 功能: 
  3.  向密碼機申請一定數(shù)量的用于加密數(shù)據(jù)的密鑰,如果不設(shè)置新的keygen,那么生成的密碼會順序產(chǎn)生下去,每次申請密鑰都會記錄上次生成的密鑰的偏移,下次在申請的時候,都會從上一位置繼續(xù)分配密鑰 
  4. 參數(shù): 
  5.  sync:同步碼,密碼機依據(jù)此同步產(chǎn)生隨機序列的密鑰 
  6.  key_num:申請的密鑰個數(shù) 
  7.  key:申請的密鑰存儲的緩存 
  8. 返回值: 
  9.  實際返回密鑰個數(shù) 

2. 設(shè)置密鑰序列函數(shù)set_keygen

  1. void set_keygen(int key
  2. 功能: 
  3.  向密碼機設(shè)置keygen,設(shè)置后會影響產(chǎn)生的隨機密鑰序列 
  4. 參數(shù): 
  5.  key:密鑰 
  6. 返回值: 
  7.  無 

3. 產(chǎn)生隨機數(shù)born_seed

  1. int born_seed(int sync,int key
  2. 功能: 
  3.  根據(jù)同步碼和keygen生成隨機密鑰種子 
  4. 參數(shù): 
  5.     sync:同步碼  
  6.  key:密鑰 
  7. 返回值: 
  8.  種子 

4. 重置keygen reset_keygen()

  1. void reset_keygen() 
  2. 功能: 
  3.  重置keygen,會影響生成的隨機數(shù)序列 

三、測試代碼實例

最終文件如下:

  1. key.c key.h main.c 

示例1 檢測產(chǎn)生的隨機序列

  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 產(chǎn)生密文----------------\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 產(chǎn)生密文----------------\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); 

執(zhí)行結(jié)果:

  1. --------------采用默認keygen 同步碼=0 產(chǎn)生密文---------------- 
  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 產(chǎn)生密文---------------- 
  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產(chǎn)生的隨機序列是不一樣的。

如果設(shè)置不同的同步碼,仍然序列還會不一樣。

示例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); 

測試結(jié)果

  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); 

執(zhí)行結(jié)果如下:

  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  

可見我們的確實現(xiàn)了數(shù)據(jù)的加密和解密。

四、數(shù)據(jù)加密的實際使用

假定我們使用上述實例代碼,把對應(yīng)的功能移植到C/S兩端,

那么一次完整的數(shù)據(jù)加密以及數(shù)據(jù)的傳輸參考流程如下:

記住一點,只要雙方設(shè)置相同的keygen和同步碼,那么密碼機吐出來的密鑰就是相同序列,

客戶端發(fā)送每發(fā)送一個報文,就把自己的明文同步碼一起發(fā)送給服務(wù)器,

服務(wù)器根據(jù)提前發(fā)送給客戶端的keygen和同步碼就可以實現(xiàn)解密操作,

雖然你可以看到明文的同步碼,

但是還需要破解密碼機算法、服務(wù)器下發(fā)的keygen密文。

五、 原理

實現(xiàn)加密算法的主要問題是如何產(chǎn)生隨機序列作為密鑰。

本例是借用庫函數(shù)rand() 原型如下:

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

函數(shù)rand() 雖然可以產(chǎn)生隨機序列,但是每次產(chǎn)生的序列其實順序是一樣的。

  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'); 

運行結(jié)果如下:

  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  

要想每次都產(chǎn)生不一樣的隨機序列應(yīng)該怎么辦呢?需要借助srand()函數(shù)

  1. void srand(unsigned int seed); 

只需要通過該函數(shù)設(shè)置一個種子,那么產(chǎn)生的序列,就會完全不一樣,

通常我們用time()返回值作為種子,

在此我們隨便寫入幾個數(shù)據(jù),來測試下該函數(shù)

  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'); 

執(zhí)行結(jié)果如下:

  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  

可見輸入不同的種子就會產(chǎn)生不同的序列。

函數(shù)原型如下:

圖片本例原理比較簡單,沒有考慮太復(fù)雜的應(yīng)用(比如多路密鑰的管理)和數(shù)據(jù)安全性,

只闡述加解密的流程,僅作為學(xué)習(xí)理解加解密流程用,此種加密算法屬于對稱加密,相對比較簡單,還是比較容易破解。

目前市場上都是由專業(yè)的公司和團隊實現(xiàn)加解密功能。

本文轉(zhuǎn)載自微信公眾號「一口Linux」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系一口Linux公眾號。

 

責(zé)任編輯:武曉燕 來源: 一口Linux
相關(guān)推薦

2022-06-28 15:29:56

Python編程語言計時器

2022-09-22 12:38:46

antd form組件代碼

2021-06-22 10:43:03

Webpack loader plugin

2023-04-26 12:46:43

DockerSpringKubernetes

2011-04-21 10:32:44

MySQL雙機同步

2019-08-26 09:25:23

RedisJavaLinux

2022-07-27 08:16:22

搜索引擎Lucene

2022-12-07 08:42:35

2016-10-25 14:54:37

2021-12-11 20:20:19

Python算法線性

2020-12-02 12:29:24

Vue無限級聯(lián)樹形

2020-12-15 08:58:07

Vue編輯器vue-cli

2009-11-09 14:57:37

WCF上傳文件

2011-01-06 10:39:25

.NET程序打包

2011-10-06 14:32:43

2015-07-15 13:18:27

附近的人開發(fā)

2018-11-22 09:17:21

消息推送系統(tǒng)

2022-08-26 08:01:38

DashWebJavaScrip

2016-11-01 09:46:04

2021-08-31 10:02:10

KubernetesLinux集群
點贊
收藏

51CTO技術(shù)棧公眾號