2026-07-27更新:使用官方签名工具 binary-sign-tool 会导致Bun打包的二进制无法正常工作,可改用以下项目中的 selfsign.py 进行签名:
# 下载selfsign.py签名脚本
wget https://raw.githubusercontent.com/hqzing/ohos-selfsign/refs/heads/main/selfsign.py
# 如果上面的github下载不了,就用我的gitcode镜像仓库:
wget https://raw.gitcode.com/hu60cn/ohos-bst-light/raw/main/selfsign.py
# 给执行权限
chmod +x selfsign.py
# 用它给claude code二进制签名
./selfsign.py ./claude
不过要让claude code二进制在鸿蒙里正常运行还需要做一些其他工作,详见这篇文章:
此外我还做了一个批量签名脚本,可以配合 selfsign.py 使用,给整个目录中的所有ELF签名,有需要可以去这里下载:
https://gitcode.com/hu60cn/ohos-bst-light/blob/main/ohos-sign-elf.py
用法:
wget https://raw.gitcode.com/hu60cn/ohos-bst-light/raw/main/selfsign.py
wget https://raw.gitcode.com/hu60cn/ohos-bst-light/raw/main/ohos-sign-elf.py
chmod +x selfsign.py ohos-sign-elf.py
./ohos-sign-elf.py ~/myproject/bin
运行py脚本需要安装python,可通过Harmonybrew安装(brew install python),或通过应用商店安装。
需要鸿蒙6系统,鸿蒙5不支持。打开开发者模式后,从应用商店的应用尝鲜里安装 CodeArts IDE。
如果 CodeArts IDE 的终端打不开,请先关闭 CodeArts IDE 的窗口(必须关闭窗口,光重启没用),然后重启电脑。
注意:签名只是让ELF有权限运行,不能让原本就不兼容鸿蒙的ELF在鸿蒙里正常运行。
如果ELF不是静态链接的程序,并且依赖glibc,那大概率不能在鸿蒙内正常运行。
如果ELF依赖其他.so库,那所有.so库也都需要签名,并且需要配置LD_LIBRARY_PATH环境变量指向so所在文件夹。
如果不想使用 CodeArts IDE,也可以从华为应用商店安装 DevBox app,然后直接在鸿蒙 HiShell 终端里运行 binary-sign-tool 命令。
https://appgallery.huawei.com/app/detail?id=com.develop.opensource.devbox&channelId=SHARE&source=appshare
不过 DevBox 目前没有 objcopy 命令,你可以从 CodeArts IDE 里拷贝一个出来用。
binary-sign-tool sign -inFile ELF文件名 -outFile ELF文件名 -selfSign 1
签名当前目录及其子目录下的所有ELF文件:
find . -type f -exec file '{}' ';' | grep --line-buffered ': ELF ' | awk -F': ELF ' '{print $1}' | while read f; do echo "$f"; binary-sign-tool sign -inFile "$f" -outFile "$f" -selfSign 1; done
注意:while循环与fish不兼容,请在zsh或bash中执行。
objcopy --remove-section .codesign ELF文件名
如果签名已存在,重新签名之前要先移除旧签名,否则会报错:.codesign section already exists
localhost ~/work/test % binary-sign-tool sign -inFile busybox -outFile busybox -selfSign 1
[Error] [sign_elf.cpp] [WriteCodeSignBlock] [134] [SignElf] .codesign section already exists
[Error] [sign_elf.cpp] [Sign] [54] [SignElf] WriteCodeSignBlock error
[Error] [self_sign_sign_provider.cpp] [SignElf] [29] [SignElf] sign elf failed
12-25 12:39:55.715 INFO - sign failed
find . -type f -exec file '{}' ';' | grep --line-buffered ': ELF ' | awk -F': ELF ' '{print $1}' | while read f; do echo "$f"; objcopy --remove-section .codesign "$f"; done
注意:while循环与fish不兼容,请在zsh或bash中执行。
以这个从 Termony 项目里提取的 busybox 命令为例:busybox(1.77 MB)
签名前:
签名:
binary-sign-tool sign -inFile busybox -outFile busybox -selfSign 1
签名后:
已知限制:
自签名ELF似乎没有JIT权限。想要JIT权限还是得打包成public hnp塞到hap里安装。鸿蒙7似乎已经没有该限制。
自签名ELF似乎也没有调用 tcsetpgrp、tcsetattr 等终端控制 API 的权限,导致 htop 命令不能正常输出,less 命令完全无法使用(问题已在鸿蒙6.1中修复)。打包成public hnp塞到hap里安装是没问题的。签名绑定机器,在一台机器上签名的ELF复制到别的机器上运行不了,别的机器必须重新签名。不对,https://github.com/SwimmingTiger/ohos-bst-light 公开的签名算法显示,签名结果只和ELF内容有关,不含任何机器id,所以签名结果是不绑定机器的。
目前的鸿蒙动态链接器无法正确处理自签名动态库的符号连接,所以可执行文件要加载的动态库都必须直接以文件形式存在,不能是符号连接,否则就算进行了签名也会加载失败。比如ffmpeg要加载libvpx.so.1,如果$LD_LIBRARY_PATH/libvpx.so.1不是文件而是指向libvpx.so.1.11的符号连接,就会加载失败。把符号连接删了,把libvpx.so.1.11复制一份重命名为libvpx.so.1就能加载成功。更新到鸿蒙6.1后问题已解决,自签名动态库的符号链接可被正常加载。