使用Paho进行MQTT TLS连接时报Error [SSL] PEM lib (_ssl.c:4022)错误如何解决
问题原因与修复方案
核心错误原因
- 证书文件与配置字段完全不匹配,这是触发
PEM lib报错的直接原因:- Paho MQTT的
tls参数中,certfile需要填写已签发的客户端证书文件,你配置中对应的certKeyPath指向的是.csr证书签名请求文件,该文件仅用于向CA申请证书,不属于有效证书,SSL库无法解析。 keyfile需要填写客户端私钥文件(你生成的parkingspot.key),但你配置中clientkeypath指向的是已签发的证书.pem文件,私钥与证书配置颠倒。
- Paho MQTT的
- TLS版本过低:你使用的
ssl.PROTOCOL_TLSv1是已被广泛弃用的TLS 1.0协议,绝大多数MQTT Broker(如EMQX)默认禁用该版本,会导致握手失败。 - Payload格式错误:
publish.single的payload参数仅接受字符串/字节类型,你直接传入字典对象会在证书问题修复后触发新的报错。
修复步骤
- 修改
config.ini的[MQTT]段,修正三个证书路径的对应关系:
[MQTT] ipaddress = 172.18.0.3 port = 8883 username = parking password = public cakeypath = /home/atn/Documents/IUK/Abschlussarbeit/emqx_mqtt_cert/ca.pem # 私钥文件对应keyfile字段 clientkeypath = /home/atn/Documents/IUK/Abschlussarbeit/emqx_mqtt_cert/parkingspot.key # 已签发的客户端证书对应certfile字段 certkeypath = /home/atn/Documents/IUK/Abschlussarbeit/emqx_mqtt_cert/parkingspot.pem
- 修改代码中的TLS配置与Payload处理:
- 先导入json模块用于序列化字典
- 将TLS版本替换为TLS 1.2及以上版本
- 把Payload字典转为JSON字符串
import json # ... 原有其他导入不变 # ... 原有逻辑不变 tls = { 'ca_certs': config['MQTT']['cakeypath'], 'certfile': config['MQTT']['certkeypath'], 'keyfile': config['MQTT']['clientkeypath'], # 替换为TLS 1.2版本,适配绝大多数主流Broker配置 'tls_version': ssl.PROTOCOL_TLSv1_2 } # 序列化Payload为JSON字符串 publish.single(topic='parkingStatus', payload=json.dumps(publishInfo), retain=True, hostname=ipAddressMQTT, port=port, keepalive=60, auth=auth, tls=tls, protocol=mqtt.MQTTv311, transport='tcp')
- 可选验证:执行以下openssl命令验证证书有效性,若能正常连接则说明证书配置无误:
openssl s_client -connect 172.18.0.3:8883 -CAfile /home/atn/Documents/IUK/Abschlussarbeit/emqx_mqtt_cert/ca.pem -cert /home/atn/Documents/IUK/Abschlussarbeit/emqx_mqtt_cert/parkingspot.pem -key /home/atn/Documents/IUK/Abschlussarbeit/emqx_mqtt_cert/parkingspot.key
内容的提问来源于stack exchange,提问作者Anh Tu
相关产品推荐
相关产品推荐

