基于boost和QT 实现客户端/服务端TCP双向证书认证与SSL加密

该代码展示了如何使用Boost库中的ASIO组件创建一个SSL/TLS服务器和客户端。服务器接受连接,进行SSL握手,并在接收到数据时进行读写操作。客户端则建立SSL连接,发送请求并接收响应。代码中包含了SSL验证回调函数和证书的使用。
摘要由CSDN通过智能技术生成

服务器代码(boost实现)

#pragma warning(disable : 4996)
#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;

class session
{
public:
	session(boost::asio::io_service& io_service, boost::asio::ssl::context& context)
		: socket_(io_service, context)
	{
	}

	ssl_socket::lowest_layer_type& socket()
	{
		return socket_.lowest_layer();
	}

	void start()
	{
		socket_.async_handshake(boost::asio::ssl::stream_base::server,
			boost::bind(&session::handle_handshake, this,
				boost::asio::placeholders::error));
	}

	void handle_handshake(const boost::system::error_code& error)
	{
		if (!error)
		{
			std::cout << "handshake success" << std::endl;
			socket_.async_read_some(boost::asio::buffer(data_, max_length),
				boost::bind(&session::handle_read, this,
					boost::asio::placeholders::error,
					boost::asio::placeholders::bytes_transferred));
		}
		else
		{
			std::cout << error.message() << std::endl;
			delete this;
		}
	}

	void handle_read(const boost::system::error_code& error,
		size_t bytes_transferred)
	{
		if (!error)
		{
			std::cout << "handle_read success:"<< std::string(data_, bytes_transferred) << std::endl;
			boost::asio::async_write(socket_,
				boost::asio::buffer(data_, bytes_transferred),
				boost::bind(&session::handle_write, this,
					boost::asio::placeholders::error, _2));
		}
		else
		{
			std::cout << "handle_read error" << std::endl;
			delete this;
		}
	}

	void handle_write(const boost::system::error_code& error, size_t bytes_transferred)
	{
		if (!error)
		{
			std::cout << "handle_write success bytes_transferred:" << bytes_transferred << std::endl;
			socket_.async_read_some(boost::asio::buffer(data_, max_length),
				boost::bind(&session::handle_read, this,
					boost::asio::placeholders::error,
					boost::asio::placeholders::bytes_transferred));
		}
		else
		{
			std::cout << "handle_write error" << std::endl;
			delete this;
		}
	}

private:
	ssl_socket socket_;
	enum { max_length = 1024 };
	char data_[max_length];
};

bool verify_callback(bool preverified, boost::asio::ssl::verify_context& ctx)
{
	char subject_name[256];
	X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
	X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
	std::cout << "subject_name:" << subject_name << std::endl;
	return true;
}

class server
{
public:
	server(boost::asio::io_service& io_service, unsigned short port)
		: io_service_(io_service),
		acceptor_(io_service,
			boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string("192.168.1.102"), port)),
		context_(boost::asio::ssl::context::sslv23)
	{
		context_.set_options(
			boost::asio::ssl::context::default_workarounds
			| boost::asio::ssl::context::no_sslv2
			| boost::asio::ssl::context::single_dh_use);
		//context_.set_password_callback(boost::bind(&server::get_password, this, _1, _2));
		context_.use_certificate_chain_file("server.crt");
		context_.use_private_key_file("private_server.key", boost::asio::ssl::context::pem);
		context_.set_default_verify_paths();
		context_.set_verify_mode(boost::asio::ssl::verify_peer | boost::asio::ssl::verify_fail_if_no_peer_cert);
		context_.set_verify_callback(verify_callback);

		session* new_session = new session(io_service_, context_);
		acceptor_.async_accept(new_session->socket(),
			boost::bind(&server::handle_accept, this, new_session,
				boost::asio::placeholders::error));
	}

	std::string get_password(std::size_t  max_length, boost::asio::ssl::context_base::password_purpose password_purpose)
	{
		std::cout << "get_password" << std::endl;
		return "boost Server";
	}

	void handle_accept(session* new_session,
		const boost::system::error_code& error)
	{
		if (!error)
		{
			std::cout << "accept success" << std::endl;
			new_session->start();
			new_session = new session(io_service_, context_);
			acceptor_.async_accept(new_session->socket(),
				boost::bind(&server::handle_accept, this, new_session,
					boost::asio::placeholders::error));
		}
		else
		{
			std::cout << "accept error" << std::endl;
			delete new_session;
		}
	}

private:
	boost::asio::io_service& io_service_;
	boost::asio::ip::tcp::acceptor acceptor_;
	boost::asio::ssl::context context_;
};

int main(int argc, char* argv[])
{
	boost::asio::io_service io_service;
	boost::asio::io_service::work work(io_service);

	using namespace std; // For atoi.
	server s(io_service, 20000);

	io_service.run();
	return 0;
}

客户端(boost实现)

#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <iostream>
using namespace boost::asio;


bool verify_callback(bool preverified, boost::asio::ssl::verify_context& ctx)
{
	char subject_name[256];
	X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
	X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
	std::cout << "subject_name:" << subject_name << std::endl;
	return true;
}

io_service service;

