tls加密通信示例

socket加上tls层实现加密通信示例:

1、生成tls层需要的证书和私钥

# 生成prime256v1曲线私钥(直接生成到代码指定的路径)
openssl ecparam -genkey -name prime256v1 -out device_key.pem

# 生成自签名证书(集成所有参数)
openssl req -x509 -new -key device_key.pem -out device_cert.pem -days 365

2、基于openssl

server端

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#define CERT_FILE "device_cert.pem"
#define KEY_FILE "device_key.pem"
#define PORT 4433
#define BACKLOG 5

SSL_CTX* create_ssl_context() {
    const SSL_METHOD *method = TLS_server_method();
    SSL_CTX *ctx = SSL_CTX_new(method);
    if (!ctx) {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    if (SSL_CTX_use_certificate_file(ctx, CERT_FILE, SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }
    if (SSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    SSL_CTX_set_ecdh_auto(ctx, 1);
    return ctx;
}

void handle_client(SSL *ssl) {
    char buf[1024] = {0};
    int bytes = SSL_read(ssl, buf, sizeof(buf)-1);
    if (bytes > 0) {
        printf("Received: %s\n", buf);
        SSL_write(ssl, "Hello from SSL Server", 21);
    }
}

int main() {
    SSL_CTX *ctx;
    int sockfd, client_fd;
    struct sockaddr_in addr;
    
    // 新增socket初始化代码
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        perror("Bind failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    if (listen(sockfd, BACKLOG) < 0) {
        perror("Listen failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();

    ctx = create_ssl_context();

    printf("Server listening on port %d...\n", PORT);
    
    while (1) {
        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        
        client_fd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len);
        if (client_fd < 0) {
            perror("Accept failed");
            continue;
        }

        SSL *ssl = SSL_new(ctx);
        SSL_set_fd(ssl, client_fd);

        if (SSL_accept(ssl) <= 0) {
            ERR_print_errors_fp(stderr);
        } else {
            printf("Connection from %s\n", inet_ntoa(client_addr.sin_addr));
            handle_client(ssl);
        }

        SSL_shutdown(ssl);
        SSL_free(ssl);
        close(client_fd);
    }

    SSL_CTX_free(ctx);
    close(sockfd);
    return 0;
}

client端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#define HOST "127.0.0.1"  // 使用IP地址更可靠
#define PORT 4433
#define BUFFER_SIZE 1024

SSL_CTX* create_client_context() {
    const SSL_METHOD *method = TLS_client_method();
    SSL_CTX *ctx = SSL_CTX_new(method);
    if (!ctx) {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    // 可选:加载CA证书验证服务端
    // SSL_CTX_load_verify_locations(ctx, "ca.crt", NULL);
    // SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
    
    return ctx;
}

void init_socket_connection(int *sockfd) {
    struct sockaddr_in serv_addr;

    // 创建TCP socket
    if ((*sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket creation error");
        exit(EXIT_FAILURE);
    }

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    // 将IP地址从字符串转换为网络格式
    if (inet_pton(AF_INET, HOST, &serv_addr.sin_addr) <= 0) {
        perror("Invalid address/Address not supported");
        close(*sockfd);
        exit(EXIT_FAILURE);
    }

    // 连接服务器
    if (connect(*sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
        perror("Connection failed");
        close(*sockfd);
        exit(EXIT_FAILURE);
    }
}

int main() {
    SSL_CTX *ctx;
    int sockfd;
    SSL *ssl;
    char buffer[BUFFER_SIZE] = {0};

    // OpenSSL初始化
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();

    // 创建SSL上下文
    ctx = create_client_context();

    // 创建并连接TCP socket
    init_socket_connection(&sockfd);
    printf("Connected to server %s:%d\n", HOST, PORT);

    // 创建SSL连接
    ssl = SSL_new(ctx);
    SSL_set_fd(ssl, sockfd);

    // 执行SSL握手
    if (SSL_connect(ssl) <= 0) {
        ERR_print_errors_fp(stderr);
        goto cleanup;
    }
    
    printf("SSL connected. Cipher: %s\n", SSL_get_cipher(ssl));

    // 发送测试消息
    const char *message = "Hello from SSL Client";
    SSL_write(ssl, message, strlen(message));
    printf("Sent: %s\n", message);

    // 接收响应
    int bytes = SSL_read(ssl, buffer, sizeof(buffer)-1);
    if (bytes > 0) {
        buffer[bytes] = '\0';
        printf("Received: %s\n", buffer);
    }

cleanup:
    // 清理资源
    SSL_shutdown(ssl);
    SSL_free(ssl);
    close(sockfd);
    SSL_CTX_free(ctx);
    return 0;
}

3、基于mbedtls

server端

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "mbedtls/net_sockets.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"

#define CERT_FILE "device_cert.pem"
#define KEY_FILE "device_key.pem"
#define PORT 4433
#define DEBUG_LEVEL 0

static void my_debug(void *ctx, int level, const char *file, int line, const char *str) {
    ((void) level);
    fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str);
}

int main() {
    mbedtls_net_context listen_fd, client_fd;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_ssl_context ssl;
    mbedtls_ssl_config conf;
    mbedtls_x509_crt srvcert;
    mbedtls_pk_context pkey;
    int ret;
    const char *pers = "ssl_server";

    // 初始化结构体
    mbedtls_net_init(&listen_fd);
    mbedtls_net_init(&client_fd);
    mbedtls_ssl_init(&ssl);
    mbedtls_ssl_config_init(&conf);
    mbedtls_x509_crt_init(&srvcert);
    mbedtls_pk_init(&pkey);
    mbedtls_ctr_drbg_init(&ctr_drbg);
    mbedtls_entropy_init(&entropy);

#if DEBUG_LEVEL
    mbedtls_debug_set_threshold(DEBUG_LEVEL);
#endif

    // 生成随机种子
    if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
                                   (const unsigned char *) pers,
                                   strlen(pers))) != 0) {
        printf("Failed: mbedtls_ctr_drbg_seed returned -0x%04x\n", -ret);
        goto exit;
    }

    // 加载证书和私钥
    if ((ret = mbedtls_x509_crt_parse_file(&srvcert, CERT_FILE)) != 0) {
        printf("Failed: mbedtls_x509_crt_parse_file returned -0x%04x\n", -ret);
        goto exit;
    }
    if ((ret = mbedtls_pk_parse_keyfile(&pkey, KEY_FILE, NULL)) != 0) {
        printf("Failed: mbedtls_pk_parse_keyfile returned -0x%04x\n", -ret);
        goto exit;
    }

    // 配置SSL
    if ((ret = mbedtls_ssl_config_defaults(&conf,
                    MBEDTLS_SSL_IS_SERVER,
                    MBEDTLS_SSL_TRANSPORT_STREAM,
                    MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
        printf("Failed: mbedtls_ssl_config_defaults returned -0x%04x\n", -ret);
        goto exit;
    }

    mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
    mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
    mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL);
    if ((ret = mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey)) != 0) {
        printf("Failed: mbedtls_ssl_conf_own_cert returned -0x%04x\n", -ret);
        goto exit;
    }

    // 启动TCP监听
    if ((ret = mbedtls_net_bind(&listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP)) != 0) {
        printf("Failed: mbedtls_net_bind returned -0x%04x\n", -ret);
        goto exit;
    }

    printf("Server listening on port %d...\n", PORT);

    while (1) {
        // 接受客户端连接
        if ((ret = mbedtls_net_accept(&listen_fd, &client_fd, NULL, 0, NULL)) != 0) {
            printf("Failed: mbedtls_net_accept returned -0x%04x\n", -ret);
            break;
        }

        // 设置SSL上下文
        if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
            printf("Failed: mbedtls_ssl_setup returned -0x%04x\n", -ret);
            goto close_client;
        }
        mbedtls_ssl_set_bio(&ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL);

        // 执行SSL握手
        while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
            if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
                printf("Failed: mbedtls_ssl_handshake returned -0x%04x\n", -ret);
                goto close_ssl;
            }
        }

        // 数据交换
        char buf[1024];
        int len;
        // while ((len = mbedtls_ssl_read(&ssl, (unsigned char *)buf, sizeof(buf)-1)) > 0) {
        //     buf[len] = '\0';
        //     printf("Received: %s\n", buf);
        //     mbedtls_ssl_write(&ssl, (const unsigned char *)"Hello from mbedTLS Server", 25);
        // }
        while (1) {
            len = mbedtls_ssl_read(&ssl, (unsigned char *)buf, sizeof(buf)-1);
            if (len == MBEDTLS_ERR_SSL_WANT_READ || len == MBEDTLS_ERR_SSL_WANT_WRITE) {
                continue; // 重试非阻塞操作(若配置了非阻塞模式)
            }
            if (len <= 0) {
                if (len == MBEDTLS_ERR_SSL_CONN_EOF) {
                    printf("Client closed connection gracefully\n");
                } else {
                    // printf("mbedtls_ssl_read error: -0x%04x\n", -len);
                }
                break;
            }
            buf[len] = '\0';
            printf("Received: %s\n", buf);
            mbedtls_ssl_write(&ssl, (const unsigned char *)"Hello from mbedTLS Server", 25);
        }


close_ssl:
        mbedtls_ssl_close_notify(&ssl);
        mbedtls_ssl_free(&ssl);
close_client:
        mbedtls_net_free(&client_fd);
    }

exit:
    // 清理资源
    mbedtls_net_free(&listen_fd);
    mbedtls_x509_crt_free(&srvcert);
    mbedtls_pk_free(&pkey);
    mbedtls_ssl_config_free(&conf);
    mbedtls_ssl_free(&ssl);
    mbedtls_ctr_drbg_free(&ctr_drbg);
    mbedtls_entropy_free(&entropy);
    return 0;
}

