codex-app-mirror安全设计详解:EdDSA字节级签名+固定公钥,如何守护Codex安装包真实性
【免费下载链接】codex-app-mirror原样镜像官方 Codex 桌面应用:每 15 分钟探测、SHA256 可校验、国内直连下载、 Mac 可增量更新 | Verbatim, verifiable mirror of the official Codex desktop app — probed every 15 min, with a Sparkle delta-update feed.项目地址: https://gitcode.com/gh_mirrors/co/codex-app-mirror
codex-app-mirror是一个面向 OpenAI Codex 桌面应用的安装包镜像项目:它每 15 分钟探测一次上游,把官方 Windows MSIX 与 macOS DMG原样、可校验地发布出来,并为 macOS 提供 Sparkle 增量更新源。既然安装包要经过第三方镜像流转,"如何保证拿到的就是官方原件"就成了整个项目的核心命题。本文用大白话拆解它的三道安全防线:EdDSA 字节级签名、**固定公钥(pinned key)**与macOS 身份门禁,让你看懂"镜像不篡改"到底是怎么被技术强制的,而不是口头承诺。
一、先搞懂一个前提:为什么镜像项目最怕"换包"
想象你在下载一个几 GB 的安装包。如果中途有人把官方包换成自己的包(哪怕只改一个字节植入后门),普通用户根本无从察觉。这就是下载渠道的信任问题。
codex-app-mirror的解法很硬核:每一道环节都把"与官方字节完全一致"变成可机器验证的事实,任何一步校验失败,整个发布流程直接中止(fail-closed,宁可不发也不发错)。下面逐一拆解。
二、第一道防线:EdDSA 字节级签名,签名跟着字节走
什么是 EdDSA 签名(30 秒科普)
EdDSA(基于椭圆曲线的数字签名算法,常见实现是 Ed25519)可以理解为官方给文件盖的一枚"防伪印章":
- OpenAI 用私钥给 Sparkle 更新归档(
.zip)算出一串签名; - 任何人拿公钥就能验签,文件改一个字节,签名立刻失效;
- 关键在于:签名签的是文件的原始字节,跟文件存放在哪里、URL 叫什么名字完全无关。
Codex 的 macOS 更新源(appcast)里,每个<enclosure>都带有sparkle:edSignature属性,就是这枚印章。
镜像的关键操作:只换地址,不动字节
镜像脚本 build-appcast.sh 在生成自己的 appcast 时只做一件事:把下载地址(url)从 OpenAI 的服务器换成镜像地址,其余属性——包括sparkle:edSignature签名值——逐字原样保留。
对应地,下载脚本 download-macos.sh 把官方.zip归档逐字节复制(verbatim copy):
归档字节被原样拷贝,这正是官方 EdDSA 签名保持有效的前提;镜像从不运行 BinaryDelta,从不重新计算签名。
换句话说:
| 官方做了什么 | 镜像做了什么 | 结果 |
|---|---|---|
| 用私钥对归档字节签名 | 原样复制字节 + 原样复制签名 | 客户端用 OpenAI 公钥验签,依然通过 |
| — | 若镜像擅自改动 1 个字节 | 验签必然失败,更新直接拒绝 |
所以"镜像无法伪造签名"不是一句口号,而是密码学的必然:没有 OpenAI 私钥,任何修改都过不了客户端的 EdDSA 验签。
探测阶段同样严格:probe-release.sh 在抓取官方 appcast 时会把每个增量差量包(delta)的全部属性原样记录,并校验其下载 URL 是否为官方 HTTPS 地址、文件名是否安全合法,从源头掐掉"投毒"的可能。
三、第二道防线:固定公钥,拒绝"听信上游"
字节级复制保证了"签名对得上",但还有一个更深的问题:客户端拿哪把公钥去验签?如果公钥也是每次从网络动态获取,攻击者只要同时篡改"文件 + 公钥"就能骗过验签(这叫公钥注入攻击)。
codex-app-mirror的做法是把 OpenAI 的 Ed25519 公钥硬编码写死在仓库里(pinned key)。在 read-macos-metadata.sh 中:
- 预期签名团队 ID:
2DC432GLL2(OpenAI 的 Apple 开发者团队) - 预期 Sparkle 公钥:
mNfr1v9t63BfgDtlw4C8lRvSY6uMggIXABDOCi3tS6k=
这意味着无论上游 appcast 将来怎么写、网络上返回什么,只要验签用的公钥不是这把写死的钥匙,流程就报错退出。公钥钉死在仓库中、可被社区审计,是整条信任链的锚点。
同样的思路也用在了Linux Preview 通道:probe-linux-preview.sh 使用固定在仓库里的 codex-linux-repository-key.b64 公钥,先核对密钥指纹3BFA0E4AE8B8CC16A2D9BA684A3B4A566C4660E4是否一致,再用gpgv验证 OpenAI 官方 APT 仓库的InRelease与 RPM 仓库的repomd.xml签名(probe-linux-preview.sh)——仓库元数据不被官方私钥签过,一个包都不会下载。校验脚本 verify-linux-preview.sh 对同一把固定密钥做了双重门禁。
四、第三道防线:macOS 身份门禁,"长得像"不算数
光验字节还不够,镜像还回答了一个问题:这个 DMG 里装的应用,真的是 OpenAI 的 Codex 吗?
read-macos-metadata.sh 在 macOS 上挂载 DMG 后,执行一组"身份门禁"检查,任何一条不满足立即失败:
- 只有一个顶层
.app——防止夹带隐藏应用(find_single_top_level_app); - Bundle ID 必须匹配:稳定通道必须是
com.openai.codex,Beta 通道必须是com.openai.codex.beta,写死在脚本里,不接受"差不多"(read-macos-metadata.sh); - 内置公钥核对:读取应用
Info.plist中的SUPublicEDKey,必须与第三部分写死的固定公钥一致——这等于让"应用自带验签钥匙"与"仓库钉死的钥匙"互相咬合,防止有人替换应用后偷梁换柱; - Apple 代码签名全量校验:运行
codesign --verify --deep --strict,逐层验证签名链,并核对 TeamIdentifier 是否等于2DC432GLL2(read-macos-metadata.sh)。
这套门禁的妙处在于它不信任文件名、不信任版本号、不信任任何"看起来对"的东西,只信任 Apple 的签名体系和密码学验证。
五、配套保险:尺寸校验与 SHA256 双重核对
三道主防线之外,还有两个低成本但高效的"保险丝":
- 下载即量尺寸:download-macos.sh 中的
validate_size会把每个下载文件的实际字节数与探测阶段从官方响应头里读到的Content-Length精确比对,差 1 个字节就中止——传输被截断、被替换都躲不过; - SHA256 全量清单:每次发布都会生成 SHA256SUMS.txt 与
release-manifest.json上游指纹,用户可手动二次核对;探测阶段还会用这些指纹与上一次 Release 对比,上游没变就不重复发版,减少无意义的资产流转(probe-release.sh 甚至会把 appcast 声明的长度与真实对象大小对齐)。
六、总结:一条"密码学闭环"的信任链
把上面的环节串起来,就是一条完整的信任链:
官方私钥签名归档 ──► 镜像逐字节复制(不动签名) │ ├─► 固定公钥钉死在仓库(公钥可审计) ├─► macOS 身份门禁(Bundle ID + Team ID + 代码签名) ├─► 字节尺寸核对(下载即校验) └─► SHA256SUMS.txt 供用户终验| 防线 | 防的是什么 | 核心文件 |
|---|---|---|
| EdDSA 字节级签名 | 镜像篡改文件字节 | build-appcast.sh |
| 固定公钥 | 公钥注入、供应链替换 | read-macos-metadata.sh |
| macOS 身份门禁 | 冒充官方应用 | read-macos-metadata.sh |
| Linux 仓库密钥固定 | 伪造 APT/RPM 仓库 | probe-linux-preview.sh |
对普通用户而言,你只需要记住一句话:codex-app-mirror 的每个字节都可以被验证是官方的——下载后顺手核对一下SHA256SUMS.txt,你的 Codex 安装包就经过了四重保险的背书。🔐
更多通道策略与更新机制的说明,可参考 docs/beta-prerelease.md 与项目主文档 README.md。
【免费下载链接】codex-app-mirror原样镜像官方 Codex 桌面应用:每 15 分钟探测、SHA256 可校验、国内直连下载、 Mac 可增量更新 | Verbatim, verifiable mirror of the official Codex desktop app — probed every 15 min, with a Sparkle delta-update feed.项目地址: https://gitcode.com/gh_mirrors/co/codex-app-mirror
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考