Openssl数据安全传输平台001:Openssl安装和配置 - Windows/CentOS7 - EVP/SHA1 代码测试

Openssl数据安全传输平台:Openssl安装和配置 - EVP/SHA1 代码测试

0 Centos7编译视频

视频传送门:

https://www.bilibili.com/video/BV1PM41197ro/?vd_source=3353f83539e46042d8cf76efb177a8e4

04-Centos7上编译Openssl1.1.1w版本

1. 安装

1.1 windows下安装openssl

在这里插入图片描述

在这里插入图片描述
OpenSSL安装完成。

1.2 Linux下安装OpenSSL

下载安装包, 下载地址: https://www.openssl.org/source/

源码安装包解压缩

.tar.gz格式:

tar zxvf openssl-1.1.1w.tar.gz

.tar.bz格式:

tar jxvf openssl-1.1.1w.tar.gz

切换root用户,进入解压目录, 安装(可参考安装文件INSTALL):

su - root

cd /path/xxxxxxx/openssl-1.1.1w

//这个的时间很长
./config

//这个的时间很长
make

//make test会显示fail
make test 		(可选)

make install	 (使用管理员权限执行该命令)

验证是否安装成功

可能软连接会有点问题,要提前重新连一下

ln -s /usr/local/lib64/libssl.so.1.1 /usr/lib64/libssl.so.1.1
ln -s /usr/local/lib64/libcrypto.so.1.1 /usr/lib64/libcrypto.so.1.1

openssl version -a

输出结果

OpenSSL 1.1.1w  11 Sep 2023
built on: Tue Oct 31 04:38:07 2023 UTC
platform: linux-x86_64
options:  bn(64,64) rc4(16x,int) des(int) idea(int) blowfish(ptr) 
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -O3 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG
OPENSSLDIR: "/usr/local/ssl"
ENGINESDIR: "/usr/local/lib64/engines-1.1"
Seeding source: os-specific

2. VS中使用openssl

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
将openssl安装目录/bin目录下(C:\OpenSSL-Win32\bin)的两个动态库拷贝到工作目录下:

libcrypto-1_1.dll
libssl-1_1.dll

C:\OpenSSL-Win32 是我的openssl安装目录
在这里插入图片描述在这里插入图片描述

_CONSOLE
_DEBUG
_SCL_SECURE_NO_WARNINGS
PROTOBUF_USE_DLLS
_CRT_SECURE_NO_WARNINGS

3. EVP测试

测试代码如下:

#define _CRT_SECURE_NO_WARNINGS
//#include <openssl/md5.h>		// md5 头文件
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/evp.h>

void getMD5(const char* str, char* result)
{
	EVP_MD_CTX* mdctx;
	unsigned int md5_digest_len = EVP_MD_size(EVP_md5());//求属性长度
    //MD5_CTX ctx;
	
	// 初始化
	//MD5_Init(&ctx);
	mdctx = EVP_MD_CTX_new();
	EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);

	// 添加数据
	//MD5_Update(&ctx, str, strlen(str));
	EVP_DigestUpdate(mdctx, str, strlen(str));

	// 计算结果
	unsigned char md[16] = { 0 };
	
	//MD5_Final(md, &ctx);
	EVP_DigestFinal_ex(mdctx, md, &md5_digest_len);

	for (int i = 0; i < 16; ++i)
	{
		sprintf(&result[i * 2], "%02x", md[i]);
	}
	EVP_MD_CTX_free(mdctx);
}

int main()
{
	char result[33] = { 0 };
	getMD5("hello, md5", result);
	printf("md5 value: %s\n", result);
	system("pause");

	return 0;
}

输出结果:

md5 value: 33b3bc8e05b4fcc16bd531dd9adac166
在这里插入图片描述

4. Shal1测试

#include <iostream>
#include <string.h>
// sha系列 哈希算法都包含该头文件
#include <openssl/sha.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>	// 将秘钥写文件的时候
#include <string>
#include <openssl/aes.h>
extern "C"
{
#include <openssl/applink.c> // 编译的时候将applinc.c包含进去参与编译
};

