Qt 解决qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed问题

文章目录

  • 背景
  • 原因
  • 解决方案

背景

Qt 使用QNetwork 模块,进行api请求时发生错误,错误信息:qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed

原因

当你用HTTP形式的时候,会发现没有问题,而使用HTTPS时,则会报错。如果对计算机网络有所了解的人,应该大致懂原因。

因为HTTP 是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。

SSL/TLS 协议建立的详细流程:

  1. Client
    首先,由客户端向服务器发起加密通信请求,也就是 Client的请求。在这一步,客户端主要向服务器发送以下信息:
    (1)客户端支持的 SSL/TLS 协议版本,如 TLS 1.2 版本。
    (2)客户端生产的随机数( Client Random ),后面用于生产「会话秘钥」。
    (3)客户端支持的密码套件列表,如 RSA 加密算法。
  2. Sever
    服务器收到客户端请求后,向客户端发出响应 。服务器回应的内容有如下内容:
    (1)确认 SSL/ TLS 协议版本,如果浏览器不支持,则关闭加密通信。
    (2)服务器生产的随机数( Server Random ),后面用于生产「会话秘钥」。
    (3)确认的密码套件列表,如 RSA 加密算法。
    (4)服务器的数字证书。
  3. 客户端回应
    客户端收到服务器的回应之后,首先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真实性。如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送如下信息:
    (1)一个随机数( pre-master key )。该随机数会被服务器公钥加密。
    (2)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。
    (3)客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供服务端校验。
    上面第一项的随机数是整个握手阶段的第三个随机数,这样服务器和客户端就同时有三个随机数,接着就用双方协商的加密算法,各自生成本次通信的「会话秘钥」。
  4. 服务器的最后回应
    服务器收到客户端的第三个随机数( pre-master key )之后,通过协商的加密算法,计算出本次通信的「会话秘钥」。然后,向客户端发生最后的信息:
    (1)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。
    (2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供客户端校验。
    至此,整个 SSL/TLS 的握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用「会话秘钥」加密内容。

回到qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed,那么这个报错,就是缺少加密的手段,也就是没有提供对HTTP加密的工具,从而无法进行HTTPS通信。

解决方案

那么原因清楚了,就应该知道,我们需要把加密这一步缺少的东西给补上。先说一点,Qt本身是支持ssl的,但是因为法律原因?没有自带对应的dll。

我们先使用这段代码打印当前Qt支持的ssl版本

#include 
#include #include 
qDebug()<< QSslSocket::sslLibraryBuildVersionString();

我这里输出的是

"OpenSSL 1.1.1d  10 Sep 2019"

接下来就去下载OpenSSL

  1. 下载OpenSSL源码,自行编译
    https://www.openssl.org/source/
  2. 直接下载dll
    Openssl下载网站
    我推荐第二个方法,省去自己编译的时间。
    然后在这个网站找到对应的版本,比如我的版本是刚刚打印的1.1.1,同时,也要注意工程是32位还是64位,我这里选择的是Win64 OpenSSL v1.1.1n Light,至于EXE还是MSI都没差异。
    Qt 解决qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed问题_第1张图片

安装的时候,我选择的是第二个,这样可以方便的进行dll文件的拷贝
Qt 解决qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed问题_第2张图片
Qt 解决qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed问题_第3张图片

进入OpenSSL安装目录。bin目录下,拷贝这两个dll文件到工程的exe程序所在路径下
Qt 解决qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed问题_第4张图片

比如我这里的路径,直接放到exe根路径下即可,然后程序即可正常运行。注意黄色框出来的是旧版本的dll,因为有的人Qt版本可能比较低,那么打印出来的OpenSSL 版本可能是1.0.2,那么dll名字大概率就是黄色框的。
Qt 解决qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed问题_第5张图片

这里我也测试了一下,不同OpenSSL 版本的dll是否可以通用,发现高低版本都不行,必须得和Qt 打印出来的OpenSSL 版本一致才行。
另外,很多帖子都是说,把这两个dll文件放到E:\QT\5.12.3\mingw73_64\bin路径下,即Qt的安装路径下。这样也可以,但是我觉得不好,个人认为,尽量别去动Qt安装路径下的文件,保证不会被认为破坏开发环境,或者以后排错,不会导致当时自己把文件放到了Qt安装路径下太久忘记,而在别的电脑上无法正常使用的情况。

你可能感兴趣的:(QT学习笔记,qt,.net,ssl)