在KawaiiMQTT中使用mbedTLS实现双向认证(Mutual TLS)需要同时配置客户端证书和私钥,并在连接时启用服务器验证。以下是详细步骤和代码实现:
1. 准备工作
确保已获取以下文件:
- CA证书(用于验证服务器证书)
- 客户端证书(用于被服务器验证)
- 客户端私钥(与客户端证书匹配)
- MQTT服务器地址和端口
2. 代码实现
以下是完整的配置步骤:
#include "kawaii_mqtt.h"
#include "mbedtls/platform.h"
#include "mbedtls/ssl.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/pk.h"
// 证书和密钥数据(示例为PEM格式字符串)
const char *ca_cert = "-----BEGIN CERTIFICATE-----n" /* 替换为你的CA证书 */ "n-----END CERTIFICATE-----";
const char *client_cert = "-----BEGIN CERTIFICATE-----n" /* 替换为客户端证书 */ "n-----END CERTIFICATE-----";
const char *client_key = "-----BEGIN PRIVATE KEY-----n" /* 替换为客户端私钥 */ "n-----END PRIVATE KEY-----";
void connect_with_mtls() {
MQTTClient client;
Network network;
// 初始化MQTT客户端
MQTTClientInit(&client, &network, 3000, send_buf, sizeof(send_buf), recv_buf, sizeof(recv_buf));
// 初始化mbedTLS网络层
mbedtls_platform_setup(NULL);
mbedtls_ssl_config conf;
mbedtls_x509_crt cacert;
mbedtls_x509_crt clicert;
mbedtls_pk_context pkey;
mbedtls_ssl_config_init(&conf);
mbedtls_x509_crt_init(&cacert);
mbedtls_x509_crt_init(&clicert);
mbedtls_pk_init(&pkey);
// 解析CA证书(验证服务器)
int ret = mbedtls_x509_crt_parse(&cacert, (const unsigned char *)ca_cert, strlen(ca_cert) + 1);
if (ret != 0) printf("CA cert parse error: -0x%xn", -ret);
// 解析客户端证书和私钥
ret = mbedtls_x509_crt_parse(&clicert, (const unsigned char *)client_cert, strlen(client_cert) + 1);
if (ret != 0) printf("Client cert parse error: -0x%xn", -ret);
ret = mbedtls_pk_parse_key(&pkey, (const unsigned char *)client_key, strlen(client_key) + 1, NULL, 0);
if (ret != 0) printf("Client key parse error: -0x%xn", -ret);
// 配置TLS
mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
// ? 设置客户端证书和私钥(双向认证关键)
mbedtls_ssl_conf_own_cert(&conf, &clicert, &pkey);
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED); // 强制验证服务器证书
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, NULL); // 设置随机数生成器
// 将配置绑定到网络层
NewNetwork_TLS(&network, "mqtt.example.com", 8883, &conf); // 替换为你的MQTT服务器地址
// 连接到MQTT服务器
if (MQTTConnect(&client, &connect_options) != 0) {
printf("MQTT connect failed!n");
} else {
printf("Connected with mTLS!n");
}
// 后续MQTT操作(订阅、发布等)
// ...
// 清理资源
mbedtls_pk_free(&pkey);
mbedtls_x509_crt_free(&clicert);
mbedtls_x509_crt_free(&cacert);
mbedtls_ssl_config_free(&conf);
}
3. 关键配置说明
加载证书/密钥:
- 使用
mbedtls_x509_crt_parse()加载CA证书和客户端证书。
- 使用
mbedtls_pk_parse_key()加载客户端私钥。
启用双向认证:
mbedtls_ssl_conf_own_cert(&conf, &clicert, &pkey):设置客户端自己的证书和私钥,这是双向认证的核心。
服务器验证:
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED):强制验证服务器证书(防止中间人攻击)。
TLS连接:
- 使用
NewNetwork_TLS()建立安全的TCP连接,并传入mbedTLS配置conf。
4. 常见问题排查
- 证书格式错误:确保证书是PEM格式(以
-----BEGIN CERTIFICATE-----开头)。
- 私钥不匹配:客户端私钥必须与证书匹配。
- 服务器配置:确认服务器已启用客户端证书验证。
- 调试输出:检查mbedTLS返回的错误码(如
-0x7F00表示解析失败)。
5. 注意事项
- 内存占用:双向认证需要额外内存存储证书链,在资源受限设备中需评估。
- 证书更新:动态加载证书时可替换硬编码的字符串,改为从文件系统读取。
- 错误处理:务必检查每个mbedTLS函数的返回值。
通过以上步骤,KawaiiMQTT即可通过mbedTLS实现安全的双向认证连接。建议使用工具(如OpenSSL)验证证书链的正确性,并在实际部署前进行充分测试。