macos应用更新的签名与校验是确保系统信任和安全安装的核心环节。开发者须用有效developer id证书签名并公证更新包,系统通过签名验证、内部代码签名检查、公证票据校验及兼容性检查层层把关,任一环节失败将导致“无法验证开发者”等提示。

macOS 应用更新中的签名与校验不是可有可无的步骤,而是决定更新能否被系统信任、用户能否顺利安装的核心环节。它直接关系到软件来源是否可信、内容是否被篡改、运行是否安全。整个过程由开发者签名、系统验证、框架执行三者协同完成,缺一不可。
签名是更新包的“数字身份证”
开发者在发布更新前,必须使用 Apple 颁发的 Developer ID Application 证书对更新包(.app 或 .pkg)进行 codesign 签名。这个签名包含三重信息:
- 应用二进制内容的加密哈希值——任何字节改动都会导致签名失效
- 开发者身份标识(Team ID + 名称)——系统据此判断是否为已知可信来源
- 时间戳(配合公证服务嵌入)——用于校验证书有效期与系统时间的一致性
没有有效签名的更新包,在 macOS 10.14.5 及以后版本会触发“无法验证开发者”红色警告,Gatekeeper 默认拦截。
校验发生在多个层级,层层把关
用户点击“立即更新”后,系统和更新框架(如 Sparkle 或 Squirrel.Mac)会并行或串行执行以下关键校验:
- 更新包签名验证:SUSignatureVerifier(Sparkle)或 SQRLInstaller(Squirrel)读取包内签名,用 Apple 根证书链反向验证签名证书是否由合法 CA 签发、是否在有效期内、是否被吊销
- 应用包内部签名验证:SUCodeSigningVerifier 检查更新后的 .app 是否仍保持完整有效的代码签名,防止替换过程中被注入恶意 dylib 或修改 Info.plist
-
公证票据(Notarization Ticket)验证:系统调用
spctl --assess检查包中是否嵌入苹果公证服务返回的 ticket,确认该版本已通过恶意行为扫描 -
系统兼容性检查:SUUpdateValidator 对比当前 macOS 版本与更新包声明的
LSMinimumSystemVersion,避免降级或越界安装
常见失败原因与对应表现
签名或校验环节出问题,通常不会报错代码,而是以用户可见的提示形式暴露:
- “已损坏,无法打开” → 更新包下载不完整,或签名哈希校验失败(
codesign -v YourApp.app返回 invalid signature) - “无法验证开发者” → Developer ID 证书过期/吊销,或未完成公证;也可能是系统时间偏差导致时间戳校验失败
- “此 App 已损坏” → 更新后 .app 的内部签名被破坏(例如资源文件被自动同步工具覆盖、entitlements 不匹配)
- 静默跳过更新 → Sparkle 配置中未启用
SUEnableAutomaticChecks或签名验证器未正确集成到 Autoupdate target
开发者必须做好的三件事
要让签名与校验稳定可靠,开发者需确保:
- 每次构建更新包时,都使用 当前有效 的 Developer ID Application 证书,并显式指定
--options=runtime和 entitlements 文件 - 签名后立即执行
xcrun notarytool submit完成公证,并用xcrun stapler staple将票据嵌入包中——不能跳过这一步 - 在 Sparkle 集成中启用签名强制验证(默认开启),且不绕过
SUCodeSigningVerifier的深度检查逻辑











