首页 > 编程语言 >c++ openssl加密 解密

c++ openssl加密 解密

时间:2024-01-25 12:13:03浏览次数:22  
标签:std PKEY string openssl c++ 解密 key EVP public

#include <iostream>
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/spawn.hpp>
#include <json.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
#include <cstdlib>

#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/pem.h>
#include <openssl/kdf.h>
/**
 *三方库
 *  boost_1_84_0
 *  Win64OpenSSL-3_2_0
 *
 *
 * 生成私钥 openssl genpkey -algorithm RSA -out private_key.pem -aes256 -pass pass:
 * 生成公钥 openssl rsa -pubout -in private_key.pem -out public_key.pem
 **/
namespace asio = boost::asio;
namespace beast = boost::beast;
namespace websocket = beast::websocket;
using tcp = asio::ip::tcp;
using json = nlohmann::json;

std::string rsa_encrypt(const std::string& plaintext, EVP_PKEY* public_key) {
	OpenSSL_add_all_algorithms();

	EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();

	// 使用 RSA 加密算法
	EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new(public_key, nullptr);
	EVP_PKEY_encrypt_init(pctx);

	// 获取加密输出长度
	size_t encrypted_length;
	EVP_PKEY_encrypt(pctx, nullptr, &encrypted_length, reinterpret_cast<const unsigned char*>(plaintext.c_str()), plaintext.length());

	std::string encrypted(encrypted_length, '\0');

	// 执行加密
	EVP_PKEY_encrypt(pctx, reinterpret_cast<unsigned char*>(&encrypted[0]), &encrypted_length, reinterpret_cast<const unsigned char*>(plaintext.c_str()), plaintext.length());

	// 释放资源
	EVP_PKEY_CTX_free(pctx);
	EVP_CIPHER_CTX_free(ctx);

	// 返回加密后的结果
	return encrypted;
}

std::string rsa_decrypt(const std::string& ciphertext, EVP_PKEY* private_key) {
	OpenSSL_add_all_algorithms();

	EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();

	// 使用 RSA 解密算法
	EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new(private_key, nullptr);
	EVP_PKEY_decrypt_init(pctx);

	// 获取解密输出长度
	size_t decrypted_length;
	EVP_PKEY_decrypt(pctx, nullptr, &decrypted_length, reinterpret_cast<const unsigned char*>(ciphertext.c_str()), ciphertext.length());

	std::string decrypted(decrypted_length, '\0');

	// 执行解密
	EVP_PKEY_decrypt(pctx, reinterpret_cast<unsigned char*>(&decrypted[0]), &decrypted_length, reinterpret_cast<const unsigned char*>(ciphertext.c_str()), ciphertext.length());

	// 释放资源
	EVP_PKEY_CTX_free(pctx);
	EVP_CIPHER_CTX_free(ctx);

	// 返回解密后的结果
	return decrypted;
}

// 从字符串加载 RSA 公钥
EVP_PKEY* load_public_key_from_string(const std::string& public_key_str) {
	BIO* bio = BIO_new_mem_buf(public_key_str.c_str(), public_key_str.length());
	EVP_PKEY* public_key = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr);
	BIO_free(bio);
	return public_key;
}

// 从字符串加载 RSA 私钥
EVP_PKEY* load_private_key_from_string(const std::string& private_key_str) {
	BIO* bio = BIO_new_mem_buf(private_key_str.c_str(), -1);
	EVP_PKEY* private_key = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, (void*)"");
	BIO_free(bio);
	return private_key;
}

void on_connect(const boost::system::error_code& ec,
	tcp::socket socket,
	websocket::stream<tcp::socket> ws,
	UCHAR pIndex,
	asio::yield_context yield) {
	if (ec) {
		std::cerr << "Connect error: " << ec.message() << std::endl;
		return;
	}
	try {
		// Perform WebSocket handshake
		ws.async_handshake("192.168.122.1", "/websocket", yield);

		while (1) {
			json vJson;
			json vParam;
			vParam["index"] = std::to_string(pIndex);
			vJson["c"] = "ReqUser";
			vJson["a"] = "getEncode";
			vJson["p"] = vParam;
			std::string sendStr = vJson.dump();
			// Send a message
			ws.async_write(asio::buffer(sendStr), yield);

			// Receive a message
			beast::flat_buffer buffer;
			ws.async_read(buffer, yield);

			std::cout << "index:" << std::to_string(pIndex) << ", Received: " << beast::make_printable(buffer.data()) << std::endl;
		}
		// Close the WebSocket connection
		ws.async_close(websocket::close_code::normal, yield);
	}
	catch (const std::exception& e) {
		std::cerr << "Error: " << e.what() << std::endl;
	}
}

