密码引擎的设计与实现
Posted 20181217Cindy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了密码引擎的设计与实现相关的知识,希望对你有一定的参考价值。
实验一 密码引擎-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编码 void tEVP_Encode() { EVP_ENCODE_CTX *ctx; ctx = EVP_ENCODE_CTX_new(); //EVP编码结构体 unsigned char in [1024]; //输入数据缓冲区 int inl; //输入数据长度 char out [2048]={0}; //输出数据缓冲区 int outl; //输出数据长度 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解码 void tEVP_Decode() { EVP_ENCODE_CTX *ctx; ctx = EVP_ENCODE_CTX_new(); //EVP编码结构体 char in [1024]; //输入数据缓冲区 int inl; //输入数据长度 unsigned char out [1024]; //输出数据缓冲区 int outl; //输出数据长度 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" ); } int main() { tEVP_Encode(); tEVP_Decode(); return 0; } |
我们可以直接直接在原文件夹中生成。
一、 执行命令将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
编译过程:
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> void tDigest() { unsigned char sm3_value[EVP_MAX_MD_SIZE]; //保存输出的摘要值的数组 int sm3_len, i; EVP_MD_CTX *sm3ctx; //EVP消息摘要结构体 sm3ctx = EVP_MD_CTX_new(); //调用函数初始化 char msg1[] = "Test Message1" ; //待计算摘要的消息1 char msg2[] = "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" ); } int main() { OpenSSL_add_all_algorithms(); tDigest(); return 0; } |
初始化函数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> void tEVP_Encrypt() { unsigned char key[EVP_MAX_KEY_LENGTH]; //密钥 unsigned char iv[EVP_MAX_KEY_LENGTH]; //初始化向量 EVP_CIPHER_CTX* ctx; //EVP算法上下文 unsigned char out [1024]; //输出密文缓冲区 int outl; //密文长度 int outltmp; const char *msg= "Hello OpenSSL" ; //待加密的数据 int rv; int i; //初始化函数才能用! 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,( const unsigned char *)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); //打印输出密文 |