using namespace std;

void sha1Test()
{
	// 1. 初始化
	SHA_CTX ctx;
	SHA1_Init(&ctx);
	// 2. 添加数据
	SHA1_Update(&ctx, "hello", strlen("hello"));
	SHA1_Update(&ctx, ", world", strlen(", world"));
	// 3. 哈希计算
	unsigned char* md = new unsigned char[SHA_DIGEST_LENGTH];
	char* res = new char[SHA_DIGEST_LENGTH*2 + 1];
	SHA1_Final(md, &ctx);
	// 4. 格式转换
	for (int i = 0; i < SHA_DIGEST_LENGTH; ++i)
	{
		sprintf(&res[i * 2], "%02x", md[i]);
	}
	cout << "sha1: " << res << endl;
}

// 生成rsa密钥对
void generateRsaKey()
{
	// 1. 创建rsa变量
	RSA* rsa = RSA_new();
	// 1.5 创建bignum对象, 并初始化
	BIGNUM* e = BN_new();
	BN_set_word(e, 12345);
	// 2. 生成密钥对 -> 密钥对在内存中
	RSA_generate_key_ex(rsa, 1024, e, NULL);
	// 3. 将密钥对写入到磁盘
#if 1
	// 公钥
	RSA* pubKey = RSAPublicKey_dup(rsa);
	// 私钥
	RSA* priKey = RSAPrivateKey_dup(rsa);
#endif
#if 0
	FILE* fp = fopen("public.pem", "w");
	PEM_write_RSAPublicKey(fp, rsa);
	fclose(fp);
	// 写私钥
	fp = fopen("private.pem", "w");
	PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL);
	fclose(fp);
#else
	BIO* bio = BIO_new_file("public-1.pem", "w");
	PEM_write_bio_RSAPublicKey(bio, rsa);
	// 释放资源
	BIO_free(bio);
	bio = BIO_new_file("private-1.pem", "w");
	PEM_write_bio_RSAPrivateKey(bio, rsa, NULL, NULL, 0, NULL, NULL);
	BIO_free(bio);
#endif
}

// 公钥加密
string encryptPublicKey()
{
	// 1. 准备要加密数据
	string text = "让编程改变世界...";
	// 2. 准备秘钥 -> 公钥
	// 从磁盘文件读秘钥
	// 使用bio的方式
	BIO* bio = BIO_new_file("public-1.pem", "r");
	RSA* pubKey = RSA_new();
	if (PEM_read_bio_RSAPublicKey(bio, &pubKey, NULL, NULL) == NULL)
	{
		cout << "读公钥失败了..." << endl;
		return string();
	}
	BIO_free(bio);
	// 3. 加密 -> 密文
	// 数据被加密之后, 长度和秘钥长度相同
	// 通过函数计算秘钥长度
	int keyLen = RSA_size(pubKey);
	char *buf = new char[keyLen];
	// 返回值就是密文长度
	int len = RSA_public_encrypt(text.size(), (const unsigned char*)text.data(), 
		(unsigned char*)buf, pubKey, RSA_PKCS1_PADDING);
	// 4. 将密文返回
	cout << "加密之后的数据: " << buf << endl;
	cout << "加密之后的数据长度: " << len << endl;
	return string(buf, len);
}

// 私钥解密
string decryptPrivateKey(string str)
{
	// 1. 准备秘钥 ->私钥
	// 从磁盘文件读秘钥
	// 使用bio的方式
	BIO* bio = BIO_new_file("private-1.pem", "r");
	RSA* priKey = RSA_new();
	if (PEM_read_bio_RSAPrivateKey(bio, &priKey, NULL, NULL) == NULL)
	{
		cout << "读私钥失败..." << endl;
		return string();
	}
	BIO_free(bio);
	// 解密 -> 明文
	// 数据被加密之后, 长度和秘钥长度相同
	// 通过函数计算秘钥长度
	int keyLen = RSA_size(priKey);
	char *buf = new char[keyLen];
	// 返回值是解密之后的数据长度 == 原始数据长度
	int len = RSA_private_decrypt(str.size(), (const unsigned char*)str.data(),
		(unsigned char*)buf, priKey, RSA_PKCS1_PADDING);
	// 4. 将明文返回
	cout << "buf: " << buf << endl;
	return string(buf, len);
}

