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;
}

浙公网安备 33010602011771号