• 001数据安全传输-多端协议传输平台:Openssl安装和配置 - EVP代码测试


    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	 (使用管理员权限执行该命令)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    验证是否安装成功

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

    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
    
    • 1
    • 2
    • 3
    • 4

    输出结果

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3. EVP测试

    测试代码如下:

    #define _CRT_SECURE_NO_WARNINGS
    //#include 		// md5 头文件
    #include 
    #include 
    #include 
    #include 
    
    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;
    }
    
    • 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

    输出结果:

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

    4. Shal1测试

    #include 
    #include 
    // sha系列 哈希算法都包含该头文件
    #include 
    #include 
    #include 	// 将秘钥写文件的时候
    #include 
    #include 
    extern "C"
    {
    #include  // 编译的时候将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;
    }
    
    • 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
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211

    在这里插入图片描述

  • 相关阅读:
    直播速递 | Plan Stitch:一种使用缝合物理计划解决查询计划性能退化问题的方法
    postgresql 格式化查询树为图片 —— pgNodeGraph 与 pg_node2graph
    C++ 与复合数据类型:透过类理解结构体
    编程技巧│高级 markdown 编辑器的惊艳语法
    Linux廉价磁盘冗余队列(RAID)
    【JavaWeb】第五章 jQuery
    实现动态页面的技术Servlet
    图第三遍补充(各种算法与力扣)
    ​力扣解法汇总934. 最短的桥
    大算力时代已经到来
  • 原文地址:https://blog.csdn.net/jiangchufeng123/article/details/133836208