1. 程式人生 > 其它 >密碼引擎的設計與實現

密碼引擎的設計與實現

實驗一 密碼引擎-0-OpenEuler ECS構建

登入自己的華為雲賬號,參考附件圖示,構建基於鯤鵬和OpenEuler的ECS。

登入進OpenEuler系統,熟悉系統使用,注意OpenEuler安裝工具使用sudo yum install ...

登入進OpenEuler系統,提交執行who命令的截圖

加分項:使用yum install 安裝C程式設計工具,以及自己的常用工具,提交安裝後測試使用的截圖。
構建基於鯤鵬和OpenEuler的ECS可參考華為雲服務購買及基礎實驗,記得照著下圖修改
登入進OpenEuler系統,熟悉系統使用,注意OpenEuler安裝工具使用sudo yum install ...

進入控制檯,點選遠端登入之後,點選CloudShell登入。

填入設定的密碼後,點選連線。

登入進OpenEuler系統,提交執行who命令的截圖
加分項:使用yum install 安裝C程式設計工具,以及自己的常用工具,提交安裝後測試使用的截圖。

實驗一 密碼引擎-1-OpenEuler-OpenSSL編譯

1. 下載最新的OpenSSL原始碼
2. 用自己的8位學號建立一個資料夾,cd 你的學號,用pwd獲得絕對路徑
3. 參考https://www.cnblogs.com/rocedu/p/5087623.html先在Ubuntu中完成OpenSSL編譯安裝,然後在OpenEuler中重現
        ./config  --prefix=..(學號目錄的絕對路徑)指定OpenSSL編譯連結
4. 提交 test_openssl.c 編譯執行截圖        
5. 加分項:在Windows中編譯OpenSSL,記錄編譯過程,提交相關文件(推薦MarkDown格式)

注:我的ubuntu用的是wsl(其實這個時候可以選擇使用老師給的openssl-master也可以使用原來wsl自帶的openssl)。

以下我使用老師提供的openssl-master:

已知老師為我們提供了openssl-master.zip,首先我們可以解壓縮到新創的20181217資料夾。

在wsl中的操作:

1 cd openssl-master 進入剛剛解壓縮的資料夾

執行下面的操作:

1 2 3 4 5 ./configure make sudo make install

這樣就安裝好了。

安裝好了之後,出現的問題及解決:

檢視openssl版本時,出錯了:
openssl: error while loading shared libraries: libssl.so.3: cannot open shared object file: No such file or directory

經過上網查詢,可知但我們輸入這兩條指令時,可以成功解決上述問題~

1 2 ln -s /usr/local/lib/libssl.so.3 /usr/lib/libssl.so.3 ln -s /usr/local/lib/libcrypto.so.3 /usr/lib/libcrypto.so.3

注意:到底是lib還是lib64需要自己進入資料夾去親自檢視。

再此檢視openssl版本時,顯示是成功的:

在ubuntu下編譯:

1 gcc -o to test_openssl.c -I /usr/local/ssl/inlcude -L /usr/local/ssl/lib -ldl -lpthread -lcrypto

可知編譯成功!

在華為雲中,同樣我們要安裝openssl,和在wsl中安裝的方式一模一樣。(首先,我們要先建立20181217資料夾,然後可以直接把openssl-master.zip包拖到華為雲的20181217資料夾下,再進行解壓縮~)

出現了和wsl中一樣的問題:

[root@ecs-cindy openssl-master]# openssl version
openssl: error while loading shared libraries: libssl.so.3: cannot open shared object file: No such file or directory

經過上網查詢,可知但我們輸入這兩條指令時,可以成功解決上述問題~

1 2 ln -s /usr/local/lib/libssl.so.3 /usr/lib64/libssl.so.3 ln -s /usr/local/lib/libcrypto.so.3 /usr/lib64/libcrypto.so.3

可知最終編譯成功了。

加分項:在Windows中編譯OpenSSL,記錄編譯過程,提交相關文件

CodeBlocks配置openssl

  • 加靜態庫

    (先啟用專案)選單欄->Project->Build Options->Debug->Linker settings->Add 自己openssl安裝目錄下/lib下所有.lib檔案(選擇時使用Ctrl+A)
  • 加動態庫

    選單欄->Project->Build Options->Debug->Search directories->Linker->Add 動態庫的目錄(參考前面安裝時的選項,設定後為/bin下)
  • 加標頭檔案

選單欄->Project->Build Options->Debug->Search directories->Compiler->Add 安裝目錄/include

測試Base64效果:

2.Virtual Studio 2019實現openssl編譯

eg:實現sm3:

由此可知windows下openssl編譯成功!

實驗一 密碼引擎-2-OpenEuler-OpenSSL測試

在Ubuntu編寫程式碼測試OpenSSL功能,包含Base64,SM2,SM3,SM4演算法的呼叫,然後在OpenEuler中重現
提交程式碼連結和執行結果截圖

