Qt 是否在构建时使其自己的库的数字签名无效?

Is Qt invalidating digital signatures of its own libraries at build-time?

我们有几个使用 Qt 的构建系统。由于我们想节省签署任务的时间,并且我们需要签署我们分发的所有未签署的二进制文件,因此我们继续在其安装位置签署所有 Qt 二进制文件,并且对于我们的一些使用 Qt 依赖项的包管理器,同样设置类型,除了它是被签名的包而不是构建从站上的本地 Qt 目录。

今天我注意到在使用 Qt 项目的 Jenkins 和 TFS 构建流程中,日志中出现了这个小的两行代码:

15:24:19 Updating Qt5Core.dll.
15:24:19 Patching Qt5Core.dll...

随后在 Jenkins 的构建日志中,其数字签名未成功验证,然后使用测试证书签名:

15:24:19 call "C:\Program Files (x86)\Windows Kits\bin\x64\signtool.exe" verify /pa C:\BuildFolder\artifacts\qt5611_win32-msvc2015\release\Qt5Core.dll
15:24:19 IF NOT "!errorlevel!" == "0" echo Self-Signing C:\BuildFolder\artifacts\qt5611_win32-msvc2015\release\Qt5Core.dll & call signtool sign /f C:\DevOps\test_certificates\cert.pfx /fd SHA512 C:\BuildFolder\artifacts\qt5611_win32-msvc2015\release\Qt5Core.dll && set something_signed=true
15:24:19 )
15:24:19 File: C:\BuildFolder\artifacts\qt5611_win32-msvc2015\release\Qt5Core.dll
15:24:19 Index Algorithm Timestamp
15:24:19 ========================================
15:24:19
15:24:19 Number of errors: 1

15:24:19 SignTool Error: No signature found.
15:24:19 Self-Signing C:\BuildFolder\artifacts\qt5611_win32-msvc2015\release\Qt5Core.dll
15:24:19 Done Adding Additional Store 15:24:19 Successfully signed: C:\BuildFolder\artifacts\qt5611_win32-msvc2015\release\Qt5Core.dll

是否有来自 QMakeJOM 的东西使 Updating/Patching 的数字签名无效?如果是这样,这是不可避免的吗?我不太精通在其他操作系统上构建 Qt 项目,但我记得需要使用一些工具来更改库指向的位置。我能想到的最好的情况是 WinDeployQt.

在幕后发生了类似的事情

如果您对 WinDeployQt 报告的内容感兴趣,这是在前两行引用之前运行的内容:

15:24:18 link /NOLOGO /DYNAMICBASE /NXCOMPAT /INCREMENTAL:NO /SUBSYSTEM:CONSOLE "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='removed-by-OP' language='*' processorArchitecture='*'" /MANIFEST:embed /OUT:C:\BuildFolder\bin\release\qt_test_build.exe @C:\Users\USER~1\AppData\Local\Temp\qt_test_build.exe.4012.485.jom
15:24:19 windeployqt -core --no-compiler-runtime --no-quick-import --no-translations C:\BuildFolder\solution_directory\..\bin\release\qt_test_build.exe
15:24:19 C:\BuildFolder\bin\release\qt_test_build.exe 64 bit, release executable
15:24:19 Direct dependencies: Qt5Core
15:24:19 All dependencies : Qt5Core
15:24:19 To be deployed : Qt5Core

qmake 除了它的输出之外不修改任何东西:它唯一的工作是为另一个构建系统生成构建脚本。

jom 是一个 make 工具,可以做 nmake 会做的事情,除非在可能的情况下并行处理多个进程。它只是遵循 makefile 中的指示。我不知道 qmake 中的任何代码会生成修改 Qt 库本身的 makefile 操作 - 除非您在项目文件中明确放置一些会导致这种情况的内容。我也从未见过它发生过。

剩下 windeployqt,它会在 Qt 二进制文件 复制 到目标位置后修补它们,因为二进制文件包含一些嵌入路径等。如果您调用windeployqt 通过您的 makefile/project 文件,那么 Qt 将看起来好像已从 job.

中进行了修改

观察您签名的原始位置中的 Qt 二进制文件是否保持不变。事实上,签名后的 Qt 安装应该 read-only 并设置权限,这样构建本身就不会搞砸,除非 Qt 安装步骤是构建本身的一部分。

唉,有一个简单的解决方法:在您构建安装包之前签署内容 - 这肯定是 windeployqt 之后。为我工作(tm)。如果您的产品包含一个可执行文件,静态构建也可能是一种选择,或者可以采用这种方式。

Qt 5.14.2 中的情况变得更好了。

在较旧的 Qt 5.13.2 中,我可以在 Qt5Core.dll 中找到 qt_prfxpath= 然后是我到该文件的本地路径。 windeployqt 将此路径替换为“.”并写入日志:

Patching Qt5Core.dll...

之后"patching"Qt5Core.dll的Authenticode签名生效 (它在我的本地文件 d:\Qt.13.2\mingw73_64\bin\Qt5Core.dll 上无效)。 Qt 安装程序补丁 Qt5Core.dll 和 windeployqt 似乎将其恢复为出厂默认状态。恕我直言,这是一个糟糕的设计解决方案。

现在,在 Qt 5.14.2 我再也看不到 "qt_prfxpath=" 并且 windeployqt 没有打补丁它。我的本地文件 d:\Qt.14.2\mingw73_64\bin\Qt5Core.dll 的签名已经有效。

所以,Qt 作者似乎已经删除了这个丑陋的补丁。如果是这样,windeployqt 不再是必需的步骤。该实用程序获得了太多过多的库,至少对于我的项目而言。我将摆脱它并在我的构建脚本中明确复制所有内容。