int main(int argc, char* argv[]) {
	typedef ssl::stream<ip::tcp::socket> ssl_socket;
	ssl::context ctx(ssl::context::sslv23);
	ctx.set_default_verify_paths();
	ctx.set_options(
		boost::asio::ssl::context::default_workarounds
		| boost::asio::ssl::context::no_sslv2
		| boost::asio::ssl::context::single_dh_use);
	ctx.use_certificate_chain_file("cilent.crt");
	ctx.use_private_key_file("private_cilent.key", boost::asio::ssl::context::pem);
	// 打开一个到指定主机的ssl socket
	io_service service;
	ssl_socket sock(service, ctx);
	boost::system::error_code code;
	sock.lowest_layer().connect(ip::tcp::endpoint(ip::address::from_string("192.168.1.102"), 20000), code);
	if (code)
	{
		std::cout << "connect error" << std::endl;
		return 0;
	}
	std::cout << "connect success" << std::endl;
	// ssl 握手
	sock.set_verify_mode(ssl::verify_peer | ssl::verify_fail_if_no_peer_cert);
	sock.set_verify_callback(verify_callback);
	boost::system::error_code ec;
	sock.handshake(ssl_socket::client);
	std::string req = "get /index.html http/1.0\r\nhost: 172.16.8.118\r\naccept: */*\r\nconnection: close\r\n\r\n";
	write(sock, buffer(req.c_str(), req.size()));
	char buff[512];
	while (true) {
		int bytes = read(sock, buffer(buff, 80), ec);
		if (bytes > 0)
		{
			std::cout << "bytes:" << bytes << std::string(buff, bytes);
		}
	}
	return 1;
}

客户端(QT实现)

QFile file("D:/Users/Documents/untitled111/cilent.crt");
    if(!file.open(QIODevice::ReadOnly))
        return;

    QSslCertificate cert(file.readAll());
    if(cert.isNull())
        return;

    QFile key("D:/Users/Documents/untitled111/private_cilent.key");
    if(!key.open(QIODevice::ReadOnly))
        return;

    QSslKey clientKey(key.readAll(), QSsl::Rsa);
    QSslConfiguration config;
    config.setPrivateKey(clientKey);
    config.setLocalCertificate(cert);
    config.setPeerVerifyMode(QSslSocket::VerifyPeer);
//    config.setCiphers(QList<QSslCipher>()<<QSslCipher("PSK-AES128-CBC-SHA256"));

    QList<QSslCipher> ls = config.supportedCiphers();
//    for(int i=0;i<ls.count();i++)
//    {
//        qDebug()<<"****"<<ls.at(i).name();
//    }

    m_sslSocket.setSslConfiguration(config);
    m_sslSocket.setProtocol(QSsl::SecureProtocols);
//    connect(&m_sslSocket, &QSslSocket::preSharedKeyAuthenticationRequired, [=](QSslPreSharedKeyAuthenticator *authenticator)
//    {
//        authenticator->setIdentity("QT user");
//        authenticator->setPreSharedKey("1111111222222222222223333333333333333");
//        qDebug()<<"---------------------------------------";
//    });
    connect(&m_sslSocket, &QSslSocket::peerVerifyError, [=](const QSslError &error){
        QSslCertificate c = error.certificate();
        qDebug()<< "cert:" << c.issuerDisplayName() << " error:" << error.errorString();
        m_sslSocket.ignoreSslErrors();
    });
    connect(&m_sslSocket, &QSslSocket::encrypted, [=]()
    {
        m_sslSocket.write("get /index.html http/1.0\r\nhost: 172.16.8.118\r\naccept: */*\r\nconnection: close\r\n\r\n");
    });
    connect(&m_sslSocket, &QSslSocket::readyRead, [=]()
    {
        qDebug()<<"======";
        qDebug()<<m_sslSocket.readAll();
    });
    m_sslSocket.connectToHostEncrypted("192.168.1.102", 20000);

证书与私钥

服务端和客户端各持有证书和私钥,其中证书是由自建CA机构颁发。
利用openssl生成证书和私钥
生成CA自签名根证书和颁发证书

TLS链路协商加密协议方式

1、由客户端发起Client Hello请求,其中带有支持的SSL协议以及支持的加密算法;
在这里插入图片描述
同时交换本地生成的随机数和a*G
在这里插入图片描述
2、服务端根据客户端支持的加密算法和SSL版本,选择后发送Server Hello和b*G,以及数据等
在这里插入图片描述
3、进行加密数据传输(交互)
在这里插入图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你可以使用Boost库来实现一个基于C++的Linux HTTP服务器。以下是一个简单的示例代码: ```cpp #include <iostream> #include <boost/asio.hpp> #include <boost/bind.hpp> class HttpServer { public: HttpServer(boost::asio::io_service& ioService, short port) : acceptor_(ioService, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) { startAccept(); } private: void startAccept() { boost::asio::ip::tcp::socket socket(acceptor_.get_io_service()); acceptor_.async_accept(socket, boost::bind(&HttpServer::handleAccept, this, socket, boost::asio::placeholders::error)); } void handleAccept(boost::asio::ip::tcp::socket& socket, const boost::system::error_code& error) { if (!error) { std::cout << "Accepted connection from: " << socket.remote_endpoint().address().to_string() << std::endl; startAccept(); } } boost::asio::ip::tcp::acceptor acceptor_; }; int main() { boost::asio::io_service ioService; HttpServer server(ioService, 8080); ioService.run(); return 0; } ``` 这个简单的HTTP服务器使用Boost库中的`asio`模块来处理网络通信。它监听8080端口,并在有新连接时打印客户端IP地址。你可以根据需要扩展这个示例,添加HTTP请求处理逻辑。 请注意,这只是一个基本的示例,实际的HTTP服务器可能需要更多的功能和复杂性。你可能需要处理HTTP请求、路由、静态文件服务、动态内容生成等。但是,这个示例应该可以帮助你入门并了解如何使用Boost库构建一个简单的Linux C++ HTTP服务器。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值