6 共享状态签名

OpenEmbedded Build System 内置了通过复用预构建产物来节省执行时间的 机制,即 共享状态缓存(sstate 缓存)。这些产物存放在目录( SSTATE_DIR )中,默认不签名。

本文介绍启用共享状态签名的步骤。此功能完全依赖 GPG,因此示例均使用 gpg 命令行工具。

6 主机要求

由于 GPG 不属于默认的 主机要求,需要自行在主机上安装。

例如,基于 Debian 的发行版通过 gpg 软件包提供该工具。安装方法如下:

$ sudo apt-get install gpg

显示 GPG 版本,确认安装成功:

$ gpg --version

6 使用 GPG 生成公私钥对

备注

如果已有公私钥对,可以跳过此步骤。

两个相互独立的任务需要用到公私钥对:

  • 使用 私钥 为 OpenEmbedded Build System 生成的共享状态产物签名。

  • 复用共享状态产物时,使用 公钥 验证它们。

备注

关于公钥密码学的更多信息,见 https://en.wikipedia.org/wiki/Public-key_cryptography。

使用 gpg 命令行工具生成新的公私钥对:

$ gpg --full-generate-key

该工具会引导你完成创建密钥对的各个步骤。

完成后,应能使用以下命令列出新密钥:

$ gpg --list-keys
pub   ed25519 2026-04-17 [SC]
      4049A47E3AAA99D0250966DC5B97632FA7F4E942
uid           [ultimate] Antonin Godard (SState Signing) <antonin.godard\@bootlin.com>
sub   cv25519 2026-04-17 [E]

记下上例中的密钥标识符 4049A47E3AAA99D0250966DC5B97632FA7F4E942,配置构建时会用到它。

6 配置构建系统为共享状态产物签名

6 共享状态的位置

需要配置构建系统,使其在生成新的共享状态产物时进行签名。任务执行完成后, 便会生成新的产物。

以下各节假定构建系统的共享状态目录( SSTATE_DIR )定义如下:

SSTATE_DIR = "${TOPDIR}/sstate-cache"

假设此目录和临时目录( TMPDIR )都为空,运行 gettext-minimal-native 配方的 create_recipe_spdx 任务:

$ bitbake gettext-minimal-native -c create_recipe_spdx

本文将始终以此命令为例。

执行后,共享状态目录中应出现新文件:

$ find $BUILDDIR/sstate-cache/ -name "*gettext-minimal-native*create_recipe_spdx*"
sstate-cache/universal/a3/6e/sstate:gettext-minimal-native:x86_64-linux:1.0:r0:x86_64:14:a36ef66df6b8c0cb5a849bc70a99dcfd61e4bacd11cefe6bbaf4978b2b3b617a_create_recipe_spdx.tar.zst
sstate-cache/universal/a3/6e/sstate:gettext-minimal-native:x86_64-linux:1.0:r0:x86_64:14:a36ef66df6b8c0cb5a849bc70a99dcfd61e4bacd11cefe6bbaf4978b2b3b617a_create_recipe_spdx.tar.zst.siginfo

这些是 OpenEmbedded Build System 默认生成的共享状态产物。它们 默认不使用 GPG 签名,下面介绍如何为这些产物添加签名。

备注

尽管名称如此,siginfo 文件与 GPG 签名无关。

6 启用共享状态签名

在主机的 安全位置 创建新的 configuration file,并添加以下语句:

SSTATE_VERIFY_SIG = "1"
SSTATE_SIG_KEY = "4049A47E3AAA99D0250966DC5B97632FA7F4E942"
SSTATE_SIG_PASSPHRASE = "<your GPG key passphrase>"

建议将这些语句放入单独的文件,因为它们包含秘密信息,不应共享。 本例假定该文件为 conf/sstate-sig-key.conf。

可通过以下命令确保文件归你所有,且其他用户无法读取:

$ chown $USER:$USER conf/sstate-sig-key.conf
$ chmod o-rwx conf/sstate-sig-key.conf

文件中的语句定义了以下变量:

  • SSTATE_VERIFY_SIG:将此变量设为 "1" 可启用共享状态签名功能。

  • SSTATE_SIG_KEY:用私钥为共享状态产物签名的 GPG 密钥标识符。

    在本例中,它对应 前文 中 gpg --list-keys 命令输出的 标识符。

  • SSTATE_SIG_PASSPHRASE:保护私钥的口令,在创建密钥对时指定。

测试配置:

  1. 继续使用 gettext-minimal-native 示例。首先删除已有的共享状态产物, 确保重新生成 do_create_recipe_spdx 任务的共享状态产物:

    $ rm -r sstate-cache/
    
  2. 运行 gettext-minimal-native 的 create_recipe_spdx 任务,但这次 将新的 sstate-sig-key.conf 文件传给 BitBake:

    $ bitbake -R conf/sstate-sig-key.conf gettext-minimal-native -c create_recipe_spdx
    

再次列出共享状态目录中的文件:

