使用OpenSSL 1.1.1d静态编译的Qt 5.13.1产生QSslSocket :: connectToHostEncrypted:TLS初始化失败

时间:2019-10-01 15:32:55

标签: c++ qt c++11 openssl

我要实现什么目标?

我需要创建一个具有SSL支持的便携式(多合一)应用程序。

出了什么问题?

所以我面临的核心问题是要在我的二进制/便携式应用程序中包含SSL支持。

该应用程序的 MCVE 很简单:

项目.pro文件

QT -= gui
QT += network

CONFIG += c++11 console
CONFIG -= app_bundle

SOURCES += \
        main.cpp

INSTALLS += target

项目main.cpp

#include <QCoreApplication>
#include <QSslSocket>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "Is SSL Enabled? " << QSslSocket::supportsSsl();
    qDebug() << "SSL Library Build Version (Qt compiled against): " << QSslSocket::sslLibraryBuildVersionString();
    qDebug() << "SSL Library Version String (available locally): " << QSslSocket::sslLibraryVersionString();

    return a.exec();
}

  • 我的 DEV计算机上的输出

    Is SSL Enabled?  true
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  "OpenSSL 1.1.1d  10 Sep 2019"

开发人员信息

    C:\Users\cybex>echo %PATH%
    C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Strawberry\c\bin;C:\Strawberry\perl\site\bin;C:\Strawberry\perl\bin

    C:\Users\cybex>openssl
    WARNING: can't open config file: /z/extlib/_openssl_/ssl/openssl.cnf
    OpenSSL> version
    OpenSSL 1.0.2g  1 Mar 2016

  • 在新的Windows 10 x86计算机上运行相同的二进制文件会导致:

    Is SSL Enabled?  false
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  ""

测试机信息(完全全新安装-Windows 10 x86)

    C:\Users\cybex>echo %PATH%
    C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\
    C:\Users\cybex>openssl
    'openssl' is not recognized as an internal or external command,
    operable program or batch file.

  • 在新的Windows 7 x64计算机上运行相同的二进制文件会导致:

    Is SSL Enabled?  false
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  ""

测试机信息(已安装驱动程序的Windows 7 x64笔记本电脑)

    C:\Users\Home>echo %PATH%
    C:\Program Files (x86)\OpenSSL\libs;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;C:\Program Files (x86)\OpenSSL\libs;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\
    C:\Users\Home>openssl
    'openssl' is not recognized as an internal or external command, operable program or batch file.

通过查看以上结果,我得出结论,安装OpenSSL可解决此问题。很好,但是我想将其包含在便携式应用程序中。

要实现这一目标,我必须

  1. 通过OpenSSL支持静态编译Qt

我是在this scriptps1 powershell script改编的here on Qt's wiki的帮助下完成此操作的。我添加了以下内容:

  • OpenSSL主页$OPENSSL_HOME

  • 线程数$threads

  • 要使用的体系结构类型$arch

配置如下:

cmd /C "configure.bat -static -debug-and-release -platform win32-g++ -prefix $QtDir `
        -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-freetype -opengl desktop -sql-sqlite -ssl -openssl -I $($OPENSSL_HOME)\include -L$($OPENSSL_HOME)\lib\MinGW`
        -opensource -confirm-license `
        -make libs -nomake tools -nomake examples -nomake tests -v"
cmd /C "mingw32-make -k -j$($threads)"

注释1:

我正在使用-openssl,而不是-openssl-linked。我尝试使用-openssl-openssl-linked构建Qt的几种变体。 -openssl-linked永远无法成功构建,请参阅this post我对原因的解释。

注释2:

我唯一成功完成的静态Qt编译是启用了-ssl -openssl配置标志

OpenSSL安装位于

`$OPENSSL_HOME = "C:\OpenSSL-Win32"` 

使用

中的MinGW库的位置
`$OPENSSL_HOME = "C:\OpenSSL-Win32\lib\MinGW",`

带有文件

Directory: C:\OpenSSL-Win32\lib\MinGW

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2019/09/11     18:11        3347286 libcrypto.a
-a----       2019/09/11     18:10         109020 libcrypto.def
-a----       2019/09/11     18:11         385126 libssl.a
-a----       2019/09/11     18:10          14033 libssl.def
  1. 将链接项目.pro添加到OpenSSL库

我将OpenSSL库添加到.pro文件中(使用针对OpenSSL 1.1.1d构建的预编译Qt-如上所示)

QT -= gui
QT += network

INCLUDEPATH += "C:\OpenSSL-Win32\include"
LIBS += -L"C:\OpenSSL-Win32\lib\MinGW\libssl.a"
LIBS += -L"C:\OpenSSL-Win32\lib\MinGW\libcrypto.a"

CONFIG += c++11 console
CONFIG -= app_bundle

SOURCES += \
        main.cpp

INSTALLS += target

注释3

带有和不带有上面链接的库的二进制大小保持不变

带有上面添加的库的二进制文件(在我的开发机上)的LDD输出为:

Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module

   Size(K) ModuleName                                         FileName
   ------- ----------                                         --------
      6280 SSL-Test.exe                                       C:\Users\cybex\QtProjects\build-SSL-Test-Desktop_Qt_Op...
      1512 ntdll.dll                                          C:\Windows\SYSTEM32\ntdll.dll
       596 KERNEL32.DLL                                       C:\Windows\system32\KERNEL32.DLL
      1500 KERNELBASE.dll                                     C:\Windows\system32\KERNELBASE.dll

具有上面添加的库的二进制文件(在Windows 10 x86测试机上)的LDD输出为:

Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module

   Size(K) ModuleName                                         FileName
   ------- ----------                                         --------
      6280 SSL-Test.exe                                       C:\Users\cybex\Desktop\SSL-Test.exe
      1512 ntdll.dll                                          C:\Windows\SYSTEM32\ntdll.dll
       596 KERNEL32.DLL                                       C:\Windows\system32\KERNEL32.DLL
      1500 KERNELBASE.dll                                     C:\Windows\system32\KERNELBASE.dll

两个 SSL信息输出都是相同的

在非Dev设备上请求SSL连接时的输出是

  

QSslSocket :: connectToHostEncrypted:TLS初始化失败

这是未包含OpenSSL库的结果。

因此,基本上,将静态OpenSSL库添加到项目文件不起作用还是我做错了吗?

2 个答案:

答案 0 :(得分:0)

OpenSSL线程本地存储由每个Qt源代码的“库加载”确定。然后,您需要确保该库与可执行文件静态链接,或者可以通过路径访问。

if (!supportsSsl()) {
    qCWarning(lcSsl, "QSslSocket::connectToHostEncrypted: TLS initialization failed");
    d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
    return;
}

supportsSsl()又如何呢?

/*!
    \internal

    Does the minimum amount of initialization to determine whether SSL
    is supported or not.
*/

bool QSslSocketPrivate::supportsSsl()
{
    return ensureLibraryLoaded();
}

但是根据这里的Qt源代码,“库加载”是一个“更深层的”概念:

bool QSslSocketPrivate::ensureLibraryLoaded()
{
    if (!q_resolveOpenSslSymbols())
        return false;

    const QMutexLocker locker(qt_opensslInitMutex);

    if (!s_libraryLoaded) {
        // Initialize OpenSSL.
        if (q_OPENSSL_init_ssl(0, nullptr) != 1)
            return false;
        q_SSL_load_error_strings();
        q_OpenSSL_add_all_algorithms();

        QSslSocketBackendPrivate::s_indexForSSLExtraData
            = q_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0L, nullptr, nullptr,
                                        nullptr, nullptr);

        // Initialize OpenSSL's random seed.
        if (!q_RAND_status()) {
            qWarning("Random number generator not seeded, disabling SSL support");
            return false;
        }

        s_libraryLoaded = true;
    }
    return true;
}

只要这不是一个远程调试会话,并且此问题的答案很重要,您就需要在DEBUG模式下使用符号构建Qt库(或准备将其用于DEBUG构建),然后只需放置一个断点在此功能中查找最后一个细节,以防止您的Qt应用程序使用OpenSSL。

调试器的答案应指出“ TLS初始化失败”的原因。

答案 1 :(得分:0)

我认为您需要在测试计算机上安装openSSL,可以从此处进行操作 https://code.google.com/archive/p/openssl-for-windows/downloads

Found in this topic