签名模型
配置元数据签名,让客户端验证仓库索引。需要客户端验证 RPM 文件内嵌签名时, 另行配置 RPM 包签名。
签名对象
| 配置 | 签名内容 | 输出 | 客户端设置 |
|---|---|---|---|
signing.rpm.metadata |
RPM 索引清单 | repodata/repomd.xml.asc |
DNF repo_gpgcheck=1 |
signing.deb.metadata |
APT 发布清单 | InRelease、Release.gpg |
APT Signed-By |
signing.rpm.packages |
RPM 包 | 内嵌 OpenPGP 签名 | DNF gpgcheck=1 |
元数据签名不改变包字节。RPM 包签名会改变包字节及 SHA-256。 SOW 不给 DEB 包文件增加签名。
配置元数据签名
RPM 与 DEB 可使用相同或不同密钥。密钥带口令时,在 key 旁增加
passfile: /run/secrets/gpg-password,或将 SOW_GPG_PASSFILE 设置为口令文件路径。
先检查配置,再构建:
已配置签名的空 Dist 与非空 Dist 生成相同种类的签名文件。InRelease 的签名正文与
Release 一致。未配置密钥时,SOW 生成未签名索引。
Managed 的密钥与签名策略来自 sow.yml;--passfile PATH 可为本次执行覆盖口令来源,
build 同样支持。
密钥与口令引用
| 元数据密钥引用 | 含义 | 签名实现 |
|---|---|---|
keys/repo.asc |
相对于工作区根的 OpenPGP 密钥文件 | 进程内 |
file:///secure/repo.asc |
绝对路径的 OpenPGP 密钥文件 | 进程内 |
env://SOW_METADATA_KEY |
ASCII 装甲格式密钥、文件路径或 GPG 密钥标识 | 取决于变量值 |
agent://KEY_ID_OR_FINGERPRINT |
本地 GPG 环境可用的密钥 | 外部 gpg |
密钥文件支持 ASCII 装甲格式和二进制 OpenPGP 数据。GPG 密钥标识可以是 16 位 key ID,
或 40、64 位指纹。引用解析为 GPG 密钥标识时,使用外部 gpg 访问私钥;
显式指定口令文件后,通过 GPG loopback 模式非交互解锁。
签名 key 引用必须解析为一个主密钥。
trusted_keys 文件可以包含多个完整公钥,包括连续的 ASCII 装甲块。
SOW 读取整个密钥集合,拒绝格式错误或被截断的输入,不会仅使用第一个密钥而忽略后续内容。
口令来源优先级为 --passfile PATH、每个密钥的 passfile 配置、SOW_GPG_PASSFILE。
旧元数据配置的 passphrase 引用继续兼容,优先级与单个密钥配置相同;
同一密钥的两个字段不能都非空。三种签名设置都接受 passfile,包括 agent:// 密钥。
口令文件为非空 UTF-8 单行。SOW 只移除末尾一个 LF 或 CRLF,保留空格与制表符。 不搜索默认路径,所选来源不可用时直接失败。完整格式、相对路径基准、权限及恢复命令范围 见口令文件。
config show 显示引用和解析出的公钥身份,不显示私钥或口令内容。
config check 解锁元数据私钥文件并检查用途;外部 GPG 元数据密钥还会试签。
RPM 包签名只检查口令格式、工具和私钥是否可用,不会签包或证明口令正确,
详见 config check。
创建新元数据签名时,选中的签名密钥需要在发布时间和
当前时间都可用。历史验证使用保留的证书。
新 APT 签名使用 SHA-256。新的发布尝试要求两份 APT 签名都使用 SHA-256、SHA-384 或 SHA-512。
升级包含 SHA-1 元数据签名的工作区后,先运行 build,再开始新发布。
已有发布尝试继续使用其记录的文件。
配置 RPM 包签名
| 模式 | 行为 |
|---|---|
never |
原样保存输入字节 |
fill |
已有签名可由当前密钥或受信密钥验证时保留原包,其余包签名 |
always |
已由当前密钥签名的包保留原样,其余包重签 |
没有密钥时默认 never,有密钥时默认 fill。fill 和 always 都必须配置密钥。
包签名在私有副本上调用主机的 rpm --addsign 或 rpm --resign。
安装 rpm、gpg,并确保 rpm 使用的 GPG 环境中有对应私钥。
密钥引用只标识签名者,不会把私钥导入该环境。原始输入文件保持不变。
SOW 检查签名结果、包坐标及排除签名头后的包体摘要。已有对象的坐标和包体相同、
且符合当前策略时,可复用已有签名字节。never 模式要求字节完全相同才能复用。
包签名工作流请使用 RPM 格式 v4。SOW 支持验证 RSA、DSA、ECDSA 与 EdDSA RPM 签名,包括保存在 RPM 签名头 tag 267(RPMSIGTAG_DSA)中的纯头签名。SOW 不支持 RPM 格式 v6 使用的签名标签。
这与 OpenPGP 签名报文版本不同;SOW 支持历史 CentOS 的 OpenPGP v3、v4 签名。
更换密钥
只修改 passfile 路径不会让 Dist 变脏;签名身份变化会使相关 Dist 变脏。更换元数据密钥后,运行 build 生成新签名,
并在发布新元数据前把新公钥分发给客户端。
已有包池对象不可变,修改 RPM 包签名策略不会原地重签这些对象。 逐步轮换包签名密钥时:
- 将新密钥设为当前密钥,使用
mode: fill。 - 旧包仍为成员时,在
trusted_keys中保留旧公钥。 - 加入由新密钥签名的新版本包。
- 旧签名包退出成员集合或被新版本替代后,再移除旧信任。
直接换新密钥并使用 always,要求所有期望成员 RPM 已符合新密钥策略。
若重签会使同一包 URL 对应不同字节,应使用新的包发行版本和文件名。
RPM 验证按包的签名时间检查证书和签名子钥是否有效。证书保留了所需历史自签名与子钥绑定时, 续期本身不会使旧包签名失效。导出续期公钥时保留这些历史公钥信息。
Plain 签名
Plain 模式只签 RPM 包文件。不带 --overwrite 时,为没有可解析内嵌签名的包签名;
带该选项时,重签全部保留的 RPM。密钥标识为 16、40 或 64 位十六进制字符,
可带 0x 前缀。执行 --pigsty 清理后,至少需要剩余一个 RPM。