// 签名和验证签名
void rsaSigAndVerfiy()
{
	// 1. 签名数据
	string text = "让编程改变世界...";
	// 2. 秘钥
	RSA* pubKey = RSA_new();
	RSA* priKey = RSA_new();
	BIO* pubBio = BIO_new_file("public.pem", "r");
	PEM_read_bio_RSAPublicKey(pubBio, &pubKey, NULL, NULL);
	BIO_free(pubBio);
	BIO* prilBio = BIO_new_file("private.pem", "r");
	PEM_read_bio_RSAPrivateKey(prilBio, &priKey, NULL, NULL);
	BIO_free(prilBio);
	// 3. 签名
	int len = RSA_size(priKey);
	unsigned int outLen = 0;
	unsigned char* out = new unsigned char[len];
	RSA_sign(NID_sha1, (const unsigned char*)text.data(), text.size(), 
		out, &outLen, priKey);
	// 要给到用户的数据
	string sigbuf((char*)out, outLen);

	// 4. 验证签名
	int ret = RSA_verify(NID_sha1, (const unsigned char*)text.data(), text.size(),
		(const unsigned char*)sigbuf.data(), sigbuf.size(), pubKey);
	cout << "ret : " << ret << endl;
}

// 测试对称加密
void aesCBCCrypto()
{
	// 1. 准备数据
	const char* pt = "AES是一套对称密钥的密码术,目前已广泛使用,用于替代已经不够安全的DES算法。所谓对称密钥,就是说加密和解密用的是同一个密钥,消息的发送方和接收方在消息传递前需要享有这个密钥。和非对称密钥体系不同,这里的密钥是双方保密的,不会让任何第三方知道。对称密钥加密法主要基于块加密,选取固定长度的密钥,去加密明文中固定长度的块,生成的密文块与明文块长度一样。显然密钥长度十分重要,块的长度也很重要。如果太短,则很容易枚举出所有的明文 - 密文映射;如果太长,性能则会急剧下降。AES中规定块长度为128 bit,而密钥长度可以选择128, 192或256 bit 。暴力破解密钥需要万亿年,这保证了AES的安全性。";
	// 2. 准备秘钥
	const char* key = "1234567887654321";
	// 3. 初始化秘钥
	AES_KEY encKey;
	AES_set_encrypt_key((const unsigned char*)key, 128, &encKey);
	// 4. 加密
	// 计算长度
	int length = 0;
	int len = strlen((char*)pt) + 1;
	if (len % 16 != 0)
	{
		length = ((len / 16) + 1) * 16;
	}
	else
	{
		length = len;
	}
	unsigned char* out = new unsigned char[length];
	unsigned char ivec[AES_BLOCK_SIZE];
	memset(ivec, 9, sizeof(ivec));
	// 密文存储在out中
	AES_cbc_encrypt((const unsigned char*)pt, out, length, &encKey, ivec, AES_ENCRYPT);

	// 5. 解密
	unsigned char* data = new unsigned char[length];
	AES_KEY deckey;
	memset(ivec, 9, sizeof(ivec));
	AES_set_decrypt_key((const unsigned char*)key, 128, &deckey);
	AES_cbc_encrypt(out, data, length, &deckey, ivec, AES_DECRYPT);
	// 6. 打印
	cout << "还原的数据: " << data << endl;

	delete[]out;
	delete[]data;
}

int main()
{
	sha1Test();
//	generateRsaKey();

	//string str = encryptPublicKey();
	//string str1 = decryptPrivateKey(str);
	//cout << "解密数据: " << str1 << endl;
	//	rsaSigAndVerfiy();
	//aesCBCCrypto();

	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大大枫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值