【鸿蒙PC】二进制签名解析:自签名、调试证书、二进制证书到底差在哪
内容提要
鸿蒙PC的三种二进制签名共用同一.codesign段,区别仅在signature字段:自签名仅填描述符自身摘要,只能证明文件未被篡改,无法声明权限;调试证书签名用证书链签出PKCS7,需开发者模式并绑定UDID,可声明权限;二进制证书签名走发行信任表,用于正式分发。签名决定身份可信,沙箱决定能否被拉起。
延伸解读
签名差异的根源:一个字段的三种填法
三种签名共用同一个 .codesign 段和 fs-verity 描述符,区别仅在 signature 字段。自签名填描述符自身摘要,调试证书和二进制证书填证书链签出的 PKCS7。权限、分发范围、设备要求等所有差异都由此推导。理解这一点,就能明白为什么无法通过换命令行参数把调试签名变成正式签名——它们只是同一代码路径的不同输入。
自签名为何无法声明权限
自签名的 signature 字段是描述符自身的摘要,只能证明文件未被篡改,无法证明签发者身份。而权限授予的对象是身份,没有证书参与就没有可背书的身份。即使通过 -moduleFile 写入 .permission 段,运行时也不会生效,因为没有一个主体来认领它。这解释了官方“自签名二进制权限策略段不生效”的根本原因。
调试证书的两道锁:UDID 与开发者模式
调试证书签名要求设备处于开发者模式,并在 .permission 中绑定 UDID。源码中,开发者模式是调试信任表是否参与匹配的开关:关闭后,调试证书签的二进制直接落到 untrusted。UDID 校验则限制运行设备范围。这两道锁将开发期凭证的影响半径压到开发者自己的机器上,是能力与约束的对偶设计。
签名之外:沙箱决定能否被拉起
签名决定文件身份是否可信,沙箱决定文件能否被应用拉起。弱沙箱应用自带 CUSTOM_SANDBOX 权限,可拉起任何二进制;强沙箱应用需申请 ALLOW_EXTERNAL_NATIVE_CODE,且仍无法拉起 adhoc bin,因为 adhoc 没有身份。注意:DevEco Studio 的 clang 编译产物默认是 adhoc bin,若需在强沙箱中拉起,必须补调试证书签名转为 debug bin。
Q&A
鸿蒙PC的三种二进制签名(自签名、调试证书、二进制证书)在技术实现上最根本的区别是什么?
三种签名共用同一个 .codesign 段、同一个 fs-verity 描述符和同一个 0x3 版本号,区别仅在于 signature 字段的填充内容:自签名填描述符自身的摘要,调试证书签名填调试证书链签出的 PKCS7,二进制证书签名填二进制证书链签出的 PKCS7。所有权限、分发范围、设备要求上的差异都由此推导而来。
为什么自签名(adhoc)的二进制能运行,却不能声明权限?
因为自签名只解决了完整性,没有解决来源。signature 字段填的是描述符自身的摘要,只能证明文件未被篡改,无法证明“这是谁签的”。权限授予的对象是身份,而自签名没有证书参与,不产生可验证的签发主体,因此运行时无法换出任何身份,权限策略段即使写入也不生效。
调试证书签名为什么必须开启开发者模式并绑定设备 UDID?
这是为了把开发期凭证的影响半径限制在开发者自己的设备上。UDID 锁:.permission 中必须写明 debug-info.device-ids,运行前由 VerityHdcStatusAndDeviceId 校验,缺了会报错。开发者模式锁:内核代码中通过 if (is_dev_mode) 决定调试信任表是否参与匹配,关闭开发者模式后调试证书签的二进制会直接落到 untrusted。
调试证书签名的共享库(.so)为什么不能声明权限?
权限的主体是进程/应用,而不是文件。.so 被 dlopen 进宿主进程后,在内核眼里不是一个能独立承担权限的实体,它藉由宿主进程的身份运行。因此“给一个 .so 授予权限”缺少可挂靠的授权对象。可执行程序拥有自己的进程,所以能拥有可被授权的身份。
鸿蒙PC上,强沙箱应用能否拉起自编译的二进制?需要什么条件?
强沙箱应用必须申请 ALLOW_EXTERNAL_NATIVE_CODE 权限,但即便如此也拉不起 adhoc bin,因为 adhoc 没有身份,无法参与信任判断。而使用 DevEco Studio 的 clang 交叉编译的二进制默认属于自签名场景,类型是 adhoc bin。因此若要在强沙箱应用中拉起自编译二进制,必须补一步调试证书签名,将其变为 debug bin。
鸿蒙PC的二进制签名与 macOS 的代码签名在设计上有哪些对应关系?
两者同构:macOS 的 codesign 对应 binary-sign-tool;正式签名对应二进制证书签名;开发签名对应调试证书签名;无身份签名(Ad Hoc)对应自签名(adhoc);完整性机制上 macOS 用代码目录哈希,鸿蒙用 fs-verity Merkle 树;校验位置 macOS 在内核+amfid,鸿蒙在内核 fs_security_verity+用户态 code_protect;信任判断 macOS 用系统信任库,鸿蒙用内核证书来源信任表。最大差异是链接期签名:macOS 的 lld 默认打 adhoc,鸿蒙的 ld.lld --code-sign 需手动开启。