$ find sstate-cache/ -name "*gettext-minimal-native*create_recipe_spdx*"
sstate-cache/universal/a3/6e/sstate:gettext-minimal-native:x86_64-linux:1.0:r0:x86_64:14:a36ef66df6b8c0cb5a849bc70a99dcfd61e4bacd11cefe6bbaf4978b2b3b617a_create_recipe_spdx.tar.zst
sstate-cache/universal/a3/6e/sstate:gettext-minimal-native:x86_64-linux:1.0:r0:x86_64:14:a36ef66df6b8c0cb5a849bc70a99dcfd61e4bacd11cefe6bbaf4978b2b3b617a_create_recipe_spdx.tar.zst.sig
sstate-cache/universal/a3/6e/sstate:gettext-minimal-native:x86_64-linux:1.0:r0:x86_64:14:a36ef66df6b8c0cb5a849bc70a99dcfd61e4bacd11cefe6bbaf4978b2b3b617a_create_recipe_spdx.tar.zst.siginfo

新增了一个 .sig 文件。这说明产物已成功签名,签名保存在单独的 .sig 文件中。

6 验证已签名的共享状态产物

现在已经配置构建为共享状态产物签名,下面介绍如何使用与私钥对应的公钥 验证这些产物。

备注

共享状态的签名和验证可以在两台不同的主机上进行,一台主机负责签名, 另一台只验证产物。推荐这样做,因为不应在多台主机之间共享私钥。

在 configuration file (例如 站点配置文件 )中加入以下语句:

SSTATE_VERIFY_SIG = "1"
SSTATE_VALID_SIGS = "5B97632FA7F4E942"

这些语句定义了:

  • SSTATE_VERIFY_SIG:将此变量设为 "1" 可启用共享状态签名功能。

  • SSTATE_VALID_SIGS:以空格分隔的密钥标识符列表,指定可接受哪些 密钥签名的共享状态产物。

    这意味着,只有使用对应密钥标识符的私钥签名的共享状态才会被复用。

    注意,这里使用的是密钥标识符的短形式,即 gpg --list-keys 显示的 长形式标识符的最后 16 个字符(下方以粗体显示):

    pub   ed25519 2026-04-17 [SC]
          4049A47E3AAA99D0250966DC5B97632FA7F4E942
    uid           [ultimate] Antonin Godard (SState Signing) <antonin.godard@bootlin.com>
    sub   cv25519 2026-04-17 [E]

检查签名验证是否正常工作:

  1. 首先删除之前构建的临时输出( TMPDIR ),让 OpenEmbedded Build System 利用共享状态重新构建所有内容:

    $ rm -rf tmp/
    
  2. 然后再次运行任务:

    $ bitbake gettext-minimal-native -c create_recipe_spdx
    
  3. 要确认成功使用了共享状态产物,请在 BitBake 的最新日志文件中 查找 create_recipe_spdx 对应的 setscene 任务:

    $ grep create_recipe_spdx_setscene tmp/log/cooker/<machine>/console-latest.log
    NOTE: Running setscene task 1 of 1 (../layers/openembedded-core/meta/recipes-core/gettext/gettext-minimal-native_1.0.bb:do_create_recipe_spdx_setscene)
    NOTE: recipe gettext-minimal-native-1.0-r0: task do_create_recipe_spdx_setscene: Started
    NOTE: recipe gettext-minimal-native-1.0-r0: task do_create_recipe_spdx_setscene: Succeeded
    

    共享状态已成功验证并使用!

备注

要确认共享状态验证有效,可以在 SSTATE_VALID_SIGS 中设置一个 “虚假”的公钥标识符:

SSTATE_VALID_SIGS = "CAFECAFECAFECAFE"

再次删除临时输出:

$ rm -r tmp/

现在尝试执行任务:

$ bitbake gettext-minimal-native -c create_recipe_spdx

控制台应输出 BitBake 的警告:

WARNING: gettext-minimal-native-1.0-r0 do_create_recipe_spdx_setscene: No accepted signatures found. Good signatures found: 5B97632FA7F4E942.
WARNING: gettext-minimal-native-1.0-r0 do_create_recipe_spdx_setscene: Cannot verify signature on sstate package ../build/sstate-cache/universal/a3/6e/sstate:gettext-minimal-native:x86_64-linux:1.0:r0:x86_64:14:a36ef66df6b8c0cb5a849bc70a99dcfd61e4bacd11cefe6bbaf4978b2b3b617a_create_recipe_spdx.tar.zst, skipping acceleration...
WARNING: gettext-minimal-native-1.0-r0 do_create_recipe_spdx_setscene: No sstate archive obtainable, will run full task instead.
WARNING: Logfile for failed setscene task is ../build/tmp/work/x86_64-linux/gettext-minimal-native/1.0/temp/log.do_create_recipe_spdx_setscene.6994
WARNING: Setscene task (../layers/openembedded-core/meta/recipes-core/gettext/gettext-minimal-native_1.0.bb:do_create_recipe_spdx_setscene) failed with exit code '1' - real task will be run instead

可以看到,这不会阻止 BitBake 继续运行,但它会执行实际任务, 不再复用共享状态。