Files
--hp-socket-TCP--ssl--/Client-Native/SSLClientConnection.cpp
2026-01-23 08:39:07 +08:00

258 lines
6.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "pch.h"
#include "SSLClientConnection.h"
namespace SSLClient {
SSLClientConnection::SSLClientConnection()
: m_sslContext(nullptr)
, m_ssl(nullptr)
, m_socket(INVALID_SOCKET)
, m_isConnected(false)
{
}
SSLClientConnection::~SSLClientConnection()
{
Cleanup();
}
bool SSLClientConnection::InitializeWinsock()
{
WSADATA wsaData;
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != 0) {
std::cerr << "[错误] WSAStartup失败错误码: " << result << std::endl;
return false;
}
return true;
}
bool SSLClientConnection::Initialize(const char* clientCert, const char* clientKey,
const char* caCert, const char* keyPassword)
{
// 初始化Winsock
if (!InitializeWinsock()) {
return false;
}
std::cout << "[客户端] 正在初始化SSL环境..." << std::endl;
// 创建SSL上下文
m_sslContext = SSL_CTX_new(TLS_client_method());
if (!m_sslContext) {
CertificateManager::PrintSSLError("创建SSL上下文失败");
return false;
}
// 设置验证模式:验证服务器证书
SSL_CTX_set_verify(m_sslContext, SSL_VERIFY_PEER, nullptr);
// 加载CA证书
X509* ca = m_certManager.LoadCertificateFromMemory(caCert);
if (!ca) {
return false;
}
X509_STORE* store = SSL_CTX_get_cert_store(m_sslContext);
if (X509_STORE_add_cert(store, ca) != 1) {
CertificateManager::PrintSSLError("添加CA证书失败");
X509_free(ca);
return false;
}
X509_free(ca);
// 加载客户端证书
X509* cert = m_certManager.LoadCertificateFromMemory(clientCert);
if (!cert) {
return false;
}
if (SSL_CTX_use_certificate(m_sslContext, cert) != 1) {
CertificateManager::PrintSSLError("使用客户端证书失败");
X509_free(cert);
return false;
}
X509_free(cert);
// 加载客户端私钥
EVP_PKEY* pkey = m_certManager.LoadPrivateKeyFromMemory(clientKey, keyPassword);
if (!pkey) {
return false;
}
if (SSL_CTX_use_PrivateKey(m_sslContext, pkey) != 1) {
CertificateManager::PrintSSLError("使用客户端私钥失败");
EVP_PKEY_free(pkey);
return false;
}
EVP_PKEY_free(pkey);
// 验证私钥和证书是否匹配
if (SSL_CTX_check_private_key(m_sslContext) != 1) {
std::cerr << "[错误] 客户端私钥和证书不匹配" << std::endl;
return false;
}
std::cout << "[客户端] SSL环境初始化成功" << std::endl;
return true;
}
bool SSLClientConnection::Connect(const char* address, int port)
{
// 创建socket
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_socket == INVALID_SOCKET) {
std::cerr << "[错误] 创建socket失败错误码: " << WSAGetLastError() << std::endl;
return false;
}
// 设置服务器地址
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(static_cast<u_short>(port));
inet_pton(AF_INET, address, &serverAddr.sin_addr);
// 连接到服务器
std::cout << "[客户端] 正在连接服务器 " << address << ":" << port << " ..." << std::endl;
if (connect(m_socket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cerr << "[错误] 连接失败,错误码: " << WSAGetLastError() << std::endl;
closesocket(m_socket);
m_socket = INVALID_SOCKET;
return false;
}
std::cout << "[客户端] TCP连接成功" << std::endl;
// 创建SSL对象
m_ssl = SSL_new(m_sslContext);
if (!m_ssl) {
CertificateManager::PrintSSLError("创建SSL对象失败");
closesocket(m_socket);
m_socket = INVALID_SOCKET;
return false;
}
// 将SSL绑定到socket
if (SSL_set_fd(m_ssl, static_cast<int>(m_socket)) != 1) {
CertificateManager::PrintSSLError("绑定SSL到socket失败");
SSL_free(m_ssl);
m_ssl = nullptr;
closesocket(m_socket);
m_socket = INVALID_SOCKET;
return false;
}
// 执行SSL握手
std::cout << "[客户端] 正在进行SSL握手..." << std::endl;
int ret = SSL_connect(m_ssl);
if (ret != 1) {
int err = SSL_get_error(m_ssl, ret);
std::cerr << "[错误] SSL握手失败错误码: " << err << std::endl;
CertificateManager::PrintSSLError("SSL_connect");
SSL_free(m_ssl);
m_ssl = nullptr;
closesocket(m_socket);
m_socket = INVALID_SOCKET;
return false;
}
m_isConnected = true;
std::cout << "[客户端] SSL握手完成" << std::endl;
std::cout << "[客户端] 使用的加密套件: " << GetCipherSuite() << std::endl;
return true;
}
bool SSLClientConnection::Send(const std::string& data)
{
if (!m_isConnected || !m_ssl) {
std::cerr << "[错误] 未连接到服务器" << std::endl;
return false;
}
int sent = SSL_write(m_ssl, data.c_str(), static_cast<int>(data.length()));
if (sent <= 0) {
int err = SSL_get_error(m_ssl, sent);
std::cerr << "[错误] 发送失败,错误码: " << err << std::endl;
CertificateManager::PrintSSLError("SSL_write");
return false;
}
std::cout << "[客户端] 发送数据: \"" << data << "\" (" << sent << " 字节)" << std::endl;
return true;
}
int SSLClientConnection::Receive(char* buffer, int bufferSize)
{
if (!m_isConnected || !m_ssl || !buffer || bufferSize <= 0) {
return -1;
}
// 设置socket为非阻塞模式
u_long mode = 1;
ioctlsocket(m_socket, FIONBIO, &mode);
int received = SSL_read(m_ssl, buffer, bufferSize - 1);
// 恢复为阻塞模式
mode = 0;
ioctlsocket(m_socket, FIONBIO, &mode);
if (received > 0) {
buffer[received] = '\0';
std::cout << "[客户端] 收到数据: \"" << buffer << "\" (" << received << " 字节)" << std::endl;
return received;
}
else if (received < 0) {
int err = SSL_get_error(m_ssl, received);
// SSL_ERROR_WANT_READ 和 SSL_ERROR_WANT_WRITE 表示没有数据,不是错误
if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) {
if (err != SSL_ERROR_ZERO_RETURN) { // 忽略正常关闭
std::cerr << "[错误] 接收失败,错误码: " << err << std::endl;
}
return -1;
}
}
return 0; // 没有数据
}
void SSLClientConnection::Disconnect()
{
std::cout << "[客户端] 正在断开连接..." << std::endl;
Cleanup();
m_isConnected = false;
std::cout << "[客户端] 已断开连接" << std::endl;
}
const char* SSLClientConnection::GetCipherSuite() const
{
if (m_ssl) {
return SSL_get_cipher(m_ssl);
}
return "未知";
}
void SSLClientConnection::Cleanup()
{
if (m_ssl) {
SSL_shutdown(m_ssl);
SSL_free(m_ssl);
m_ssl = nullptr;
}
if (m_socket != INVALID_SOCKET) {
closesocket(m_socket);
m_socket = INVALID_SOCKET;
}
if (m_sslContext) {
SSL_CTX_free(m_sslContext);
m_sslContext = nullptr;
}
WSACleanup();
}
} // namespace SSLClient