int main() {
	/*asio::io_context io_context;
	tcp::resolver resolver(io_context);

	auto endpoints = resolver.resolve("192.168.122.1", "8080");

	for (UCHAR i = 0; i < 3; i++) {
		asio::spawn(io_context, [&, endpoints, i](asio::yield_context yield) {
			UCHAR vIndex = i;
			tcp::socket socket(io_context);
			websocket::stream<tcp::socket> ws(std::move(socket));
			boost::system::error_code ec;
			asio::async_connect(ws.next_layer(), endpoints, yield[ec]);
			asio::spawn(io_context, [&](asio::yield_context yield) {
				on_connect(ec, std::move(socket), std::move(ws), vIndex, yield);
				});
			});
	}
	io_context.run();*/
	/*EVP_PKEY* public_key = load_public_key_from_string("-----BEGIN PUBLIC KEY-----\n"
		"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA30H4zHRoqCNTW0XBG9SO\n"
		"lWX5woPi82nix + h2o2b9H15msUbF2 / HN5h6WjEyeZbv7HvVJw77BYxyiZeQzYcVl\n"
		"d4JH / lElkBtkuMLLdwBeSxwvgsQvlrxMh1ruv8CePtXayZ7nFkto76E9CX6xR9kV\n"
		"Tm + EdDta45SG / IBJmxE1hoX9dbX + ns + 5bigmeS9C / NZIznpr + OGygCf81apAey8f\n"
		"19bJAbZYTjHA2f365Dgtspxm6Slg4US8WK1R5saVyRJ6UP2IGbsQEsTCjGkgV7c4\n"
		"s9 + mSN2c3G8rxyDuH9RWkCDQspkubonBKiG49GTIYiCFXqwXzKpbUIY1y01djbht\n"
		"TQIDAQAB\n"
		"---- - END PUBLIC KEY---- -\n");*/
		// 明文和密钥
	// 文件路径
	std::ifstream publicStream("c:\\public_key.pem");
	std::ifstream privateStream("c:\\private_key.pem");

	// 读取文件内容
	std::string publicContent((std::istreambuf_iterator<char>(publicStream)), std::istreambuf_iterator<char>());
	std::string privateContent((std::istreambuf_iterator<char>(privateStream)), std::istreambuf_iterator<char>());

	std::string plaintext = "Hello, OpenSSL!";
	EVP_PKEY* public_key = load_public_key_from_string(publicContent);
	EVP_PKEY* private_key = load_private_key_from_string(privateContent);

	// 加密
	std::string ciphertext = rsa_encrypt(plaintext, public_key);
	std::cout << "Encrypted: " << ciphertext << std::endl;

	// 解密
	std::string decrypted = rsa_decrypt(ciphertext, private_key);
	std::cout << "Decrypted: " << decrypted << std::endl;
	return 0;
}

标签:std,PKEY,string,openssl,c++,解密,key,EVP,public
From: https://www.cnblogs.com/kuangke/p/17986885

相关文章

  • 用C++11打造智能观察者模式:详解实现步骤完整示例代码
     观察者模式是一种行为设计模式,其中一个对象(主题)维护其依赖对象(观察者)的列表,当主题的状态发生变化时,它通知所有观察者。以下是一个使用C++11实现观察者模式的简单例子:定义观察者接口(Observer): 创建一个观察者接口,该接口包含观察者需要实现的更新方法。这个接口可以包含其他......
  • SHELL AES ECB 加密解密
    SHELLAESECB加密解密AES(高级加密标准)算法可以使用ECB模式进行加密和解密。在Shell中,我们可以通过openssl命令来进行AES的ECB加密和解密操作。下面是示例代码:安装OpenSSL工具包(如果未安装):sudoapt-getinstallopenssl创建一个名为encrypt_decrypt.sh的脚本文件并编写以下......
  • 1. C++ 开发环境
    C++开发环境VisualC++/GCC(G++)/Clang(Clang++)集成开发环境:VisualStudio/CodeLite/Code::blocks/CLion/Eclipse...工具:/usr/bin/timevalgrindcppreferenceCompilerexplorerC++Insights当前各版本编译器对C++20特性的支持情况:查看网站:https://......
  • C/C++ 常用输出流
    在程序设计中,数据输入/输出(I/O)操作是必不可少的,C++语言的数据输入/输出操作是通过I/O流库来实现的。C++中把数据之间的传输操作称为流,流既可以表示数据从内存传送到某个载体或设备中,即输出流,也可以表示数据从某个载体或设备传送到内存缓冲区变量中,即输入流。C++流涉及以下概念:标......
  • KY124 二叉搜索树C++
    先把BST建立起,然后递归遍历判断树就好了。#include<iostream>#include<string>usingnamespacestd;structnode{chardata;structnode*left;structnode*right;};typedefstructnodetree;tree*build(strings){inti=0;tree*root=NULL......
  • KY207 二叉排序树C++
    考二叉搜索树的插入。#include<iostream>usingnamespacestd;structnode{intdata;structnode*left;structnode*right;};typedefstructnodetree;intmain(){intn;while(cin>>n){tree*root=NULL;while(n!=0......
  • KY11 二叉树遍历C++
    这个题目思路其实就是先序遍历的变形。相当于沿着先序遍历的顺序跟着构建二叉树就行。然后中序遍历这个树。#include<iostream>#include<string>usingnamespacestd;structtnode{chardata;structtnode*left;structtnode*right;};typedefstructt......
  • KY212 二叉树遍历C++
    思路是先构造出树,然后在后序遍历整个树。#include<iostream>#include<string>usingnamespacestd;structTnode{chardata;structTnode*left;structTnode*right;};typedefstructTnodeTree;Tree*build(stringpre,inth1,intt1,stringin,inth2......
  • C++ STL Template Traits 技术
    C++的traits技术,是一种约定俗称的技术方案,用来为同一类数据(包括自定义数据类型和内置数据类型)提供统一的类型名(traits),这样可以统一的操作函数,例如advance(),swap(),encode()/decode()等。问题描述首先来看traits技术可以解决什么问题,我们拥有自定义类型Foo,Bar,以及编译......
  • 关于“公钥加密私钥解密,私钥加签公钥验签”的一些理解
    看了网上的很多资料,发现有些点没有说到,也比较复杂,这里根据个人的理解,简单描述,方便记忆。 先理解公/私钥(yue)的意思:私钥,即 私人 的钥匙,是唯一的,所以可以用来证明来源是特定的人公钥,即 公用 的钥匙,我可以将它给很多人(公众)。所以既然那么多人都知道,所以公钥并不能证明来源......