基于openEuler的OpenSSL编译安装和编程基础

基于openEuler的OpenSSL编译安装和编程基础

有关OpenSSL的编译、安装、使用、编程我写过一篇博客Linux下OpenSSL的安装与使用.

由于学校跟华为合作“智能基座”产教融合协同育人基地项目,我们把学习平台从原来的X64+Ubuntu的架构换成ARM64(鲲鹏)+openEuler的架构。

ARM64 + openEuler环境可以在华为云购买ECS,同学们使用优惠券注意按下图选项购买:

特别提醒:做完实验一定要关机,否则优惠券会很快用完!!!

另外还可以自己购买个树莓派,自己安装openEuler,可以参考这个教程树莓派openEuler安装.

下面演示基于华为云ECS,鲲鹏+openEuler架构。

远程登录openEuler,我们看一下openEuler默认有没有安装OpenSSL,如下图所示,openEuler默认已经安装好了OpenSSL:

当前openEuler系统安装的OpenSSL版本是1.1.1d,现在(2021.04)OpenSSL最新的版本是1.1.1k,还有一个问题,openEuler中没有变成开发需要的头文件。我们需要自己下载OpenSSL的源码编译安装。

OpenSSL编译安装

  1. 我们去OpenSSL官网下载最新版本OpenSSL 1.1.1k的源码openssl-1.1.1k.tar.gz,然后把代码上传到openEuler云服务器中。
  2. 建立两个文件夹,分别放置OpenSSL的源码和安装路径,记住pwd运行的结果/root/rocopenssl
mkdir rocopensslsrc rocopenssl
cd rocopenssl
pwd 
  1. 解压源代码到rocopensslsrc文件夹:
tar -zxvf openssl-1.1.1k.tar.gz -C rocopensslsrc
  1. 配置编译安装路径(/root/rocopenssl),和openEuler系统默认的不同。
cd rocopensslsrc/openssl-1.1.1k
./config --prefix=/root/rocopenssl
  1. 编译(make时间稍长,耐心等待),测试、安装,其中测试步骤可选:
make
make test
make install
  1. 查看安装后的版本,确定是最新安装的1.1.1k版:
cd ~/rocopenssl
./bin/openssl version

注意用到的库还是旧版本的,这个问题怎么解决留作思考题吧

  1. 大家要注意的是rocopenssl下的include和lib的路径,我们后面编程要用到。
/root/rocopenssl/include
/root/rocopenssl/lib

以上步骤可以使用下面的installopenssl.sh脚本完成:

#! /bin/sh

cd

if [ ! -d rocopenssl ];
then
    mkdir rocopenssl
    mkdir rocopensslsrc
fi

if [ ! -f ~/openssl-1.1.1k.tar.gz ]; 
then
	wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz
	tar -zxvf ~/openssl-1.1.1k.tar.gz -C ~/rocopensslsrc
	
	cd ~/rocopensslsrc/openssl-1.1.1k
	./config --prefix=/root/rocopenssl
	make
    make test
    make install
	
	~/rocopenssl/bin/openssl version
fi

OpenSSL命令的使用

学会工具第一招,学会查看帮助文档,OpenSSL命令的帮助使用openssl help查看:

OpenSSL命令下面有很多子命令分为三类:标准命令,消息摘要命令和密码命令。这些命令我们有两种用法,以最简单的产看版本命令为例,我们可以先输入openssl进入OpenSSL的功能界面后输入version,也可以直接在openEuler终端中直接输入openssl version进行查看,在实际应用中我们多采用后一种方法。

对于子命令的使用帮助,我们可以有两种方式查看openssl help xxsubcmdopenssl xxsubcmd --help,比如用这两种方法查看消息摘要子命令的用法:

openssl dgst 常用选项(options)有:

[-md5|-md4|-md2|-sha1|-sha|-mdc2|-ripemd160|-dss1] :指定一种摘要算法

-out filename:将摘要值保存到指定文件中

比如我们用国密算法sm3计算besti的摘要,注意子命令的两种用法以及管道的用法:

besti放到besti.txt文件中,计算文件的摘要:

