Apple 的代码设计实用程序如何决定使用哪些 SHA 算法对共享库进行签名?

How does Apple's codesign utility decide which SHA algorithm(s) to sign a shared library with?

首先,了解一些背景知识:我正在调查为什么我公司的 MacOS/X 申请(从所有方面看来都已正确签署;运行 在 MacOS/X 10 下没问题.11.x 和 10.12.x; Gatekeeper 在所有 MacOS 版本上都很好;"spctl --assess" 和 "codesign -vvvv" 都说它满足所有的要求OS 版本)但不会在 OS/X 10.10.x 下启动 - 在 10.10.x 下,当我尝试启动它时,我收到 dyld 抱怨的崩溃报告某些库未正确签名:

Dyld Error Message:
  Library not loaded:     @executable_path/../Frameworks/libcrypto.1.0.0.dylib
  Referenced from: /Applications/MyApplication v123/MyApplication.app/Contents/MacOS/MyApplication
  Reason: no suitable image found.  Did find:
  /Applications/MyApplication v123/MyApplication.app/Contents/MacOS/../Frameworks/libcrypto.1.0.0.dylib: code signature invalid for '/Applications/MyApplication v123/MyApplication.app/Contents/MacOS/../Frameworks/libcrypto.1.0.0.dylib'

在调查该问题时,我注意到 .app/Contents/Framework 中的库都是使用完全相同的代码签名命令签名的,通过我们 [=32= 上的 build/package 脚本] build machine 运行ning OS/X 10.12 -- 为它们计算了不同种类的哈希值。

也就是说,如果我查看其中一个非 Qt .dylib 文件是如何签名的,我发现它只记录了一个 sha256 哈希值:

sierrabuild-polaris:MyApp v123 autobuild$ codesign -vvvd ./MyApp.app/Contents/Frameworks/libsndfile.1.dylib 
Executable=/Applications/MyApp v123/MyApp.app/Contents/Frameworks/libsndfile.1.dylib
Identifier=libsndfile.1
Format=Mach-O thin (x86_64)
CodeDirectory v=20200 size=4140 flags=0x0(none) hashes=125+2 location=embedded
Hash type=sha256 size=32
CandidateCDHash sha256=b4256e9bf0fac567bb8ac86f56964c066b93d069
Hash choices=sha256     <----------------------------- ONLY 256!?
CDHash=b4256e9bf0fac567bb8ac86f56964c066b93d069
Signature size=8846
Authority=Developer ID Application: MyCompany
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=Jan 24, 2017, 1:39:58 AM
Info.plist=not bound
TeamIdentifier=5XD27G7646
Sealed Resources=none
Internal requirements count=1 size=172

...但是如果我查看任何专属 Qt 框架的签名方式,OTOH,我发现它同时包含 sha1 和 sha256 哈希值:

sierrabuild-polaris:MyApp v123 autobuild$ codesign -vvvd ./MyApp.app/Contents/Frameworks/QtCore.framework/Versions/5/QtCore
Executable=/Applications/MyApp v123/MyApp.app/Contents/Frameworks/QtCore.framework/Versions/5/QtCore
Identifier=org.qt-project.QtCore
Format=bundle with Mach-O thin (x86_64)
CodeDirectory v=20200 size=42549 flags=0x0(none) hashes=1324+3 location=embedded
Hash type=sha256 size=32
CandidateCDHash sha1=09b5854f83091228f1baaad1455e7a30d6500c95
CandidateCDHash sha256=6dfdc74da06618e1b406a6e5fd0794fe43701def
Hash choices=sha1,sha256    <------------- BOTH sha1 and sha256, yay!
CDHash=6dfdc74da06618e1b406a6e5fd0794fe43701def
Signature size=8896
Authority=Developer ID Application: MyCompany
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=Jan 24, 2017, 1:39:57 AM
Info.plist entries=8
TeamIdentifier=5XD27G7646
Sealed Resources version=2 rules=13 files=1
Internal requirements count=1 size=184

考虑到 dyld 在尝试 运行 我在 Yosemite 下的应用程序时的错误总是指的是只有 sha256 哈希的库之一,我的工作理论是 OS/X 10 .10.x 的 dyld 足够古老以至于它不知道 SHA-256 哈希值,这就是为什么它在尝试加载仅使用 SHA-256 签名的强制共享库时出错的原因散列。

我的问题(假设我在这里没有完全找错树)是:协同设计如何决定何时单独使用 sha256 哈希标记文件,而不是同时添加 sha1 和 sha256 哈希?我如何强制代码设计始终包含两个哈希值,以便我的应用程序可以再次在 10.10.x 下启动(就像我们将构建机器升级到 OSX/Sierra 之前一样)?

郑重声明,这是我在构建脚本中调用代码签名的方式——所有库的调用参数完全相同(Qt 框架库以 sha1、sha256 和非仅以 sha256 结尾的 Qt 库),例如:

codesign -f -v -s "Developer ID Application:  MyCompanyName" "./Frameworks/libcrypto.1.0.0.dylib"
codesign -f -v -s "Developer ID Application:  MyCompanyName" "./Frameworks/QtCore.framework/Versions/5/QtCore"

经过大量谷歌搜索后,this answer and this answer 找到了解决方案。

问题是我的应用程序中包含的几个 third-party 共享库仅使用它们的默认构建设置(例如“./configure; make”)进行编译,并且由于它们是在以下条件下编译的OS/X 10.12,当然它们在编译时只考虑了 10.12 的兼容性。

为了让它们以生成的 .dylib 文件也适用于早期 OS/X 版本的方式进行编译,我将这些行添加到我的构建脚本的顶部:

export  LDFLAGS="-mmacosx-version-min=10.9"   
export   CFLAGS="-mmacosx-version-min=10.9"   
export CXXFLAGS="-mmacosx-version-min=10.9"

... 这对除 libssl 之外的所有库(libssh2、libsndfile、libogg、libflac、libvorbis 等)都有效——对于那个库,我必须 hand-modify Configure文件并以这种方式将 -mmacosx-version-min 参数插入编译器的 command-line 参数。

通过这一更改,codesign 现在将 SHA-1 和 SHA-256 哈希应用于所有 .dylib 文件,并且生成的 .app 现在可以在 10.10.x.[=12 下按预期运行=]

Jeremy Friesner 的 对我有用。只是关于编译 OpenSSL 的附注。至少对于 1.0.2h,不需要更改配置文件。以下工作正常

./configure darwin64-x86_64-cc shared --openssldir=$HOME/cmake_builds/openssl-1.0.2h.bin -mmacosx-version-min=10.10