client端

#include <stdio.h>
#include <string.h>
#include "mbedtls/net_sockets.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 4433
#define DEBUG_LEVEL 1

static void my_debug(void *ctx, int level, const char *file, int line, const char *str) {
    ((void) level);
    fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str);
}

int main() {
    mbedtls_net_context server_fd;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_ssl_context ssl;
    mbedtls_ssl_config conf;
    int ret;
    const char *pers = "ssl_client";

    // 初始化结构体
    mbedtls_net_init(&server_fd);
    mbedtls_ssl_init(&ssl);
    mbedtls_ssl_config_init(&conf);
    mbedtls_ctr_drbg_init(&ctr_drbg);
    mbedtls_entropy_init(&entropy);

#if DEBUG_LEVEL
    mbedtls_debug_set_threshold(DEBUG_LEVEL);
#endif

    // 生成随机种子
    if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
                                   (const unsigned char *) pers,
                                   strlen(pers))) != 0) {
        printf("Failed: mbedtls_ctr_drbg_seed returned -0x%04x\n", -ret);
        goto exit;
    }

    // 连接服务器
    if ((ret = mbedtls_net_connect(&server_fd, SERVER_IP, "4433", MBEDTLS_NET_PROTO_TCP)) != 0) {
        printf("Failed: mbedtls_net_connect returned -0x%04x\n", -ret);
        goto exit;
    }

    // 配置SSL
    if ((ret = mbedtls_ssl_config_defaults(&conf,
                    MBEDTLS_SSL_IS_CLIENT,
                    MBEDTLS_SSL_TRANSPORT_STREAM,
                    MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
        printf("Failed: mbedtls_ssl_config_defaults returned -0x%04x\n", -ret);
        goto exit;
    }

    mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
    mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);

    // 不验证服务器证书(测试用)
    mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE);

    if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
        printf("Failed: mbedtls_ssl_setup returned -0x%04x\n", -ret);
        goto exit;
    }
    mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);

    // 执行SSL握手
    while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
        if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
            printf("Failed: mbedtls_ssl_handshake returned -0x%04x\n", -ret);
            goto exit;
        }
    }

    // 发送数据
    const char *request = "Hello from mbedTLS Client";
    if ((ret = mbedtls_ssl_write(&ssl, (const unsigned char *)request, strlen(request))) <= 0) {
        printf("Failed: mbedtls_ssl_write returned -0x%04x\n", ret);
        goto exit;
    }

    // 接收响应
    char buf[1024];
    if ((ret = mbedtls_ssl_read(&ssl, (unsigned char *)buf, sizeof(buf)-1)) <= 0) {
        printf("Failed: mbedtls_ssl_read returned -0x%04x\n", ret);
        goto exit;
    }
    buf[ret] = '\0';
    printf("Server response: %s\n", buf);

exit:
    // 清理资源
    mbedtls_ssl_close_notify(&ssl);
    mbedtls_net_free(&server_fd);
    mbedtls_ssl_free(&ssl);
    mbedtls_ssl_config_free(&conf);
    mbedtls_ctr_drbg_free(&ctr_drbg);
    mbedtls_entropy_free(&entropy);
    return ret;
}
posted @ 2025-03-09 12:21  LX2020  阅读(170)  评论(0)    收藏  举报