Hotdry.

Article

Coldkey:后量子时代 age 密钥生成与纸备份工具

解析 Coldkey 如何使用 ML-KEM-768+X25519 混合密钥封装机制生成抗量子 age 密钥,并通过 QR 码纸备份实现离线冷存储的完整工程化方案。

2026-05-15security

在机密信息管理领域,age 和 sops 已成为行业标准的数据加密工具。它们的设计哲学强调简洁性与安全性:使用单一私钥加密所有敏感数据,通过密钥文件实现访问控制。然而,这种架构带来了一个根本性风险 —— 密钥文件的物理安全等同于所有加密数据的物理安全。磁盘故障、人为误操作或硬件丢失都可能导致密钥永久丢失,进而造成所有受保护数据的不可逆损失。Coldkey 正是为解决这一核心问题而诞生的工具,它将后量子密码学与纸质备份相结合,为 age/sops 用户提供了一套完整的密钥保护方案。

ML-KEM-768 与 X25519 混合密钥封装机制

Coldkey 生成的密钥采用了 Filipo Valsorda 设计的 post-quantum age 格式,其核心是 ML-KEM-768 与 X25519 的混合密钥封装机制。ML-KEM(原名 CRYSTALS-Kyber)是 NIST 在 2024 年正式发布的后量子密钥封装算法,基于模格(Module Lattice)上的错误学习问题(Module-LWE)构建,具备抗量子计算攻击的能力。X25519 则是一成熟的椭圆曲线密钥交换协议,两者的组合意味着 Coldkey 生成的密钥既能抵御传统密码分析攻击,又能抵御未来量子计算机的暴力破解。

这种混合设计的工程价值在于渐进式迁移。X25519 确保了密钥在当前环境下的可用性,ML-KEM-768 则提供了面向未来的安全保障。Coldkey 在生成密钥时,会创建一个包含两种算法封装结果的复合密钥文件,存储在标准的 keys.txt 格式中。值得注意的是,工具实际上只存储 32 字节的种子(seed),ML-KEM-768 私钥和 X25519 私钥均由种子派生生成。这种设计直接决定了纸备份的可行性 —— 较小的数据量意味着可以用更少的 QR 码承载完整信息。

QR 码纸备份的工程实现

Coldkey 的纸备份输出是单页可打印的 HTML 文档,包含四个核心组成部分:原始密钥文本的 monospace 显示、QR 码图像、SHA-256 校验和,以及分步恢复说明。工具使用 version 40 的 QR 码,纠错级别为 L,单个 QR 码的最大数据容量为 2,953 字节。实际生成的 keys.txt 文件大小约为 2,089 字节,完全可以编码在单个 QR 码中,这是整个方案能够简化为单页备份的技术前提。

当密钥文件因特殊配置而超出单 QR 码容量时,Coldkey 会自动启用多码分帧协议。该协议在编码数据前添加 COLDKEY:<part>/<total>: 前缀,标识当前分片序号和总分片数。恢复时,用户需要按顺序扫描所有 QR 码,去除前缀后将分片数据拼接,再通过 SHA-256 校验和验证完整性。这种设计避免了复杂的分片重组算法,仅依赖字符串拼接和哈希校验即可完成恢复。

Docker 运行环境下,just docker-run 命令会将备份文件输出到 ./output/ 目录,用户可以直接在浏览器中打开生成的 HTML 文件进行打印。HTML 文档内置了打印样式表,打印按钮在打印时自动隐藏,确保备份介质上不包含任何冗余的 UI 元素。纸张备份完成后,建议进行 laminating 处理以增强耐久性,并存放在防火保险箱中。

内存安全与容器隔离

Coldkey 在内存安全层面的设计体现了纵深防御原则。全局内存锁定通过 mlockall(MCL_CURRENT|MCL_FUTURE) 系统调用实现,它阻止密钥材料被换页到磁盘交换区。即使系统因内存压力触发了页面置换,密钥数据仍保留在物理内存中。这一机制需要 CAP_IPC_LOCK Linux 能力,在 Docker 环境中需通过 --cap-add IPC_LOCK 参数显式授予。如果没有此权限,Coldkey 会输出警告但继续执行,因为仍有文件系统级别的保护措施。

