Nix 二进制缓存签名密钥对生成指南nix-store --generate-binary-cache-key 详解【免费下载链接】nixNix, the purely functional package manager项目地址: https://gitcode.com/gh_mirrors/ni/nixNix 的二进制缓存binary cache通过 Ed25519 签名来保证下载的构建产物确实来自可信的构建服务器。nix-store --generate-binary-cache-key是生成这种签名密钥对的标准入口一次命令即可产出私钥与公钥两个文件。读完本文你将掌握该命令的完整语法、三个必选参数的语义与命名规范、密钥文件的磁盘格式与权限约定以及如何将生成的公钥/私钥接入nix.conf的trusted-public-keys、secret-key-files配置搭建一条完整可信的二进制分发链路。命令概览根据官方手册 generate-binary-cache-key.md该命令的完整定义为nix-store --generate-binary-cache-key- generate key pair to use for a binary cache即“生成用于二进制缓存的密钥对”。其语法为nix-store --generate-binary-cache-key key-name secret-key-file public-key-file与nix-store的其他操作如--realise、--gc、--query一样它属于nix-store这一传统命令体系通过 nix-store.cc 中的命令行参数解析分派到对应的操作处理器。三个必选参数命令恰好接收三个位置参数缺一不可。从源码实现看参数个数会被严格校验opGenerateBinaryCacheKey首先检查opArgs.size() ! 3否则抛出UsageError(three arguments expected)见 nix-store.cc。三个参数的语义如下1. key-name密钥名称密钥名称用于客户端在验证签名时查找对应密钥即签名/密钥对的“身份标识”。它的取值几乎是任意的但官方建议遵循以下命名惯例使用缓存服务器的主机名作为主体例如cache.example.org追加一个编号后缀表示密钥的代数例如cache.example.org-1每当需要吊销旧密钥并轮换新密钥时将编号递增为cache.example.org-2、cache.example.org-3……之所以要“带编号递增”是因为密钥名称会随着签名一并分发Nix 客户端持有多个公钥时正是依靠签名中携带的 key-name 去匹配本地的trusted-public-keys列表见下文“与 nix.conf 的衔接”因此密钥轮换时用编号区分代际客户端可以平滑地同时信任新旧密钥。作为对照Nix 官方缓存默认信任的公钥就遵循这一格式其默认值即cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY见 globals.hh。2. secret-key-file私钥存储文件名私钥文件保存 Ed25519 签名私钥。该文件必须严格保密只有二进制缓存的签名方即你的构建/发布服务器才能读取。3. public-key-file公钥存储文件名公钥文件用于分发给所有从该二进制缓存下载产物的客户端客户端将其加入trusted-public-keys配置后即可验证缓存内容的真实性。密钥对的底层实现与文件格式--generate-binary-cache-key生成的并非普通的 OpenPGP 或 X.509 密钥而是Ed25519 密钥对。手册中给出的参考实现是 ed25519.cr.yp.to 所描述的 Edwards 曲线数字签名算法文档原文如此。从仓库源码可以完整还原其生成与落盘过程。操作处理器 opGenerateBinaryCacheKey 的核心逻辑只有三行auto secretKey SecretKey::generate(keyName); writeFile(publicKeyFile, secretKey.toPublicKey().to_string(), 0666, FsSync::Yes); writeFile(secretKeyFile, secretKey.to_string(), 0600, FsSync::Yes);对应的底层密码学实现位于 local-keys.cc生成SecretKey::generate调用 libsodium 的crypto_sign_keypair一次性生成公私钥对local-keys.cc导出公钥SecretKey::toPublicKey调用crypto_sign_ed25519_sk_to_pk从私钥派生出 Ed25519 公钥local-keys.cc序列化Key::to_string将密钥编码为name:base64-data的冒号分隔格式local-keys.cc。也就是说生成的两个文件内容形如cache.example.org-1:Base64 编码的密钥材料其中私钥/公钥的二进制长度分别为crypto_sign_SECRETKEYBYTES64 字节与crypto_sign_PUBLICKEYBYTES32 字节解析时会对长度与格式做严格校验local-keys.cc 与 L139-L144。值得注意的是文件权限的刻意区别文件权限原因公钥文件0666需要分发给所有客户端任何人都应可读私钥文件0600仅属主可读写防止签名私钥泄露此外两个文件都以FsSync::Yes同步写盘确保密钥文件在崩溃/断电场景下不会出现半写状态。私钥在解析出错时也不会在错误消息中打印原始值构造函数传入sensitiveValue true避免通过日志泄漏私钥local-keys.cc。与 nix.conf 的衔接签名与验签的完整闭环生成密钥对本身只是第一步要让二进制缓存真正具备签名能力需要把两个文件接入 Nix 的签名/验签配置。相关配置项定义在 globals.hhtrusted-public-keys空格分隔的公钥列表格式即name:base64。当从其他 Nix store如 substituter/二进制缓存拷贝 store object 时Nix 要求该对象至少满足以下条件之一才接受已使用受信任密钥列表中的密钥签名、require-sigs被设为false、store URL 配置了trustedtrue、或该对象是内容寻址content-addressed的secret-key-files空格分隔的私钥文件列表用于对本地构建出的路径进行签名。手册中对该配置项的说明明确写道这些密钥可以用nix-store --generate-binary-cache-key生成对应的公钥可以分发给其他用户由他们加入各自nix.conf的trusted-public-keysrequire-sigs默认true。开启时任何非内容寻址路径在加入或拷贝进 Nix store 前例如从二进制缓存替换下载时都必须带有受信任密钥的签名受信任密钥即trusted-public-keys中列出的公钥或与secret-key-files中私钥对应的公钥。设为false则无条件信任所有非内容寻址路径内容寻址路径天然可信不受此选项影响。签名与验签两端会在运行时汇合getDefaultPublicKeys()实现于 keys.cc会把trusted-public-keys中的公钥与secret-key-files中各私钥派生的公钥合并成一个PublicKeys映射供后续verifyDetached校验使用其中不可读的私钥文件会被静默忽略——这是多用户安装下的正常情况普通用户本就不该读到 root 的签名私钥。签名本身采用分离签名detached signature格式key-name:signature-in-Base64local-keys.hh验证时先按签名中的 key-name 查表找到对应公钥再用 libsodium 的crypto_sign_verify_detached校验local-keys.cc。完整工作流示例以下展示从零搭建一个签名二进制缓存的端到端流程。1. 在发布服务器上生成密钥对$ nix-store --generate-binary-cache-key cache.example.org-1 \ /etc/nix/secret-key-file \ /etc/nix/public-key-file命令无输出即成功。检查生成结果$ ls -l /etc/nix/secret-key-file /etc/nix/public-key-file -rw------- 1 root root 96 ... /etc/nix/secret-key-file -rw-r--r-- 1 root root 64 ... /etc/nix/public-key-file $ cat /etc/nix/public-key-file cache.example.org-1:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2. 在发布服务器上启用签名将私钥文件路径加入 Nix 配置例如/etc/nix/nix.confsecret-key-files /etc/nix/secret-key-file此后本地构建的 store 路径都会被该私钥签名。3. 在客户端信任该公钥将公钥内容追加到每个客户端的nix.conftrusted-public-keys cache.example.org-1:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4. 验证链路客户端配置substituters指向你的缓存后下载的产物会先经require-sigs的签名校验校验失败则拒绝使用该缓存内容。可保留 Nix 官方缓存的默认公钥cache.nixos.org-1:...与自己的公钥并存实现多缓存并行信任。5. 密钥轮换若怀疑私钥泄露或需要更换生成新密钥对时使用递增编号如cache.example.org-2在客户端同时保留新旧公钥以实现平滑过渡待所有客户端都完成迁移后再移除旧公钥。安全注意事项与常见疑问私钥绝不外传secret-key-file是签名的唯一凭证泄露即意味着攻击者可以为任意构建产物伪造有效签名从而在客户端机器上执行任意代码。分发时只分发公钥。文件权限不可忽略命令自动将私钥文件设为0600、公钥文件设为0666这是签名/验签角色的最小权限模型若手动复制密钥请保持同样的权限约定。参数数量严格命令必须且只能提供三个位置参数多传或少传都会直接报错three arguments expected且该操作不接受任何额外的操作标志unknown flag会抛错。key-name 是安全边界的一部分验签时先按 key-name 查找公钥名称不匹配即拒绝local-keys.cc因此命名应全局唯一且可预期。参考与延伸阅读本命令手册原文generate-binary-cache-key.mdnix-store通用选项如--add-root等nix-store/opt-common.mdNix 命令通用选项--help、--verbose、--max-jobs等opt-common.md通用环境变量NIX_CONFIG、NIX_PATH、NIX_STORE_DIR等env-common.md命令实现src/nix/nix-store/nix-store.cc密钥密码学实现src/libutil/signature/local-keys.cc签名/密钥数据结构定义src/libutil/include/nix/util/signature/local-keys.hh相关配置项定义trusted-public-keys/secret-key-files/require-sigssrc/libstore/include/nix/store/globals.hh公钥集合加载逻辑src/libstore/keys.cc【免费下载链接】nixNix, the purely functional package manager项目地址: https://gitcode.com/gh_mirrors/ni/nix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考