如何使用随机数产生对称加密算法的密钥?如何使用国密算法sm4进行对称加解密?如果产生sm2的公私钥对?如果用SM2算法加密解密,签名验签?这些作为思考题吧。

OpenSSL编程

密码算法库的功能非常强大,是OpenSSL的基础,它实现了现代密码学大部分主流的密码算法和标准,主要包括公开密钥(非对称)算法、对称加密算法、信息摘要算法、X509 数字证书标准、PKCS12个人信息交换语法标准、PKCS7 加密消息语法标准、OCSP 在线证书状态查询协议、 CRL 证书吊销列表等标准。同时 OpenSSL 还提供了Engine 机制;利用 Engine 可以将加密卡、加密机这样的外部硬件算法模块无缝集成到 OpenSSL 中。密码算法库在 Windows 下编译后其库文件为 libeay32.lib(如果编译成动态库则为 libeay32.dll),在 Linux 编译后其库文件名称为 libcrypto.a。

现在的版本支持国密算法如SM2,SM3,SM4等算法。

简单测试

编写一个测试代码test_openssl.c:

#include <stdio.h>
#include <openssl/evp.h>

int main(){
	
    OpenSSL_add_all_algorithms();
	
    return 0;
}

然后用下面命令编译:

gcc -o to test_openssl.c -I /root/rocopenssl/include -L /root/rocopenssl/lib -lcrypto -lpthread

执行./to;echo $?,结果打印0.

BASE64算法

OpenSS1在 Evp.h中提供了Base64 编码和解码的函数。Base64 编码就是把二进制数据转换为可见的 ASCIⅡ字符。Base64 解码是相反的过程。Base64编码后的数据方便在 Web 中传输以及可视化的复制和粘贴。

OpenSSL 进行 Base64 编码的函数主要有EVP_EncodeInit、EVP_EncodeUpdate、EVP_EncodeFinal和 EVP_EncodeBlock。其中 EVP_EncodeInit、EVP_EncodeUpdateEVP_EncodeFinal 适用于处理不定长的大数据,EVP_EncodeBlock 适用于处理短数据。

OpenSSL 进行 Base64 解码的函数主要有EVP_Decodelnit、EVP_DecodeUpdate、EVP_DecodeFinal和 EVP_DecodeBlock。其中 EVP_DecodeInit、EVP_DecodeUpdateEVP_DecodeFinal适用于处理不定长的大数据,EVP_DecodeBlock 适用于处理短数据。

上面的函数可以完成消息的编码和解码,它们均定义在 openssl/evp.h 文件中。

我们要注意的是XXXInit,XXXUpdte,XXXFinal的编程模式。

我们写一个BASE64的测试代码testbase64.c :

#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;
}

代码中有中文,编译运行可能出现乱码,使用gcc编译时可以使用如下参数:

  • -finput-charset 指定源文件(保存文件时选择)的编码方式(若不指定,编译器默认是UTF-8)
  • -fexec-charset 指定可执行程序中的字符以什么编码方式来表示,默认是UTF-8

编译代码的命令是:

gcc -o testbase64 testbase64.c -I /root/rocopenssl/include -L /root/rocopenssl/lib -lcrypto -lpthread -finput-charset=GBK -fexec-charset=UTF-8

测试中的用到一个test.dat 是个二进制文件,可以用echo命令生成,或者用二进制编辑工具生成。

执行./testbase64,结果如下图:

作业

  1. 两人一组
  2. 基于Socket实现TCP通信,一人实现服务器,一人实现客户端
  3. 研究OpenSSL算法,测试对称算法中的SM4,非对称算法中的SM2,Hash算法中的SM3
  4. 选用合适的算法,基于混合密码系统实现对TCP通信进行机密性、完整性保护。
  5. 学有余力者,对系统进行安全性分析和改进。

参考资料


欢迎关注“rocedu”微信公众号(手机上长按二维码)

做中教,做中学,实践中共同进步!

rocedu



如果你觉得本文对你有帮助,请点一下左下角的“好文要顶”和“收藏该文


posted @ 2021-04-05 08:40  娄老师  阅读(2161)  评论(0编辑  收藏  举报