公证机制 App Notarization
在osx10.14.5版本中苹果新增了公证机制(App Notarization),关于什么是公证机制大家可以查看这篇文章:《嘶吼RoarTalk:所有开发人员都注意了!苹果将正式采用Notarization机制》
我们重点说一说公证机制给我们开发者带来了什么问题,在2020年1月后,从10.14.5开始所有使用Developer ID 签名的软件都需要被认证才能运行,10.15以后所有软件都默认需要认证。 其实这个具体的版本号如何对我们开发的意义不大,因为很少有软件会针对不同的小版本提供不同的软件安装包。
所以可以简单的总结一下,在2022年做osx系统的应用开发就必须进行应用公证。 公证过后的软件打开时一般系统会询问您是否确定打开应用。如下图:
而不公证的应用就会显示如下,无法打开使用:
公证需要的必备条件
我讲解一下不使用xcode打包的应用进行公证的流程,主要是electron技术栈,也适用一些其他打包应用的技术栈。
签名(codesign)
苹果的签名机制主要使用xcode携带的工具codesign,签名简单来说就是对文件进行一个hash运算生产一个值储存在signature文件中,这里主要说一下codesign常用的几个参数。
-s sign的意思指定一个签名证书,证书格式如下"Developer ID Application: xxxxx公司或者个人开发者 (xxxxxxx唯一标识)"。
-f force强制覆盖已有的签名文件
--options 签名过程中的配置项,最重要的可以设置runtime选项代表应用使用hardruntime强环境运行和签名
--timestamp 签名信息里面是否包含时间信息
--entitlements 指定plist文件路径用来给应用申请相应的运行权限
--deep 递归签名应用中的各种Helper,framerwork等文件
-c 检查签名的应用是否可以通过公证验证
一个包含以上参数的可以通过公证检查的签名命令如下:
codesign -fs "证书"
--options=runtime app路径
--timestamp --deep
--entitlements plist路径`
关于签名的更多信息可以查看《Code Signing Guide》
关于codesign的说明文档访问x-man-page://1/codesign
证书
上面说到了签名需要开发者证书,简单和大家说一下证书。苹果的开发证书分很多种,有个人证书企业证书,大家自己注册个人开发者的话可以在xcode中生成自己的签名证书导入到钥匙串中,公司开发的话一版都是使用公司为主体的企业证书,会给我们个人一个p12的子证书,大家双击安装到钥匙串中就可以。
当安装正式后,我们打开自己的钥匙串 -> 登陆 -> 我的证书如下:
一般大家会看的几种证书在这里
Developer ID Application:
给app文件签名的。3rd Party Mac Developer Installer
给MAS(Mac App Store)签名Developer ID Installer
给类似pkg安装包签名
这里注意一下pkg安装包有专门的签名命令,可以不使用codesign,而使用
productsign
--sign "Developer ID Installer: xxx"
soucre.pkg源文件位置
source_sign.pkg签名后位置
如果不确定自己安装了哪些证书是可以签名的也可以使用命令查询:
security find-identity -v -p codesigning
公证的命令
公证使用xcrun altool命令上传,主要注意需要添加几个必须参数
- --notarize-app 代表本次上传的文件要进行公证
- --primary-bundle-id 应用的bundldID
- --username 签名证书的开发者账号
- --password 专用密码
- --file 要公正上传的文件路径 公证代码如下:
xcrun altool --notarize-app \
--primary-bundle-id "com.xxxxx" \
--username "xxxxxxx@xx.com" \
--password "xxxx-xxxx-xxxx-xxxx" \
--file ./xxx.pkg
注:密码要使用一个专用密码,不建议使用开发者账号的登陆密码,可以前往苹果账号网站生产APP专用密码
公证上传完成后,你会获取到一个字符串作为本次公证请求的标识,后面可以使用这个标识查询公证的结果信息。 公证完成后苹果会给对应的账号邮箱发送邮件,反馈给你公证的结果和对应的原因。 查询代码:
xcrun altool --notarization-info "${UUID}" \
-u "xxxxx@.com" \
-p "xxxx-xxxx-xxxx-xxxx"
UUID是上传完成是获取到的标识。
公证成功后还可以给应用进行盖章操作,把对应的公证信息加入到安装包里面。这部操作具体的作用比这不太了解,加不加这一步都不影响我们要解决的问题,用户使用app弹出不可用的问题。
盖章操作如下:
xcrun stapler staple ./xxxx.pkg
公证报错的各种解决方案
苹果返回的报错信息是很清晰的,大家其实根据报错返回的信息解决就可以。我说一下我自己遇见过的问题吧。
-
You must first sign the relevant contracts online
你的开发者中心有新的协议没有确认同意,登陆一下开发者中心同意一下新的协议就可以了。 -
The signature of the binary is invalid
有二进制文件没有签名,找到这个文件使用codesign单独进行一下签名就可以 -
The binary is not signed with a valid Developer ID certificate
证书无效,解决一下证书的问题 -
The signature does not include a secure timestamp
签名的时候添加一下--timestamp参数 -
The executable does not have the hardened runtime enabled
添加参数--options=runtime
其他的一些苹果有详细的文档说明大家可以看一下,Resolving Common Notarization Issues。 关于签名使用hardened runtime后会出现崩溃无法启动的问题,大多数是由于使用了一些权限但是没有添加到plist文件当中,推荐大家参考Enable hardened runtime (macOS)和Hardened Runtime进行解决。
electron-builder技术栈签名
可以使用electron-notarize依赖进行配置,electron-builder配置提供了afterSign钩子函数,在签名完成后进行公证步骤。具体方法参考Notarizing your Electron application,这也是electron-builder官方推荐的公证方式。
补充最近遇到的大坑,关于用户权限的继承问题
mac的应用在使用用户的摄像机麦克风文件系统录屏等等功能的时候需要授权,大家都知道同一个bundleID的应用签名后的授权应该是可以继承的。
这没有问题,最近我把公司之前只签名没有公证的应用进行了pkg安装包的公证,为了减少安装时用户不知道如何去隐私操作的问题。但是更新后诡异的问题出现了,明明授权了的权限在用户更新后第一次去使用的时候又一次出现了授权弹窗,授权后还依旧无法使用,只有重启应用才可以正常使用。
我苦思冥想找不到问题所在,最后发现不是公证的问题,是发布更新的时候失误,给用户推送了一个没有签名的app文件覆盖安装,这时候就出现这个诡异问题了。最后我总结了一下,虽然苹果应用是继承相同BundleID的权限的但是前提是签名后,所以如果出现签名和不签名的app覆盖更新混用,就会出现诡异的授权问题。这里大家千万要注意不管是安装包还是更新包都要签名啊!