加分項:在Windows中重現(已重現)
程式碼連結:https://gitee.com/csq200215/csq/tree/master/%E4%BF%A1%E6%81%AF%E5%AE%89%E5%85%A8%E7%B3%BB%E7%BB%9F%EF%BC%88%E4%B8%8B%EF%BC%89%E7%AC%AC%E4%B8%80%E6%AC%A1%E5%AE%9E%E9%AA%8C

Base64:(使用老師給我們的Openssl-Test.zip)

1.在wsl實現

注意:老師給的程式碼在ubuntu下是不能跑通的,我們需要對EVP_Base64資料夾中的main.c檔案進行修改(或者直接再重新生成一個Base64.c)

Base64.c如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 #include <stdio.h> #include <string.h> #include <openssl/evp.h> #include <openssl/x509.h> //Base64編碼 voidtEVP_Encode() { EVP_ENCODE_CTX *ctx; ctx = EVP_ENCODE_CTX_new();//EVP編碼結構體 unsignedcharin[1024];//輸入資料緩衝區 intinl;//輸入資料長度 charout[2048]={0};//輸出資料緩衝區 intoutl;//輸出資料長度 FILE *infp;//輸入檔案控制代碼 FILE *outfp;//輸出檔案控制代碼 infp = fopen("test.dat","rb");//開啟待編碼的檔案 if(infp == NULL) { printf("Open File \"Test.dat\" for Read Err.\n"); return; } outfp = fopen("test.txt","w");//開啟編碼後儲存的檔案 if(outfp == NULL) { printf("Open File \"test.txt\" For Write Err.\n"); return; } EVP_EncodeInit(ctx);//Base64編碼初始化 printf("檔案\"Test.dat\" Base64編碼後為:\n"); //迴圈讀取原文,並呼叫EVP_EncodeUpdate計算Base64編碼 while(1) { inl = fread(in,1,1024,infp); if(inl <= 0) break; EVP_EncodeUpdate(ctx,out,&outl,in,inl);//編碼 fwrite(out,1,outl,outfp);//輸出編碼結果到檔案 printf("%s",out); } EVP_EncodeFinal(ctx,out,&outl);//完成編碼,輸出最後的資料。 fwrite(out,1,outl,outfp); printf("%s",out); fclose(infp); fclose(outfp); printf("對檔案\"Test.dat\" Base64編碼完成,儲存到\"test.txt\"檔案.\n\n\n"); } //Base64解碼 voidtEVP_Decode() { EVP_ENCODE_CTX *ctx; ctx = EVP_ENCODE_CTX_new();//EVP編碼結構體 charin[1024];//輸入資料緩衝區 intinl;//輸入資料長度 unsignedcharout[1024];//輸出資料緩衝區 intoutl;//輸出資料長度 FILE *infp;//輸入檔案控制代碼 FILE *outfp;//輸出檔案控制代碼 infp = fopen("test.txt","r");//開啟待解碼的檔案 if(infp == NULL) { printf("Open File \"Test.txt\" for Read Err.\n"); return; } outfp = fopen("test-1.dat","wb");//開啟解碼後儲存的檔案 if(outfp == NULL) { printf("Open File \"test-1.txt\" For Write Err.\n"); return; } EVP_DecodeInit(ctx);//Base64解碼初始化 printf("開始對檔案\"Test.txt\" Base64解碼...\n\n"); //迴圈讀取原文,並呼叫EVP_DecodeUpdate進行Base64解碼 while(1) { inl = fread(in,1,1024,infp); if(inl <= 0) break; EVP_DecodeUpdate(ctx,out,&outl,in,inl);//Base64解碼 fwrite(out,1,outl,outfp);//輸出到檔案 } EVP_DecodeFinal(ctx,out,&outl);//完成解碼,輸出最後的資料。 fwrite(out,1,outl,outfp); fclose(infp); fclose(outfp); printf("對檔案\"Test.txt\" Base64解碼完成,儲存為\"test-1.dat\"\n\n\n"); } intmain() { tEVP_Encode(); tEVP_Decode(); return0; }

我們可以直接直接在原資料夾中生成。

一、 執行命令將Base64.c編譯成可執行檔案Base64。

1 gcc -o Base64 Base64.c -I /usr/local/ssl/inlcude -L /usr/local/ssl/lib -ldl -lpthread -lcrypto

另一種執行方法~gcc -o Base64 Base64.c -lpthread -lcrypto

2.華為雲

在OpenEuler中重現。

首先我們把下載好的 Openssl-Test.zip檔案直接拖到華為雲的20181217資料夾下。

1 unzip Openssl-Test.zip 實現解壓縮。

進入Openssl-Test資料夾中,再進入EVP_Base64資料夾:

注意:老師給的程式碼在ubuntu下是不能跑通的,我們需要對EVP_Base64資料夾中的main.c檔案進行修改(或者直接再重新生成一個Base64.c)。

和之前一樣~

實現:

可知可以成功實現。

在windows中重現:

二、實現SM2

sm2程式碼連結

編譯過程:

gcc sm2_create_key_pair.c test_demo.c sm2_encrypt_and_decrypt.c test_sm2_encrypt_and_decrypt.c -o mysm2 -lcrypto

執行過程:

在華為雲上執行過程:

執行結果:

可知成功實現。

在windows上的 VS中重現:

三、SM3

程式碼:

mysm3.c

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <stdio.h> #include <string.h> #include <openssl/evp.h> voidtDigest() { unsignedcharsm3_value[EVP_MAX_MD_SIZE];//儲存輸出的摘要值的陣列 intsm3_len, i; EVP_MD_CTX *sm3ctx;//EVP訊息摘要結構體 sm3ctx = EVP_MD_CTX_new();//呼叫函式初始化 charmsg1[] ="Test Message1";//待計算摘要的訊息1 charmsg2[] ="Test Message2";//待計算摘要的訊息2 EVP_MD_CTX_init(sm3ctx);//初始化摘要結構體 EVP_DigestInit_ex(sm3ctx, EVP_sm3(), NULL);//設定摘要演算法和密碼演算法引擎,這裡密碼演算法使用sm3,演算法引擎使用OpenSSL預設引擎即軟演算法 EVP_DigestUpdate(sm3ctx, msg1, strlen(msg1));//呼叫摘要UpDate計算msg1的摘要 EVP_DigestUpdate(sm3ctx, msg2, strlen(msg2));//呼叫摘要UpDate計算msg2的摘要 EVP_DigestFinal_ex(sm3ctx, sm3_value, &sm3_len);//摘要結束,輸出摘要值 EVP_MD_CTX_reset(sm3ctx);//釋放記憶體 printf("原始資料%s和%s的摘要值為:\n",msg1,msg2); for(i = 0; i < sm3_len; i++) { printf("0x%02x ", sm3_value[i]); } printf("\n"); } intmain() { OpenSSL_add_all_algorithms(); tDigest(); return0; }

初始化函式EVP_MD_CTX_init
函式功能:初始化一個 EVP_MD_CTX 結構體。只有呼叫該函式初始化後,EVP_MD_CTX結構體才能在其他函式中呼叫。
函式定義:
void EVP_MD_CTxinit(EVP MD CTX *ctx):

在ubuntu下實現:

執行命令:

1 gcc -o mysm3 mysm3.c -lpthread -lcrypto

在華為雲上實現:

在windows下的VS 2019中重現

四、SM4

程式碼:

mysm4.c :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 #include <stdio.h> #include <string.h> #include <windows.h> #include <openssl/evp.h> #include <openssl/x509.h> voidtEVP_Encrypt() { unsignedcharkey[EVP_MAX_KEY_LENGTH];//金鑰 unsignedchariv[EVP_MAX_KEY_LENGTH];//初始化向量 EVP_CIPHER_CTX* ctx;//EVP演算法上下文 unsignedcharout[1024];//輸出密文緩衝區 intoutl;//密文長度 intoutltmp; constchar*msg="Hello OpenSSL";//待加密的資料 intrv; inti; //初始化函式才能用! ctx = EVP_CIPHER_CTX_new(); //設定key和iv(可以採用隨機數和可以是使用者輸入) for(i=0;i<24;i++) { key[i]=i; } for(i=0;i<8;i++) { iv[i]=i; } //初始化密碼演算法結構體 EVP_CIPHER_CTX_init(ctx); //設定演算法和金鑰以 rv = EVP_EncryptInit_ex(ctx,EVP_sm4_cbc(),NULL,key,iv); if(rv!=1) { printf("Err\n"); return; } //資料加密 rv = EVP_EncryptUpdate(ctx,out,&outl,(constunsignedchar*)msg,strlen(msg)); if(rv!=1) { printf("Err\n"); return; } //結束資料加密,把剩餘資料輸出。 rv = EVP_EncryptFinal_ex(ctx,out+outl,&outltmp); if(rv!=1) { printf("Err\n"); return; } outl = outl +outltmp; printf("原文為:%s\n",msg); //列印輸出密文 printf("密文長度:%d\n密文資料:\n",outl); for(i=0;i<outl;i++) { printf("0x%02x ",out[i]); } printf("\n"); } intmain() { OpenSSL_add_all_algorithms(); tEVP_Encrypt(); return0; }

  編譯、執行實現:

gcc -o mysm4 mysm4.c -lpthread -lcrypto
./mysm4
執行結果如下

執行命令

1 gcc -o mysm4 mysm4.c -lpthread -lcrypto

接下來放到雲上試試~

可以發現也成功了!

在windows中重現: