我要实现什么目标?
我需要创建一个具有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();
}
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
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.
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可解决此问题。很好,但是我想将其包含在便携式应用程序中。
要实现这一目标,我必须
我是在this script的ps1
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
我将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库添加到项目文件不起作用还是我做错了吗?
答案 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