跳转至内容

开发者Wiki:Repo DB 签名

来自 ArchWiki

[RFC] Repo DB 签名 (以及 ISO/其他构件)

我们的仓库 DB 当前未签名,因为将 GPG 私钥放在向仓库添加包的服务器上存在安全隐患。然而,我们希望自动签名我们的 db、iso 和其他构件,因此必须做出一些妥协。

关于这个话题已经进行了几次讨论

签名仓库数据库就像下面一样简单

repo-add -v -s foo.db pacman-3.0.0-1-x86_64.pkg.tar.gz
lrwxrwxrwx 1 jelle users  13 Aug 15 20:56 foo.db -> foo.db.tar.gz
lrwxrwxrwx 1 jelle users  17 Aug 15 20:56 foo.db.sig -> foo.db.tar.gz.sig
-rw-r--r-- 1 jelle users 504 Aug 15 20:56 foo.db.tar.gz
-rw-r--r-- 1 jelle users 503 Aug 15 20:56 foo.db.tar.gz.old
-rw-r--r-- 1 jelle users 310 Aug 15 20:56 foo.db.tar.gz.sig
lrwxrwxrwx 1 jelle users  16 Aug 15 20:56 foo.files -> foo.files.tar.gz
lrwxrwxrwx 1 jelle users  20 Aug 15 20:56 foo.files.sig -> 
foo.files.tar.gz.sig
-rw-r--r-- 1 jelle users 782 Aug 15 20:56 foo.files.tar.gz
-rw-r--r-- 1 jelle users 782 Aug 15 20:56 foo.files.tar.gz.old
-rw-r--r-- 1 jelle users 310 Aug 15 20:56 foo.files.tar.gz.sig

repo-add 签名仓库如下

gpg --detach-sign --use-agent --no-armor

无论是有意还是无意,repo-add 都可以仅签名 db 而不添加包。

repo-add foo.db.tar.gz -s

提出的解决方案

从“安全”隔离区签名 (解决方案 1)

创建一个专用的签名主机,该主机接收文件,然后返回签名。

应在此主机上添加一些限制

  • 签名速率限制 (每月仅签名一次 ISO)
  • 安全地记录签名过的构件
  • 来自特定 IP 的请求 (这应该是仅 repos.archlinux.org)
  • 身份验证 (SSH?)
  • 独立主机、虚拟机或容器?
  • 最小访问列表

参见 Bluewind 的提案。

实现: https://git.server-speed.net/users/flo/alass/[失效链接 2025-03-15—未解析域名]

从“安全”隔离区签名 (解决方案 2)

与将任意文件发送到“安全”隔离区不同,隔离区会拉取要签名文件并返回一个新签名文件。

工作流程

  1. 触发 DB 更改操作,仓库被锁定。
  2. 创建一个新的 DB 文件并放入临时位置。
  3. 发送通知给(或更准确地说,由)安全隔离区,告知有新的 DB 文件需要签名。
  4. 安全隔离区检索要签名文件。
  5. 它对其进行签名,并(可选,待定)记录其已完成。
  6. 将签名上传回 DB 服务器。
  7. DB 服务器将 DB 及其签名放到位,释放仓库锁并重置通知通道。

全局实现细节

  1. 无特别/新内容。
  2. 在此需要将新生成的 DB 放在特定位置。
  3. 此时,DB 更改操作有两种主要方式可以通知需要新的签名
    1. 不执行任何操作: 隔离区正在查找临时位置的 DB,并在看到文件时知道有事要做(而不是例如 404)。
    2. 写入特定文件: 文件可以包含一个 0 (表示没有新的 DB 需要签名),或一个 1,甚至实际 DB 文件的校验和,以避免传输过程中的损坏问题。
  4. 如果执行了上述第二种情况,只需使用同一种安全连接检索 DB。
  5. 这里有很多值得思考的地方。特别是*安全*日志记录很困难。这将在下面详细介绍。
  6. 这里有很多可能的上传机制,请参见下文。
  7. 这要求 DB 更改操作正在等待签名返回。

具体细节

  • 关于从 DB 服务器检索文件到隔离区: 我能想到的最安全的方法是使用一个非常加固的 HTTPS 连接。这意味着服务器和客户端都使用自定义 CA(可能位于隔离区)颁发的证书进行身份验证,仅支持 TLS 1.3,ECDHE 与 Ed448 和 Poly1305-Chacha20 或 AES-GCM。我们需要在监视通知文件时保持连接打开,以避免在监视频率上重新建立新的 TLS 会话。
  • 上传签名回来: 我们可以使用相同的设置通过 HTTP(S) 上传,但不确定这是否非常重要(除非我们签了一个错误的文件,签名本身是公开文件,所以…)。需要仔细考虑攻击场景。
  • 对于以上两点,我们可以强制使用双方的 IP 地址以提高安全性。仓库服务器上的实际入口点也可以是 TOR 隐藏服务,但不确定我们是否想要这样做(我猜可能有缺点)。
  • 现在,让我们深入研究日志记录和威胁模型。这可能是困难的部分。
  1. 如果我们不考虑隔离区可能被攻破,那么我们只需要签名脚本还将签名记录到远程上传点和本地文件(以防网络故障)。
  2. 如果我们考虑隔离区可能被攻破但没有 root 权限,那么密钥只能由 root 访问或放在 HSM 中,但(仅限 root 可写)签名+日志脚本可供普通用户使用。这样攻击者就无法在不记录的情况下签名文件。
  3. 如果我们考虑隔离区被 root 攻破,拥有 HSM 是唯一能让我们免于完全失败的保护(它需要攻击者维持在隔离区的存在,这将防止长期攻击),但这基本上还是输定了。

请注意,其中大多数具体细节也适用于解决方案 1。

与解决方案 1 相比的优点

  • 隔离区上的开放端口至少少了一个(“提交”端口),这意味着如果只允许物理访问该机器而不是 SSH,则可以将其降至零(我们也可以将 SSH 隐藏在 TOR 中)。
  • 取决于实现细节,对任意文件签名的保护可能更健壮。

与解决方案 1 相比的缺点

  • 双方都需要监视器(等待签名文件,等待签名上传)vs 几乎没有(嗯,你仍然需要等待签名返回,但这是你的“握手”的一部分)。
  • 为了获得不多的安全性而增加了复杂性(嗯,在某些点上,安全性的提升需要大量的努力)。

https://www.mail-archive.com/arch-dev-public@archlinux.org/msg25637.html

比较 收益/陷阱

  • 两个解决方案都有一个问题,那就是存在一段时间仓库 db 未签名。解决方案是使用临时 db,然后移动该 db。

其他发行版的解决方案

Debian

OpenSuSe 构建服务

OBS (OpenSuSe 构建服务) 有一个签名守护程序,它接受数据并返回签名。

代码 wiki

Fedora

待解决问题

  • 应该使用哪个密钥来签名仓库 db?
  • 通过 SSH 进行远程签名的 Repo DB?
  • 分发公钥。在密钥环中?
  • 使用硬件令牌?