我开发了一款带有Qt5的Mac应用,所以在Xcode之外。我希望GateKeeper允许我的应用程序在客户端的计算机上运行,而不是发出“无法打开,因为无法确认开发人员的身份”警告。
我已成功对该应用程序进行了数字签名,但GateKeeper仍然附带此投诉。我有一个Apple开发人员证书(我是团队代理),我的钥匙串说它是有效的。我还安装了两个Apple root证书。
我使用命令行实用程序codesign
对app文件夹中的所有二进制文件进行数字签名,此外我还会对app文件夹本身进行数字签名。在所有情况下,协同设计的响应都是信息性的,并且没有显示错误。使用codesign我可以检查确实所有二进制文件都已签名,运行
$ codesign --verify --deep --verbose=2 MyApp.app
显示所有二进制文件已经验证。此外,它报告:
MyApp.app:在磁盘上有效
MyApp.app:满足其指定要求
运行:
$ codesign -v --verbose=4 --display MyApp.app
给出
可执行文件= / Users / xxx / trunk / yyy / deploy / release / MyApp.app / Contents / MacOS / MyApp
Identifier = aaaa.MyApp
格式=捆绑Mach-O thin(x86_64)
CodeDirectory v = 20200 size = 12461 flags = 0x0(none)hashes = 616 + 3 location = embedded
哈希类型= sha1大小= 20
CDHash = d1c12c783dac0e8d9a2b749fb896b11558cec8b6
签名尺寸= 8532
Authority =开发者ID申请:XXXXX
授权=开发者ID认证机构
权限= Apple Root CA
时间戳= 29岁。 2015 12; 04:40
Info.plist entries = 8
TeamIdentifier = YYYYY
密封资源版本= 2规则= 12个文件= 10
内部要求数= 1尺寸= 180
似乎没问题。
正在运行
$ spctl -a -t exec -vv MyApp.app
所有二进制文件上的结果为
MyApp.app:接受了 source =开发者ID origin =开发者ID申请:XXXX
也似乎没问题
运行XCode命令行工具check-signature
在app或app文件夹中的二进制文件上:
$ ./check-signature /Users/xxx/trunk/yyy/release/MyApp.app
结果
在所有案例中(c)2014 Apple Inc.保留所有权利。
是的
是期望的结果。
但是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,其中包含“从网上下载等”和一个“仍然继续进行”的按钮?
如果应用程序未使用单个“确定”按钮和“未识别的开发人员等”文本对MessageBox进行签名,则
答案 0 :(得分:16)
很抱歉回答我自己的问题,但我没有别的办法,因为编辑原始问题会导致意大利面条文字。
我终于解决了我的问题。首先是信用:(i)我的其他stackoverflow question的答案非常有用,(ii)我通过提交所谓的技术支持事件(TSI)得到了Apple官方开发人员的非常好(付费)建议)。
基于这一切,我现在能够在这里给出一个非常简洁的方法,说明如何通过GateKeeper成功处理您的Mac应用程序。详细说明食谱后,我将展示我原来的错误。
目标:在Xcode之外开发了一个Mac应用程序,让GateKeeper发出警告"从互联网下载......"有三个按钮,其中一个是"打开"
失败:当GateKeeper向文本" ..身份不明的开发者发出警告时。"或文本" ..未经证实的开发者.."在两种情况下都带有一个带有一个OK按钮的消息框。
获取应用程序GateKeeper就绪包含三个步骤:
- 让您的应用程序独立,没有不可接受的外部依赖关系。唯一可接受的外部依赖是系统库。应将所有其他依赖项复制到MyApp.app文件夹。 GateKeeper拒绝任何具有非系统外部依赖性的应用程序
- 二进制文件不应位于MyApp.app文件夹内的非法位置。库进入MyApp / Contents / Frameworks,可执行文件进入MyApp / Contents / MacOS
- MyApp中的所有二进制文件都应进行数字签名。然后应签署MyApp.app文件夹。为此签署Apple"开发者ID申请......"证书是必要的
我们的食谱是自动的。所有工作都由一个脚本完成。在Qt Creator的情况下,我们使用qmake脚本,我们通过$$system
命令访问系统shell。使用(Xcode)系统命令之一codesign
,spctl
或check-signature
时,我们假设您已将stderr重定向到stdout ,如answer to question中所述。否则,在运行这些实用程序时,您将无法捕获系统响应。在下文中,我们不会明确地显示此重定向。
这是我们的食谱
一个。让应用程序独立:
- 将所有需要的二进制文件复制(使用脚本)到MyApp.folder
- 运行(使用脚本)
install_name_tool -change
和install_name_tool -id
,以便应用内的所有依赖关系都是相对类型@executable_path/../MacOS..
或@executable_path/../Frameworks
- 在MyApp.app文件夹中的所有二进制文件上运行(使用脚本)
otool -L
并标记任何非法依赖,例如" @rpath ..."或绝对文件路径不是系统路径。请注意,otool -L
无法保证找到所有依赖项。插件通常超出otool
的范围。这就是你需要下一次检查的原因。- 在位置" MyApp.app/Contents/MacOS"处启动终端。运行
export DYLD_PRINT_LIBRARIES=1
。然后在同一个终端窗口./MyApp
内运行。您的终端将填满数百个已加载的库。再次检查此列表是否有禁止的库(计算机上存在的库,但客户的计算机上没有)。- 布丁的证据就在吃。我们使用MacInCloud virtual machines并检查我们的应用是否在那里运行。替代解决方案可能是不是开发人员的亲属的Mac。或者您也可以在自己的Mac上创建一个新用户(" test")并将应用程序复制到其下载(或桌面文件夹,或......)。在后一种情况下,您必须临时重命名IDE的根文件夹,否则用户" test"会在那里找到丢失的二进制文件。
醇>B签署应用
- 签名:使用我们的脚本,我们在应用程序中的所有二进制文件上运行
codesign --force --verify --verbose --sign \"Developer ID Application: ....\" \"/path/to/binary\"
,然后在应用程序文件夹本身上运行。在每种情况下都会捕获系统响应。它应该在每种情况下都包含字符串"签名的Mach-O thin"。- 验证:对应用程序中的每个二进制文件和应用程序本身运行(使用脚本)命令
codesign --verify --verbose \"/path/to/binary\"
,并捕获系统响应。它应该在每种情况下包含字符串"在磁盘上有效"并且"满足其指定要求"。- GateKeeper检查:在每个二进制文件和app文件夹本身上运行(使用脚本)
spctl -a -t exec -vv /path/to/binary\"
。捕获系统响应。它应该在所有情况下都包含字符串"接受的来源"。- check-signature:在每个二进制文件和app文件夹本身上运行(带脚本)
醇>check-signature \"/path/to/banary\"
。捕获系统响应。它应该包含字符串" YES"在每种情况下。C外部检查
将您的应用压缩到一个zip文件中。上传到您的某个云服务器
- 醇>
GateKeepers在其常规守门员角色上保留了长列表(通常为数百项)异常。如果要测试GateKeeper,您的应用必须不在该列表中。而不是编辑此列表更简单的技巧是在Mac上创建新用户。登录该用户并从Internet云服务器下载zip文件。 Finder会自动解压缩它。点击它。如果GateKeeper告诉您它可以打开应用程序,但它会在从Internet下载的同时向您发出警告,那么现在是时候抓一个(白色)啤酒了。
我的错误
我做了大量的安装和签名,没有明确检查每个二进制文件的结果。在那之后,我会在许多二进制文件上使用otool -L
,但不是全部。我错过了从早期的Qt版本升级到Qt 5.5的事实,二进制libqminimal.dylib
已经获得了额外的依赖,即:QtDBus
。我没有注意到它,但是GateKeeper做到了。
Qt开发人员可能想知道为什么我们不只是使用macdeployqt
在Mac上部署Qt应用程序。首先,我们不喜欢不使用记录不良的黑盒实用程序。在互联网论坛上,有很多人报告macdeployqt
的问题。此外,在比较不同的Qt版本时,Qt库可以具有不同的安装位置(由otool-L
报告)。当我们有一个新的Qt版本时,我们的脚本将立即开始对禁止的依赖关系大喊大叫。通过这种方式,我们可以获得有关此新版本中已更改内容的信息。
答案 1 :(得分:1)
otool -l $file | grep -A2 LC_RPATH
和install_name_tool -delete_rpath $path $file
检查和删除二进制文件和库中的嵌入路径install_name_tool
。spctl -a -t exec -vv /path/to/binary
。您将收到有关资源信封的错误。这是预期的,而不是问题。macdeployqt
工作正常。我通过更改构建来解决问题,这样绝对路径没有进入有问题的dylib文件(libquazip)。我仍然使用install_name_tool
来删除Qt安装的绝对路径。然后,我使用macdeployqt
创建捆绑包,签署捆绑包并创建DMG文件。答案 2 :(得分:1)
我的两位:
要真正验证代码签名,我必须将我的DMG上传到 服务器并使用浏览器下载或手动设置隔离属性:
APP_PATH="Any.app"
xattr -w com.apple.quarantine '0081;5a37dc6a;Google Chrome;F15F7E1C-F894-4B7D-91B4-E110D11C4858' "$APP_PATH"
xattr -l "$APP_PATH" # You should see the quarantine attribute here
open "$APP_PATH"
如果您的应用已正确签名,您应该会看到一个系统对话框 一个“打开”按钮。
我通过查看另一个来找到隔离属性的值 .app从网上下载。我不知道有什么价值 装置
我真的不明白为什么spctl命令说“接受”了 如果Gatekeeper服务拒绝打开应用程序。
我有“未识别的开发人员”消息框,因为我的Qt框架被引用为“ @rpath /QtCore.framework”。使用install_name_tool将其更改为“ @application_path /../ Frameworks /QtCore.framework”修复了我的应用中的问题。
答案 3 :(得分:0)
经过多次尝试后想出问题。
在我的情况下: 流行消息 - 损坏的应用程序是由于库丢失。 我使用QT创建了.app文件。 要生成dmg,我使用的是deploymacqt命令工具。 deploymacqt工具在.app中创建动态库,所以基本上如果我们在创建dmg之前进行协同编码,这个alter会操纵代码符号。 所以正确的解决方法是。
# Create dmg using
deploymacqt <yourapp.app> -dmg
# Open resulted dmg file, copy <yourapp.app> to different folder(let's say /Documents/<yourapp.app>)
# Codesign the /Documents/<yourapp.app> using
codesign --deep --force --verify --verbose --sign "Developer ID Application: <developerid>" <yourapp.app>
# Verify using
codesign --verify --verbose=4 <yourapp.app>
* you should see something like this
<yourapp.app>: valid on disk
<yourapp.app>: satisfies its Designated Requirement
# Now create again the dmg file using dropdmg(https://c-command.com/dropdmg/) application, download, install dropdmg. set the cofiguration preferences with your developer id certificate in signing option.
# drag and drop <yourapp.app> to dropdmg app, wait for creation of dmg to complete. voila you have now successfully created dmg with proper developer id certification.
# verify resulted dmg again using
codesign --verify --verbose=4 <yourapp.dmg>
# you can also verify with gatekeeper
spctl -a -t exec -vv <yourapp.dmg>
答案 4 :(得分:0)
您需要使用可执行文件和框架的命令行otool -l
验证所有rpath。如果可执行文件中有本地rpath(例如:/ user / name / Qt /),请删除它(使用此命令install_name_tool -delete_rpath
)。