对于pyinstaller打包的MacOS应用该如何进行签名公证?

因为MacOS10.15以后,app store以外的MacOS应用是需要苹果的签名公证的。对于pyinstaller打包生成的MacOS应用,该如何进行MacOS应用的签名公证?(其实就是苹果要收钱,做签名公证必须每年要交大约700人民币的开发者订阅费)

喜欢这个问题 | 分享 | 新建回答

回答

jerkzhang

Feb 25, 2022
1 赞

准备工作:

1、注册苹果开发者账号,不管是个人的还是公司的苹果开发者账号都行;
2、保证已经安装了Xcode,如尚未安装,自己去app store中下载Xcode即可;
3、保证已经安装了Xcode Command Line Tools,如尚未安装,在terminal终端命令行中输入“xcode-select --install”即可开始安装;
4、选择合适版本的pyinstaller,尽量新一点,别用太老的pyinstaller,好像是必须大于4.5版本。

第一步:配置开发者证书,并进行签名

打开“启动台 - 其他 - 钥匙串访问”;

钥匙串访问

如下图所示,在“ 钥匙串访问”的菜单中选择 “证书助理 - 从证书颁发机构请求证书...”;

从证书颁发机构请求证书

在弹窗中填写信息,填写信息完成后保存到本地,
文件名为“CertificateSigningRequest.certSigningRequest

注意,选择“存储到磁盘”。

证书助理

登录苹果开发者账号 https://developer.apple.com/account/
点击左边侧栏上的“Certificates, Identifiers & Profiles”,进入Certificates, Identifiers & Profiles页面。

点击添加证书按钮(加号或者是“Create a certificate”按钮都是创建新证书的功能按钮)

选择如下选项:

Developer ID Application
This certificate is used to code sign your app for distribution outside of the Mac App Store.

意思是这个证书就是为了分发在Mac APP Store外的MacOS应用的;上传之前请求生成并保存在本地的“CertificateSigningRequest.certSigningRequest”文件即可。

创建证书时选择“Developer ID Application”

上传的时候,会有选择“G2 Sub-CA (Xcode 11.4.1 or later)”还是“Previous Sub-CA”,选择“Previous Sub-CA”即可,如果你的Xcode足够新,选择前者也可以。这类证书只要保持开发者账户每年成功扣费,证书都会有效,但是注意一下“Any certificates created after Feb 01, 2022 and associated to the previous Sub-CA will expire on Feb 01, 2027.”这句话,意思就是2022年2月1日之后,如果是选择Previous Sub-CA证书进行公证的应用,在2027年2月1日以后都会失效的,所以如果环境条件允许的话,建议采用G2吧。不过,也没关系,大不了2027年以后再换证书呗……

上传成功后,会生成证书供下载,下载即可,会得到一个叫“developerID_application.cer”的证书。

双击下载好的证书,先点击“查看证书”,把证书名的完整版给记下来,再点击“添加”。证书名大概就是类似Developer ID Application: XXX (XXX)的字符串,之后会用到,但XXX记得补全成自己的证书名。

回到苹果开发者网站的“Certificates, Identifiers & Profiles”页面左边栏的“Identifiers”,为APP创建ID,即Bundle ID,也叫“Bundle identifier”,就是APP ID。

APP ID分为两种,

  • Explicit App ID「明确的 App ID」,一般格式是:com.company.appName;这种 id 只能用在一个app上,每一个新应用都要创建并只有一个。
  • Wildcard App ID「通配符 App ID」, 一般格式是:com.domainname.* ;这种 id 可以用在多个应用上,虽然方便,但是使用这种id的应用不能使用通知功能,所以不常用。

如果没有要用通知等功能的需求,可以创建一张野卡(Wildcard)方便一点,不需要以后每次都创建即可。但如果有明确需求要通知等功能,那就创建Explicit APP ID即可。总之创建成功后,记住该APP ID,之后打包的时候要用。



在原有pyinstaller打包app的基础上加入如下两个参数:

--osx-bundle-identifier BUNDLE_IDENTIFIER
                        Mac OS .app bundle identifier is used as the default
                        unique program name for code signing purposes. The
                        usual form is a hierarchical name in reverse DNS
                        notation. For example:
                        com.mycompany.department.appname (default: first
                        script's basename)
--codesign-identity IDENTITY
                        Code signing identity (macOS only). Use the provided
                        identity to sign collected binaries and generated
                        executable. If signing identity is not provided, ad-
                        hoc signing is performed instead.

--osx-bundle-identifier对应的是APP ID,
也就是上述生成的“Bundle ID”,也就是上述类似“com.domainname.* ”的字符串;

--codesign-identity 对应的是上述的证书名,
即类似Developer ID Application: XXX (XXX)的字符串。

加上后的pyinstaller命令类似如下示例:

pyinstaller -w -D --icon xxx.icns --osx-bundle-identifier "com.domainname.*" --codesign-identity "Developer ID Application: XXX (XXX)" target.py

上述只是一个例子,但osx-bundle-identifier和codesign-identity参数要带上。



登录开发者账户对应的APPLE ID账户中,生成一个“APP专用密码”。
因为之后要用到这个专用密码。

App 专用密码

接下来对生成的MacOS的APP进行公证。

xcrun altool --notarize-app -t osx -f "XXX.zip" --primary-bundle-id "com.domainname.*" -u "开发者账户登录名" --password "APP专用密码"

注意,要在上传前,把.app文件打包成.zip文件。zip文件上传成功后会提示成功上传的。一般几分钟-1小时就能公证完成了(通常情况下是几分钟就ok了),届时会自动发邮件通知的。

另外建议打包成zip的方式参考如下这种方式,避免报错。

ditto -c -k --sequesterRsrc --keepParent "XXX.app" "XXX.app.zip"

也可以主动查询结果:

xcrun altool --notarization-info "上传成功后返回的一串ID用于查询结果" -u 开发者账户名称 --password "APP专用密码"

主动查询结果的最大作用是公证失败时,主动查询可以查到失败的原因。


自我验证一下该应用是否成功公证:

spctl --verbose=4 --assess --type execute XXX.app

如果结果说到accepted这类积极的词汇,那就是公证成功了。