文件系统层面,密钥文件以 0600 权限创建,确保仅创建者有权读写。写入时强制使用 fsync 刷盘,保证数据落入持久化存储而非仅停留在页缓存。临时文件采用三遍覆写(3-pass overwrite)机制进行安全删除,防止文件系统残留导致的密钥泄露。这些措施共同构建了从内存到磁盘的全链路保护。

容器隔离是 Coldkey 推荐的安全加固方案。just docker-run 命令默认应用以下 Docker 安全标志:网络隔离(--network none)确保密钥生成过程完全离线运行;根文件系统只读(--read-only)防止容器内任何写入操作;所有能力集丢弃(--cap-drop ALL)限制了容器内进程的系统调用权限;no-new-privileges:true 安全选项阻止通过 setuid 二进制文件进行的权限提升攻击。临时目录使用 tmpfs 挂载,数据完全存储在内存中,容器终止后自动清空。

容器镜像选用 distroless/static:nonroot 基础镜像,该镜像不包含 shell 和标准工具链,使用非 root 用户(UID 65534)运行,大幅削减了攻击面。

Go 运行时限制与缓解措施

Coldkey 的内存安全实现面临 Go 运行时垃圾回收器的固有局限。Go 的字符串是不可变对象,当密钥数据以字符串形式存储(如调用 identity.String() 方法)时,无法通过常规手段覆写其内存副本。Coldkey 使用 secure.Zero() 函数对字节缓冲区进行覆写,该函数内部调用 Go 内置的 clear() 函数重置 []byte 类型的内存内容。然而,早期的字符串副本可能已在堆内存中形成独立对象,在垃圾回收触发前持续占用内存。

这一限制的缓解策略是 mlockall 与内存覆写的组合使用。虽然覆写不能保证立即生效,但 mlockall 确保所有密钥副本(包括字符串对象)永不被换出到磁盘。即使垃圾回收器在密钥处理完成后才执行内存释放,这些数据也仅存在于物理内存中,不会泄露到磁盘交换文件。对于安全要求极高的场景,建议在容器环境外使用硬件安全模块(HSM)存储密钥。

恢复流程与验证

Coldkey 的恢复流程设计强调简单可靠。用户在需要恢复密钥时,首先通过 QR 码扫描仪或手动输入的方式获取密钥文本内容。扫描模式下,建议使用开源的 zbar 库或商业 QR 扫描工具,确保按从左到右、从上到下的顺序扫描多个分片 QR 码。获取原始文本后,保存至 ~/.config/sops/age/keys.txt,使用 sha256sum 命令比对备份文档上打印的 SHA-256 校验和。校验通过后,通过 sops -d <any .sops file> 命令测试解密功能是否正常。

验证步骤的必要性不可忽视。SHA-256 校验和排除了打印错误、墨水褪色或扫描遗漏导致的数据损坏。sops 测试解密则验证了密钥格式的完整性,确保密钥文件能够被加密工具正确解析。两个验证步骤都通过后,才可认为密钥成功恢复。

生产环境部署建议

在生产环境中集成 Coldkey 时,应建立明确的密钥轮换策略。建议每 12 个月生成新密钥并重新加密所有 sops 文件,旧密钥至少保留 30 天以应对回滚需求。新密钥生成后,立即创建纸备份并安全存储,旧密钥的纸备份应在确认新密钥完全可用后销毁。

纸备份的存放位置需要权衡可用性与安全性。防火保险箱是基础配置,建议选择能够承受 1 小时以上 1000°C 高温的型号。对于组织级密钥管理,可考虑在地理分散的多个安全位置各存放一份备份,主站点保留一份,本地银行保险箱存放一份,异地灾难恢复站点存放一份。恢复时需确保至少有一个人在所有备份地点拥有合法访问权限。

Docker 环境的安全基线应包含定期审计。建议使用 docker bench security 检查容器运行时配置,验证 --cap-drop ALL--read-only 等标志是否持续生效。镜像更新后应重新执行安全基线检查,确保新版本未引入意外的能力授予或权限变更。

Coldkey 将后量子密码学与实用的纸质备份相结合,为 age/sops 用户提供了兼顾未来安全与当前可用性的密钥管理方案。在量子计算威胁日益临近的背景下,及早部署后量子密钥保护措施是负责任的安全工程实践。


参考资料

security

内容声明:本文无广告投放、无付费植入。

如有事实性问题,欢迎发送勘误至 i@hotdrydog.com