代码签名是macOS可信链的起点,基于公钥密码学验证完整性与身份,需同时满足Authority、TeamIdentifier和valid on disk三要素,且自Catalina起必须配合公证才能运行。
代码签名不是“贴标签”,而是可信链的起点
macos 的代码签名不是简单打个戳就完事。它本质是一套基于公钥密码学的完整性与身份验证机制:开发者用私钥对应用内容生成唯一哈希,再由苹果信任的根证书签发的中间证书背书该签名。系统运行时会重新计算哈希、用公钥解密签名比对,并逐级回溯证书链至 apple root ca。只要文件被改一个字节、证书过期、或中间链断裂,校验立刻失败。
签名必须匹配三要素,缺一不可
一个合法有效的签名需同时满足:
- Authority 字段明确显示为 Developer ID Application: XXX 或 Apple Distribution: XXX,不能是 adhoc、unidentified developer 或为空
- TeamIdentifier 非空且与开发者账号注册的 Team ID 一致,这是苹果识别归属的关键标识
- valid on disk 返回 yes,表示当前磁盘上的文件与签名时完全一致,未被篡改或损坏
用 codesign -dv --verbose=4 /path/to.app 可直接查看这三项。若其中任一不达标,Gatekeeper 就会拦截——哪怕应用本身完全无害。
签名只是基础,公证才是 macOS 10.15+ 的硬门槛
从 Catalina 开始,仅签名已不够。苹果要求所有非 App Store 分发的 Developer ID 应用,必须额外通过 Notarization(公证) 流程:上传二进制到苹果服务器,经自动恶意行为扫描并嵌入票据(ticket)。未公证的应用在 Ventura 及更新系统上默认无法启动,弹窗显示“无法验证开发者”。
验证是否真正通过公证,不能只看有没有签名,而要用:
-
spctl --assess --type execute --verbose=4 /path/to.app—— 输出含 accepted 才算过关 -
xattr -pl com.apple.quarantine /path/to.app—— 查看是否有 ticket=1 标记
运行时保护靠签名联动其他机制
签名本身不防攻击,但它为后续安全机制提供信任锚点:
- Sandbox 和 Hardened Runtime 的启用依赖签名中声明的 entitlements(权限配置),签名无效则沙盒策略不生效
-
Sparkle 等更新框架 在安装更新包前,会调用
SUSignatureVerifier验证更新包签名,并用SUCodeSigningVerifier二次校验主 App 是否仍保持原始签名 - 系统更新 虽不依赖开发者操作,但其签名验证逻辑同源——同样校验 Apple 根证书链、哈希一致性与时间戳,只是由 AMFI 内核模块强制执行
没有签名,这些防护层就失去可信依据;签名失效,整条安全链条即刻中断。











