使用 selfsign.py 或 binary-sign-tool 命令为任意 ELF 签名,让其有权限在鸿蒙 HiShell 中执行

@Ta 2025-12-15发布,09-23 22:28修改 16977点击

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)

签名前:

image.png(50.55 KB)

签名:

binary-sign-tool sign -inFile busybox -outFile busybox -selfSign 1

image.png(337.26 KB)

签名后:

image.png(248.4 KB)

回复列表(6|隐藏机器人聊天)
  • @Ta / 09-23 22:28 / 样 / 源

    已知限制:

    1. 自签名ELF似乎没有JIT权限。想要JIT权限还是得打包成public hnp塞到hap里安装。
      鸿蒙7似乎已经没有该限制。

    ff60da1e6708913ed44598e698f7573b.png(121.92 KB)

    1. 自签名ELF似乎也没有调用 tcsetpgrp、tcsetattr 等终端控制 API 的权限,导致 htop 命令不能正常输出,less 命令完全无法使用(问题已在鸿蒙6.1中修复)。打包成public hnp塞到hap里安装是没问题的。

    image.png(39.56 KB)

    1. 签名绑定机器,在一台机器上签名的ELF复制到别的机器上运行不了,别的机器必须重新签名。
      不对,https://github.com/SwimmingTiger/ohos-bst-light 公开的签名算法显示,签名结果只和ELF内容有关,不含任何机器id,所以签名结果是不绑定机器的。

    2. 目前的鸿蒙动态链接器无法正确处理自签名动态库的符号连接,所以可执行文件要加载的动态库都必须直接以文件形式存在,不能是符号连接,否则就算进行了签名也会加载失败。比如ffmpeg要加载libvpx.so.1,如果$LD_LIBRARY_PATH/libvpx.so.1不是文件而是指向libvpx.so.1.11的符号连接,就会加载失败。把符号连接删了,把libvpx.so.1.11复制一份重命名为libvpx.so.1就能加载成功。
      更新到鸿蒙6.1后问题已解决,自签名动态库的符号链接可被正常加载。

  • @Ta / 2025-12-17 / 样 / 源

    转行搞鸿蒙开发了?
    小米20定制版

  • @Ta / 2025-12-17 / 样 / 源

    @幻阳化翼,嗯确有此意

  • @Ta / 2025-12-17 / 样 / 源

    已签名的 busybox 命令,用于测试ELF签名是否绑定机器。
    如果你不能运行,说明ELF签名是绑定机器的,你必须重新给它签名。

    busybox(1.78 MB)

    放在“个人”文件夹,打开HiShell终端运行:

    chmod +x busybox
    ./busybox
    

    screenshot_20251217_191716.jpg(176.71 KB)

    image.png(768.95 KB)

  • @Ta / 2025-12-22 / 样 / 源

    @老虎会游泳,手头有一部旧的荣耀手机,升级系统后是鸿蒙2.0,而最新是3.0,但已经错过升级尝鲜,从哪可以找到完整卡刷包呢

  • @Ta / 2025-12-22 / 样 / 源

    @echo醉老仙,在系统设置里点击检查更新,点进去后看右上角的四个点里面有没有升级尝鲜

添加新回复
回复需要登录。