我已经成功地数字签署了应用程序,但GateKeeper仍然提供这个投诉.我有一个苹果开发商证书(我是团队代理),我的钥匙扣说它是有效的.我也安装了两个苹果根证书.
我使用命令行实用程序codesign来数字签署应用程序文件夹内的所有二进制文件,另外我对应用程序文件夹本身进行数字签名.在所有情况下,代码的响应都是信息丰富的,不显示任何错误.通过代码签名,我可以检查所有的二进制文件是否已经签名,正在运行
$codesign --verify --deep --verbose=2 MyApp.app
MyApp.app: valid on disk
MyApp.app: satisfies its Designated Requirement
运行:
$codesign -v --verbose=4 --display MyApp.app
给
Executable=/Users/xxx/trunk/yyy/deploy/release/MyApp.app/Contents/MacOS/MyApp
Identifier=aaaa.MyApp
Format=bundle with Mach-O thin (x86_64)
CodeDirectory v=20200 size=12461 flags=0x0(none) hashes=616+3 location=embedded
Hash type=sha1 size=20
CDHash=d1c12c783dac0e8d9a2b749fb896b11558cec8b6
Signature size=8532
Authority=Developer ID Application: XXXXX
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=29 jul. 2015 12;04:40
Info.plist entries=8
TeamIdentifier=YYYYY
Sealed Resources version=2 rules=12 files=10
Internal requirements count=1 size=180
这似乎可以.
运行
$spctl -a -t exec -vv MyApp.app
在所有二进制文件上作为结果
MyApp.app: accepted
source=Developer ID
origin=Developer ID Application: XXXX
这也似乎可以
运行XCode命令行工具检查签名
在应用程序或应用程序文件夹中的二进制文件夹中:
$./check-signature /Users/xxx/trunk/yyy/release/MyApp.app
作为结果
(c) 2014 Apple Inc. All rights reserved.
YES
在所有情况下都是期望的结果.
但是GateKeeper仍然不接受应用程序,并抱怨开发人员无法确认的事实.
[作者于2015年7月17日星期五添加]
我想我已经找到了这个问题.我不知道这是一个功能还是OSX的错误.我被stackoverflow question 19551298帮助了很多.
每当从互联网下载文件时,它会获得与之相关联的扩展文件属性com.apple.quarantine.当在Finder中双击此下载的文件时,GateKeeper有两种可能性:
>当文件未签名时,会发出“不明身份的开发人员等”消息
>当文件被数字签名时,会发出“开发人员无法确认等”的消息
在这两种情况下,MessageBox只有一个按钮,一个OK按钮.当这个按钮被点击时,除了MessageBox关闭之外什么也没有发生.
如果扩展属性被删除(xattr -d),应用程序将运行,不是签名.
当应用程序通过在应用程序的Finder中的鼠标右键单击启动应用程序,然后单击“打开”菜单操作时,行为是不同的.再次显示两个消息框中的一个,但现在有一个额外的按钮允许用户打开应用程序.签名和未签名的唯一区别是“不明”或“未确认”的消息.我不期望我的客户能够告诉差异.因此,签署该应用程序是一项徒劳无功的行为.
在Apple Support Documentation的基础上,我预计GateKeeper在双击下载的应用程序时可能会有更好的行为(或许文档已经过时了,或者我误读了):
>如果应用程序被签名,GateKeeper应该显示一个“从互联网等下载”的MessageBox和一个“继续进行”的按钮.
>如果应用程序没有使用单个OK按钮和文本“Unidentified developer etc ..”签名MessageBox.
解决方法
我终于解决了我的问题.第一个信用:(i)我的另一个stackoverflow question的答案是非常有用的,(ii)通过提交所谓的技术支持事件(TSI),我得到了官方苹果开发商的非常好的(有偿的)建议.
在所有这一切的基础上,我现在可以给出一个非常简明的秘诀,说明如何让您的Mac应用程序成功地被GateKeeper处理.详细介绍食谱之后,我会显示我原来的错误.
Goal: After having developed a Mac app outside Xcode to have GateKeeper issuing the warning “Downloaded from the Internet …” with three buttons,one of which is “open”.
Failure: When GateKeeper issues a warning with either the text “.. unidentified developer..” or the text “.. unconfirmed developer .. ” with – in both cases – a messageBox with a single OK button.
让您的应用程序GateKeeper准备就绪涉及三个步骤:
- Make your app standalone with no unacceptable external dependencies. The only acceptable external dependences are system libraries. All other dependencies should have been copied to your MyApp.app folder. GateKeeper rejects any app that has non-system external dependencies
- Binaries should not be located at illegal positions inside the MyApp.app folder. Libraries go into MyApp/Contents/Frameworks and the executable goes into MyApp/Contents/MacOS
- All binaries inside MyApp should be digitally signed. Then the MyApp.app folder should be signed. For this signing an Apple “Developer ID Application …” certificate is necessary
我们的食谱是自动的.所有的工作都是由一个脚本完成的.在Qt Creator的情况下,我们使用一个qmake脚本,我们通过$$system命令访问系统shell.当使用(Xcode)系统命令中的任何一个(xcode)系统命令,code,spctl或check-signature时,我们假定您已经将stderr重定向到stdout,如answer to question所示.否则,在运行这些实用程序时,您将无法捕获系统响应.在下面我们将不会显式地显示此重定向.
这里是我们的招待会
A. Making the app stand-alone:
- copy (with a script) all the needed binaries to the MyApp.folder
- run (with a script)
install_name_tool -change
andinstall_name_tool -id
such that all dependences inside the app are of the relative type@executable_path/../MacOS..
or@executable_path/../Frameworks
- run (with a script)
otool -L
on all binaries inside the MyApp.app folder and flag any illegal dependence,like “@rpath…” or absolute file paths not being system paths. Note thatotool -L
is not guaranteed to find all dependencies. Plugins are often beyond the horizon ofotool
. That is why you need the next check.- start a terminal at the location “MyApp.app/Contents/MacOS”. Run
export DYLD_PRINT_LIBRARIES=1
. Then run inside the same terminal window./MyApp
. Your terminal will fill up with over hundred loaded libraries. Check this list again for forbidden libraries (libraries present on your computer,but not on the computer of your customers).- proof of the pudding is in the eating. We use the 07002 and check whether or not our app runs there. Alternative solution could be the Mac of a relative who is not a developer. Or you could also create a new user (“test”) on your own Mac and copy the app to its Download (or Desktop folder,or …). In the latter case you must temporarily rename the root folder of your IDE as otherwise the user “test” will find the missing binaries there.
B Signing the app
- Signing: With our script we run
codesign --force --verify --verbose --sign \"Developer ID Application: ....\" \"/path/to/binary\"
on all the binaries in the app and then on the app folder itself. In each case the system response is caught. It should contain in each case the string “signed Mach-O thin”.- Verification: Run (with a script) command
codesign --verify --verbose \"/path/to/binary\"
on each binary in your app and on the app itself and catch the system response. It should in each case contain the strings “valid on disk” and “satisfies its Designated Requirement”.- GateKeeper check: Run (with a script)
spctl -a -t exec -vv /path/to/binary\"
on each binary and on the app folder itself. The system response is caught. It should contain in all cases the string “accepted source”.- check-signature: Run (with a script)
check-signature \"/path/to/banary\"
on each binary and on the app folder itself. The system response is caught. It should contain the string “YES” in each case.C External check
zip your app into a single zip file. Upload to one of your cloud servers
GateKeepers keeps a long list (typically hundreds of items) of exceptions on its general gate-keeper role. Your app must not be in that list if you want to test GateKeeper. Rather than editing this list a much simpler trick is creating a new user on your Mac. Log in to that user and download the zip file from the Internet cloud server. Finder will automatically uncompress it. Click on it. If GateKeeper tells you that it can open the application but it warns you at the same time that it is downloaded from the Internet,it is time to grab a (white) beer.
我的错
我做了大量的安装和签名,没有明确地检查每个二进制文件的结果.之后,我将使用otool -L在一些二进制文件,但不是所有.我错过了从早期的Qt版本升级到Qt 5.5的二进制libqminimal.dylib已经获得了额外的依赖关系,即:QtDBus.我没有注意到,但是GateKeeper做了.
Qt开发人员可能会想知道为什么我们不仅仅是使用macdeployqt在Mac上部署Qt应用程序.首先,我们不喜欢不使用不成文的黑箱实用程序.在互联网论坛上,有相当多的人报告macdeployqt的问题.此外,当比较不同的Qt版本时,Qt库可以具有不同的安装位置(由otool-L报告).当我们有一个新的Qt版本时,我们的脚本将立即开始对被禁止的依赖关系大喊大叫.以这种方式,我们可以获得有关这个新版本发生变化的信息.