为何要签名
对 app 进行代码签名可让用户确信它来自已知来源,且自最后一次签名之后未被修改。在您的 Mac app 或 iOS app 可以使用商店服务,安装到 iOS 设备上进行开发或测试,或者提交到 App Store 之前,必须先使用 Apple 颁布的证书对其进行签名。
在 OS X 的安全性与隐私
的设置里有一项设置是允许从以下位置下载的应用程序
,默认的设置是Mac App Store 和被认可的开发者
。
也就是说在用户不手动修改设置的情况下,用户无法打开未签名的程序。
下面就来介绍如何使用 Developer ID 为 app 签名。
注意:本文不适用于发布到 Mac App Store 的签名。
如何签名
将你的 Apple ID 添加到 Xcode
- 打开 Xcode 的 Preferences。
- 选择
Accounts
。 - 点击左下角的加号按钮。
- 填入你的 Apple ID。
加入一个 Program
在添加 Apple ID 的界面,你可以选择 Join a Program...
来加入一个 program。
你也可以让 program 的管理员来将你添加到你们公司的 program。
在 Xcode 中设置 signing identity
- 选择你项目的 target。
- 选择
General
。 - 在
Signing
中选择Developer ID
。 - 在
Team
中选择你加入的 program。
创建 Developer ID certificate
方法一:
首先在自己的电脑上使用钥匙串访问
来创建一个certificate signing request (CSR)
。
- 打开
钥匙串访问
,在菜单栏中选择钥匙串访问 > 证书助理 > 从证书颁发机构请求证书
。 - 填入你的邮件地址和常用名,选择下方的
存储到磁盘
,点击继续选择文件位置保存即可。 - 管理员在 Member Center 里面的
Certificates, Identifiers & Profiles
页面中,选择Certificates
下方的All
。 - 选择右上角的加号按钮。
- 选择
Production
下方的Developer ID
。 - 选择证书类型
Developer ID Application
,点击Continue
。 - 选择前面生成的 CSR(扩展名是 .certSigningRequest) 文件,点击
Continue
。 - 选择
Generate
并且下载证书。 - 将证书导入到 Keychain 中。
方法二:
- 打开 Xcode 的偏好设置,选择
Accounts
选项卡,选择加入的 program,点击View Details
。 - 此时 Xcode 没有找到任何证书,会提示是否要帮你申请证书,此时只要选择以
The Developer ID Application
开头的选项即可。(也可以点击左边的加号来添加一个Developer ID Distribution
) - 等待 program 的管理员来审批。
验证:
方法一:
在 Xcode 的 Preference > Accounts
中选择加入的 program,选择 View Details...
,应该能看到一项 Developer ID Application
。
方法二:
在钥匙串访问中能找到一个名为 Developer ID Application: Your Company Name
的证书。
签名
方法一(使用 Xcode 签名):
- 选择菜单中的
Product > Archive
。 - (可选)选择
Validate...
来验证打包。 - 点击
Export...
- 按照提示选择
Export a Developer ID-signed Application
。 - 选择一个 team。
- 输入文件名,保存即可。
但是使用 Xcode 签名有可能会失败,下面的签名验证部分会提到。
方法二(使用命令行):
1 | codesign --force --verbose=4 --sign "Developer ID Application: Your Company Name" Foo.app |
codesign 要求项目中包含的所有框架、库都已经被签名,并且 codesign 不会自动帮你完成,这需要我们单独为每一个库进行签名后再为整个 app 签名。
签名或验证一个 framework 时使用的路径是MyCustomFramework/Versions/A
,比如
1 | codesign -s "Developer ID Application: Your Company Name" ../MyCustomFramework/Versions/A |
签名时不要使用--deep
参数。
如果 framework 签名失败,可能是由于
- Info.plist 文件中的 CFBundleExecutable 值与可执行文件的文件名不一致。
- 目录结构不对(比如 QT),framework 的目录结构必须与下面完全一样。
1 | MyFramework.framework/ |
签名验证
输入下面的命令:
1 | spctl -a -v Foo.app |
如果验证通过,则会提示:
1 | Foo.app: accepted |
出现下面的提示:
1 | Foo.app: rejected |
此时如果用户通过浏览器或者邮箱接收到安装包再打开 app 时就会提示文件已损坏。
解决方法:
使用下面的命令
1 | codesign --verify --deep --verbose=3 /path/to/signed/app |
找出验证不通过的重新签名,再重新签名整个 app 即可。
脚本
下面是我用来签名的脚本。
1 | #!/usr/bin/python |
参考
http://furbo.org/2013/10/17/code-signing-and-mavericks/
https://github.com/sunuslee/sunus-cookbook/blob/master/Cocoa/codesign.md