使用硬件安全模块发布 F-Droid 存储库

以下是使用硬件安全模块 (HSM) 通过 F-Droid 发布应用的教程。本文中使用的 HSM 是 Nitrokey HSM2。其他硬件令牌应该具有类似的功能,但你必须使用不同的命令与 HSM 交互。

一旦在 HSM 中生成密钥,将签名密钥存储在 HSM 中会提供主要的安全优势,它永远无法以纯文本形式提取。而是将要签名的数据发送到 HSM,它将使用内部持有的密钥材料生成签名。他们还应用了一些防篡改技术,这使得密钥的物理提取非常困难。

Android 应用的签名密钥是所述应用身份的一部分。作为一项安全措施,只有在新的 apk 使用与旧 apk 相同的私钥签名时,才能安装应用的更新。将密钥存储在 HSM 中可确保即使攻击者破坏了你的基础设施,他们也无法窃取签名密钥。事实上,攻击者是否可能已经获得了密钥的访问权永远不会有任何疑虑。这需要盗走物理 HSM,而这至少将轻易发现。尽管如此,入侵者仍可能使用 HSM 签署恶意应用。

F-Droid 有两个签名步骤。所有 apk 以及存储库索引都已签名。理想情况下,所有这些密钥都应存储在 HSM 中。

声明: 我问 Nitrokey 他们是否可以赞助一些 Nitrokey HSM 来让 F-Droid 的发布工作流程与之配合使用。他们同意给我寄三个,并让我写一篇关于我的结果的博客文章。

步骤 0:准备 Nitrokey HSM2

强烈建议在使用前用设备密钥加密密钥 (DKEK) 初始化 Nitrokey。这允许密钥备份和恢复到另一个使用相同 DKEK 初始化的 Nitrokey,以防出现硬件故障。将现有的签名密钥导入 HSM 也需要它(见下文)。

有关如何设置此功能的分步指南以及管理 DKEK 共享和密码短语的可能选项,可在此处找到

不用说,你应该将 DKEK 存放在一个非常安全的地方。

(可选)第 1 步:将现有的签名密钥导入 HSM

Nitrokey HSM2 只能导入使用正确的 DKEK “包装”(加密)的密钥,因此要从 java 密钥库中导入纯密钥,必须首先使用 DKEK 手动包装该密钥。Nitrokey HSM 内的智能卡制造商 (CardContact) 有一个名为 smartcard-shell 的工具可以做到这一点。这些工具不是很好用(它是一个用 javascript 编写的 java GUI 工具)。我将此过程移植到了一个小型命令行 python 工具,可以在这里找到该工具。

第 2 步:设置 F-Droid 存储库

你应该使用最新的 2.0a 版本的 F-Droid 或从 git master 安装它。最近解决了一些 HSM 使用问题。

初始化一个新的存储库如下,这将设置必要的配置文件,以便将 fdroid 与 HSM 一起使用

$ fdroid init --keystore NONE # NONE 表示使用 HSM 密钥库

然后,你至少需要更改 config.py 中的 keystorepass ,这需要设置为 Nitrokeys 智能卡引脚。如果你已导入现有存储库签名密钥,则需要将其设置为 repo_keyalias。否则,你可以直接在 HSM 上创建一个新密钥(将 keydname 更改为你的存储库证书详细信息。)

$ fdroid update --create-key # 这需要一段时间...

第 3 步:签名应用并发布索引

从现在开始,只要将 Nitrokey 插入你的机器,一切都应该照常工作。当使用 fdroid publish 和使用 fdroid update 生成签名的存储库索引时,F-Droid 将自动使用它。

那么签名很多应用呢?

Nitrokey HSM2 用于签名密钥的空间有限,它最多可以存储 38 个 2048 位 RSA 密钥。有一个正在进行的合并请求 MR利用包装的密钥功能仅按需将应用签名密钥加载到 HSM 上。这允许通过单个 Nitrokey 使用无限数量的不同键。(非常感谢 Jason Donenfeld (zx2c4) 提出这个想法!)