20.4 OpenSSL 套接字AES加密传输

在读者了解了加密算法的具体使用流程后,那么我们就可以使用这些加密算法对网络中的数据包进行加密处理,加密算法此处我们先采用AES算法,在网络通信中,只需要在发送数据之前对特定字符串进行加密处理,而在接收到数据后在使用相同的算法对数据进行恢复即可,读者如果有了套接字编程的基础,那么理解这段代码将变得很容易。

首先来看服务端代码片段,服务端在接受数据之前通过初始化aes_key变量设置一个加密密钥,在收到recv()数据后,直接调用AES函数实现解密,当解密完成后则直接输出原始字符串。

c 复制代码
#include <iostream>
#include <winsock2.h>
#include <WS2tcpip.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/aes.h>
#include <openssl/crypto.h>

extern "C"
{
#include <openssl/applink.c>
}

#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"libssl_static.lib")
#pragma comment(lib,"libcrypto.lib")

// AES加密与解密
void AES(unsigned char* InBuff, unsigned char* OutBuff, unsigned char* key, char* Type)
{
    if (strcmp(Type, "encode") == 0)
    {
        AES_KEY AESEncryptKey;
        AES_set_encrypt_key(key, 256, &AESEncryptKey);
        AES_encrypt(InBuff, OutBuff, &AESEncryptKey);
    }
    else if (strcmp(Type, "decode") == 0)
    {
        AES_KEY AESDecryptKey;
        AES_set_decrypt_key(key, 256, &AESDecryptKey);
        AES_decrypt(InBuff, OutBuff, &AESDecryptKey);
    }
}

int main(int argc, char* argv[])
{
    WSADATA WSAData;
    WSAStartup(MAKEWORD(2, 0), &WSAData);

    SOCKET server_socket;
    server_socket = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in ServerAddr;
    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_port = htons(9999);
    ServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    bind(server_socket, (LPSOCKADDR)&ServerAddr, sizeof(ServerAddr));
    listen(server_socket, 10);

    SOCKET message_socket;
    if ((message_socket = accept(server_socket, (LPSOCKADDR)0, (int*)0)) != INVALID_SOCKET)
    {
        // 生成AES密钥
        unsigned char aes_key[32] = { 0x11,0x22,0x33,0x44 };

        // 使用RSA私钥加密AES的密钥,并发给客户端
        char* encrypt = nullptr;
        int encrypt_length = 0;

        // 接收客户端发来的AES数据,解密输出
        unsigned char Buffer[1024] = {0};
        unsigned char DecodeBuf[1024] = { 0 };

        recv(message_socket, (char *)Buffer, 1024, 0);
        std::cout << "接收加密长度: " << strlen((char *)Buffer) << std::endl;

        AES(Buffer, DecodeBuf, aes_key, (char*)"decode");
        std::cout << "解密内容: " << DecodeBuf << std::endl;

    }
    closesocket(server_socket);
    WSACleanup();
    
    system("pause");
    return 0;
}

接着是客户端代码,如下所示,首先设置aes_key密钥对,此处需要保持服务端与客户端密钥的一致性,在发送数据之前先调用AES算法对字符串进行加密处理,接着在调用send函数将加密后的字节序传输到服务器端。

c 复制代码
#include <iostream>
#include <winsock2.h>
#include <WS2tcpip.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/aes.h>
#include <openssl/crypto.h>

extern "C"
{
#include <openssl/applink.c>
}

#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"libssl_static.lib")
#pragma comment(lib,"libcrypto.lib")

// AES 加密与解密
void AES(unsigned char* InBuff, unsigned char* OutBuff, unsigned char* key, char* Type)
{
    if (strcmp(Type, "encode") == 0)
    {
        AES_KEY AESEncryptKey;
        AES_set_encrypt_key(key, 256, &AESEncryptKey);
        AES_encrypt(InBuff, OutBuff, &AESEncryptKey);
    }
    else if (strcmp(Type, "decode") == 0)
    {
        AES_KEY AESDecryptKey;
        AES_set_decrypt_key(key, 256, &AESDecryptKey);
        AES_decrypt(InBuff, OutBuff, &AESDecryptKey);
    }
}

int main(int argc, char* argv[])
{
    WSADATA WSAData;
    WSAStartup(MAKEWORD(2, 0), &WSAData);
    SOCKET client_socket;
    client_socket = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in ClientAddr;
    ClientAddr.sin_family = AF_INET;
    ClientAddr.sin_port = htons(9999);
    ClientAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    if (connect(client_socket, (LPSOCKADDR)&ClientAddr, sizeof(ClientAddr)) != SOCKET_ERROR)
    {
        unsigned char aes_key[32] = { 0x11,0x22,0x33,0x44 };

        // 使用AES加密数据,并发送给服务端
        char Buffer[1024] = "hello lyshark";
        unsigned char EncodeBuf[1024] = { 0 };

        AES((unsigned char *)Buffer, EncodeBuf, aes_key, (char*)"encode");
    std::cout << "发送加密长度: " << strlen((char *)EncodeBuf) << std::endl;
        send(client_socket, (char *)EncodeBuf, 1024, 0);

        closesocket(client_socket);
        WSACleanup();
    }
    
    system("pause");
    return 0;
}

读者可自行编译上方代码,首先运行服务端然后再运行客户端,至此数据会被加密传输到对端,并使用相同的方式解密,如下图所示;

相关推荐
charlie1145141912 小时前
Cinux · 第一次跳进 Ring 3:用户态与特权隔离
开发语言·c++·操作系统·开源项目
别动我齐刘海2 小时前
机器学习基础2——C++、OpenCV、点云、Open3D
c++·人工智能·opencv·机器学习·计算机视觉·机器人·ros2
躺不平的理查德2 小时前
Windows C++ 第三方库使用流程备忘录--OpenCV
开发语言·c++
余额瞒着我当琳2 小时前
C++STL容器string--迭代器,string的接口,string的遍历,访问方式
c++
郭涤生2 小时前
rootfs 详解与裁剪优化记录
linux·c++·bsp
小小龙学IT3 小时前
C++ std::vector 底层实现深度解析:内存布局、扩容策略、移动语义与迭代器失效
开发语言·c++·算法
码匠许师傅3 小时前
【C++ 面试真题】聊聊 volatile 和 mutable
开发语言·c++·面试
(Charon)4 小时前
【C++】线程安全队列(二):生产者消费者模型与 condition_variable 阻塞等待
c语言·开发语言·c++
痛&快乐着4 小时前
C++之std::map 全面详解:底层原理、最佳实践与踩坑指南
c++
10岁的博客5 小时前
【C++题解】最多共线点问题:小飞拿蛋糕游戏的最优策略
c++