鸿蒙PC生态三方软件移植:ohos-sdk 生成的库或二进制的自动签名实现
本文介绍了鸿蒙OHOS-SDK中实现自动代码签名的技术方案。传统手动签名方式在复杂项目中效率低下,通过修改LLVM链接器参数(--code-sign)和封装ld.lld脚本,可实现编译时自动签名。签名信息存储在ELF文件的.codesign段中,使用llvm-readelf可验证签名结果。文章详细说明了SDK下载、链接器配置和环境变量设置的具体步骤,并提供了常见问题解决方案。这项技术显著提升了开发
当使用OHOS-SDK编译的应用或者移植的三方库,都需要签名后方可在鸿蒙PC真机上运行。在鸿蒙PC系统的开发中,签名就像是给应用贴上一个可信的标签,是确保应用能在设备上安全运行的关键步骤。然而,传统的手动签名方式在复杂项目中极其繁琐,这就使得自动签名技术变得尤为重要。
今天,给大家推荐一个鸿蒙 ohos-sdk 的自动二进制或库签名的技巧,免去手动一个一个签名的麻烦。
当前网上的博客里面做法基本上都是用 ohos-sdk 编完东西之后再用 ohos-sdk 里面的签名工具手动做一次签名。这样的手工操作较为繁琐,尤其是涉及到大量二进制或 so 的时候就会更繁琐。
这里提供一个技巧,可以让编译工具链在编东西的时候直接自动对产物打上代码签名,省去人工操作的繁琐。
实现原理
鸿蒙 SDK 代码签名机制
鸿蒙系统有个严格的要求,所有可执行文件和共享库都必须经过签名才能在设备上运行。这就好比你要进入一个安全的场所,必须要有有效的通行证才行。传统的签名方式就是使用 binary-sign-tool (在toolchains/lib目录下有该签名工具)对编译后的产物进行处理,
例如:
../../ohos-sdk/linux/toolchains/lib/binary-sign-tool sign -inFile "a.out" -outFile "a.out.signed" -selfSign "1"
但在复杂项目里,手动给每个依赖库签名,就像要给一群人逐个发放通行证,工作量巨大,所以自动化签名就成了刚需。
这个技巧是建立在这个 PR 的基础之上的:
https://gitcode.com/openharmony/third_party_llvm-project/pull/882
这是 OpenHarmony 社区的人往 ohos-sdk 里面的 LLVM 添加的一个特性:如果链接器收到了 --code-sign 参数,它就会自动对生成出来的 ELF 文件做自签名。
这相比于手工签名已经便利很多了,但每次编东西要额外加一个链接器参数还是会有点影响体验。
为了把这最后一步的体验问题也优化掉,我们选择对调用链接器的流程做一点改造,让 clang 驱动器在调用链接器的时候一定携带这个参数,那就能实现自动签名的效果了。
链接器封装技术
这项技术的核心就是把原生的 ld.lld 软链接替换成一个封装脚本。这个脚本就像是一个智能小助手,在链接过程中会自动注入签名参数。具体来说,就是通过脚本向 lld 链接器传递 --code-sign 参数,实现编译时自动签名。而且,对于开发者而言,这个签名过程就像隐身了一样,完全不需要额外操作。
ELF 文件格式与代码签名段
签名信息会存储在 ELF 文件的特定段 .codesign 中。我们可以使用 llvm-readelf -S 命令来查看这个段。这个段有一些特殊的属性,它属于 PROGBITS 类型,并且有特定的内存对齐要求,是 4096 字节。
代码解析
自动化签名实施步骤
1. SDK 下载与解压
sdk_download_url="https://cidownload.openharmony.cn/version/Daily_Version/OpenHarmony_6.1.0.27/20260111_020523/version-Daily_Version-OpenHarmony_6.1.0.27-20260111_020523-ohos-sdk-public.tar.gz"
curl -o ohos-sdk-public.tar.gz $sdk_download_url
mkdir ohos-sdk
tar -zxf ohos-sdk-public.tar.gz -C ohos-sdk
这段代码的作用是从指定的 URL 下载 SDK 压缩包,然后创建一个名为 ohos-sdk 的目录,并将压缩包解压到该目录下。
注意:为了使用这个最新的链接器签名特性,我们需要把 ohos-sdk 换成最新的日构建版本。ohos-sdk 6.0 正式版是不行的,比较旧的日构建版本也不行。这里下载一份(1 月 11 日)的日构建版本。
2. 链接器封装配置
cd ohos-sdk/linux/native/llvm/bin
rm ld.lld # 移除原始软链接
lld_absolute_path=$(realpath lld)
# 创建封装脚本
printf '#!/bin/bash\nexec -a "$0" %s --code-sign "$@"\n' "$lld_absolute_path" > ld.lld
chmod 0755 ld.lld # 添加执行权限
首先进入指定的目录,移除原始的 ld.lld 软链接,然后获取 lld 的绝对路径。接着创建一个封装脚本,这个脚本会在调用 ld.lld 时自动传递 --code-sign 参数。最后给脚本添加执行权限。
编译验证流程
0. 环境变量配置
export PATH=$PATH:$(realpath ohos-sdk/linux/native/llvm/bin)
这行代码将修改后的链接器目录添加到环境变量 PATH 中,这样系统就能找到我们定制的链接器了。(此步骤根据你的需要,非必须。如果你是使用export的方式导出的则不需要配置到环境变量里。这里只是方面下面测试直接使用clang命令)
1. 简单程序编译测试
echo -e '#include <stdio.h>\nint main(void) {\n printf("Hello, world!\\n");\n return 0;\n}' > helloworld.c
clang --target=aarch64-linux-ohos helloworld.c -o helloworld
这里创建了一个简单的 C 语言程序 helloworld.c,然后使用 clang 编译器将其编译成可执行文件 helloworld。
2. 签名验证
llvm-readelf -S helloworld | grep codesign
# 应输出包含 .codesign 段的信息
通过 llvm-readelf -S 命令查看 helloworld 文件的段信息,并使用 grep 命令过滤出 .codesign 段的信息。如果输出中有相关信息,说明签名成功。
[34] .symtab SYMTAB 0000000000000000 001de0 000990 18 36 91 8
[35] .shstrtab STRTAB 0000000000000000 002770 000178 00 0 0 1
[36] .strtab STRTAB 0000000000000000 0028e8 0002f9 00 0 0 1
[37] .codesign PROGBITS 0000000000000000 003000 001000 00 0 0 4096
常见问题与解决方案
SDK下载链接失效
日构建版本的产物过期策略并不透明,有时候一年都不会过期,有时候一个月就过期了。
如果你刚好碰到文中的下载链接过期了,这里有两个处理办法:
- 去网页上下载最新的;
- 用脚本下载最新的。
网页就是这个网页:https://dcp.openharmony.cn,对着我的截图去找这个产物就行。
脚本方式下载SDK如下:
query_component() {
component=$1
curl -fsSL 'https://dcp.openharmony.cn/api/daily_build/build/list/component' \
-H 'Accept: application/json, text/plain, */*' \
-H 'Content-Type: application/json' \
--data-raw '{"projectName":"openharmony","branch":"master","pageNum":1,"pageSize":10,"deviceLevel":"","component":"'${component}'","type":1,"startTime":"2025080100000000","endTime":"20990101235959","sortType":"","sortField":"","hardwareBoard":"","buildStatus":"success","buildFailReason":"","withDomain":1}'
}
sdk_download_url=$(query_component "ohos-sdk-public" | jq -r ".data.list.dataList[0].obsPath")
curl -o ohos-sdk-public.tar.gz $sdk_download_url
签名失败问题
- 问题现象:编译成功了,但文件里却没有
.codesign段。 - 解决方案:
- 检查封装脚本权限:
chmod 0755 ld.lld - 验证脚本内容是否正确指向
lld路径 - 确认
--code-sign参数格式正确
- 检查封装脚本权限:
总结
使用上述技巧,可以使得鸿蒙 ohos-sdk 自动对库或二进制文件签名,为开发者带来了极大的便利,它显著提高了开发效率,尤其是在处理复杂项目依赖时,避免了繁琐的手动签名过程。同时,它也确保了代码的安全性和合规性,让代码在鸿蒙系统上能够安全、稳定地运行。
展望
随着鸿蒙系统的不断发展和完善,自动代码签名技术也可能会有更多的优化和改进。未来,可能会有更简洁、高效的签名方式出现,进一步降低开发者的工作量。同时,在安全性方面也可能会有新的增强措施,为鸿蒙生态的发展提供更坚实的保障。
希望通过这篇文章,大家对鸿蒙 ohos-sdk 自动代码签名技术有了更深入的了解,能够在开发中更好地运用这项技术。
最后,欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/,共同交流进步!
参考链接
更多推荐




所有评论(0)