基于 OpenSSL 的区块链核心密码学 C++ 加密与解密技术:从基础到实际应用

发布时间 2023-10-27 15:39:40作者: 天使angl

基于 OpenSSL 的区块链核心密码学 C++ 加密与解密技术:从基础到实际应用

项目需要,需要用C++后端 进行RSA算法加密,Web端(Java)进行解密。把之前遇到的问题整理一下。一步一坑,坑坑有惊喜。 能到这来,RSA算法原理就不细讲了 ,反正作为学渣我也不太懂。
背景:为了网络数据安全,Web端(Java)要求用RSA加密算法传数据,公钥加密私钥解密方式(RSA有公钥加密私钥解密、私钥加密公钥解密),公钥秘钥都有Java生成,格式都是pkcs#8,本文秘钥的长度为2048。


第一步:生成正确的秘钥格式

java给的公钥是字符串,但是真正加密的时候用的pkcs#8格式的秘钥。java公钥字符串

std::string publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxFGq9XJtuXmXh6nIYmhAmmd67RK5uIExhkd8YjPYJfqSqyMA/1G0KkxUaRlqf2A0vjn12341ZE/BcdVQ3AG9NYNfAJMYLpPobGqMHV6S7OhyvJjnqyZD8hr8StbyUgXtJ3VNyZ3uhzi7W8Dje7MfFdVz8xlsW+z17ffZCWMkznFMPHuKHDoPAztKoQ1Fq6YconTq2F7cSVnFc0jkLu6X/ihz5dcPiz90WjFEANWRauuVXB2MMgdsjIhBgV8XTRKoB6zUDWVtR9icRVlgpwJjcSL/5xnwzhmgpG7lnAWwA7KE0/zrOx2jj1PkfiBvmk+H5Iyo9kTUQ2jaOqWwEqycSwIDAQAB";
 

pkcs#8格式的公钥

std::string publicKey =-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxFGq9XJtuXmXh6nIYmhA
mmd67RK5uIExhkd8YjPYJfqSqyMA/1G0KkxUaRlqf2A0vjnPcdw1ZE/BcdVQ3AG9
NYNfAJMYLpPobGqMHV6S7OhyvJjnqyZD8hr8StbyUgXtJ3VNyZ3uhzi7W8Dje7Mf
FdVz8xlsW+z17ffZCWMkznFMPHuKHDoPAztKoQ1Fq6YconTq2F7cSVnFc0jkLu6X
/ihz5dcPiz90WjFEANWRauuVXB2MMgdsjIhBgV8XTRKoB6zUDWVtR9icRVlgpwJj
cSL/5xnwzhmgpG7lnAWwA7KE0/zrOx2jj1PkfiBvmk+H5Iyo9kTUQ2jaOqWwEqyc
SwIDAQAB
-----END PUBLIC KEY-----
”;
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

第二步:C++ RSA加密,用openssl库实现

string encodeData="123456789";//需要加密的内容
publicKey //第一步生成 pkcs#8格式的公钥
vector<char> res= rsa_encode(encodeData, publicKey )
{
	std::vector<char> encrypt_data;
	BIO* in = BIO_new_mem_buf((void*)pubkey.c_str(), -1);
	if (in == NULL) 
	{
		return std::vector<char>();
	}
	RSA* rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL);
	BIO_free(in);
	if (rsa == NULL) {
		return std::vector<char>();
	}
		int size = RSA_size(rsa);
	encrypt_data.resize(size);
	int ret = RSA_public_encrypt(
		message.length(), (unsigned char*)message.c_str(),
		(unsigned char*)encrypt_data.data(), rsa, RSA_PKCS1_PADDING);
	RSA_free(rsa);
	if (ret == -1) {
		return std::vector<char>();
	}
	return encrypt_data;
}
 
  • 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

此时会生成密文,打印出来之后是乱码,莫惊慌。对生成的密文进行base64转换,C++代码实现

size//encrypt_data.size()
std::string  encodedData = Base64((unsigned char*)encrypt_data, int size)
{
	std::string _base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	int num = 0, bin = 0, i;
	std::string _encode_result;
	const unsigned char * current;
		current = str;
	while (bytes > 2) {
		_encode_result += _base64_table[current[0] >> 2];
		_encode_result += _base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
		_encode_result += _base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
		_encode_result += _base64_table[current[2] & 0x3f];

		current += 3;
		bytes -= 3;
	}
		if (bytes > 0)
	{
		_encode_result += _base64_table[current[0] >> 2];
		if (bytes % 3 == 1) {
			_encode_result += _base64_table[(current[0] & 0x03) << 4];
			_encode_result += "==";
		}
		else if (bytes % 3 == 2) {
			_encode_result += _base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
			_encode_result += _base64_table[(current[1] & 0x0f) << 2];
			_encode_result += "=";
		}
	}
	return _encode_result;
}
 
  • 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

经过base64转化后的结果:

"Rn6yJNPLXZmMMWf7Rp6AURTiujNgnmpSFwzJLouXAPAgmS5ktyzGBCNF5/0ROG5PxHp+kLWfH25Kt0zhChXkuLWm3vmVGAXYfTVxBcPGqnEILnyiYIXnPpI3F5ahCPdXmHk0/+n3XNwWeHbEsX4ds7HuMT7Y3f9980FXGMwBXGGZiGKXIlHbJyBASgdjUq0F15igeVgKYIBXlIIAj8HT0Udmppd1mZDgdk/XbQIZ8okRJcdL37v53ogqkLyipoDJn1hJYLcL56nlNWxOK14oHpLCId3HjybhVUh2TVdTMQmQ4EVRE+OLGfVPCI9jILDxH4qQIvehJ9oma2EMDlwzbg=="
 
  • 1

大功告成!此时生成的string传给Web端,java可以根据密文解码出加密的文本。