苹果的codesign实用程序如何决定使用哪个SHA算法签署共享库?

16

首先,一些背景:我正在调查为什么我的公司的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中的库都是使用相同的codesign命令进行签名的,通过在运行OS/X 10.12的OS/X构建机器上构建/打包脚本完成。然而,它们计算出来的哈希值却不同。

也就是说,如果我查看其中一个非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框架的签名时,我发现它包含了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哈希值签名的捕获共享库时出现错误的原因。

我的问题(假设我没有完全错了)是:codesign何时决定仅使用sha256哈希值来盖章,而不是同时添加sha1和sha256哈希值?如何强制codesign始终包含两个哈希值,以便我的应用程序可以再次在10.10.x下启动(就像在我们将构建机升级到OSX / Sierra之前那样)?

记录一下,这是我在构建脚本中调用codesign的方式 - 对于所有库(最终具有sha1,sha256和仅具有sha256的Qt框架库和非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"
3个回答

19

经过大量的谷歌搜索,这个答案这个答案带领我找到了解决方案。

问题在于我的应用程序中包含的几个第三方共享库只是使用它们的默认构建设置(例如"./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"

...这对所有库(libssh2、libsndfile、libogg、libflac、libvorbis等)都起作用了,除了libssl——对于那个库,我不得不手动修改Configure文件并将-mmacosx-version-min参数插入到编译器的命令行参数中。

通过这个改变,codesign现在对所有的.dylib文件应用SHA-1和SHA-256哈希,并且生成的.app现在可以在10.10.x下按预期运行。


你好 我目前也遇到了同样的问题,有些地方不是很清楚。 你是否需要在用于构建自己的应用程序的脚本顶部添加导出行,或者在重新构建类似于libsndfile的第三方库之前,在命令行中添加这些导出行? - nmud
我有一个顶层构建脚本,它调用下层构建脚本来构建库,然后是最终的下层构建脚本,用于构建使用这些库的应用程序。我将上述导出命令放在顶层构建脚本的顶部,以便LDFLAGS、CFLAGS和CXXFLAGS环境变量对所有构建脚本(库和应用程序)都可用。 - Jeremy Friesner
好的。在我的情况下,我正在构建一个Qt应用程序,因此我需要使用那些导出标志先重新构建第三方库,然后在库正常之后重新构建我的应用程序。问题是我已经使用brew构建了libsndfile等第三方库,所以我不知道是否可以像./configure CFLAGS="..."这样做。 - nmud
我发现为了解决这个问题,我必须避免使用brew :( - Jeremy Friesner
实际上,我认为我需要重新构建每个库,而不使用brew,这样我就可以更好地控制。感谢您的帮助! - nmud
显示剩余4条评论

2

Jeremy Friesner的答案对我很有帮助。关于编译OpenSSL的一点小提示,至少在1.0.2h版本中不需要更改Configure文件。以下命令可以正常工作。

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

0

只有当您针对 macOS 10.14 或更高版本时,它才停止使用 SHA-1。

对我而言,设置 MACOSX_DEPLOYMENT_TARGET = 10.14 可行(需要将其设置为构建和链接的环境变量以在 Xcode 之外进行构建和链接,并且可以在 Xcode 的目标配置中为 Xcode 自身设置)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接