Git 3.0 即将默认采用 SHA-256 将是一个代价高昂的错误

Git 3.0 计划将默认哈希格式从 SHA‑1 转向 SHA‑256,这引发了担忧:此举可能会割裂生态,并破坏数十年来依赖 40 字符提交 ID 的工具、引用和工作流。批评者认为,SHA‑1 的弱点对 Git 的真实威胁模型而言大多只是理论上的,而更强的哈希应作为额外的完整性或签名机制叠加使用,而不应以不兼容的方式替换核心 ID 格式。支持迁移者则反驳说,哈希安全如今已成为监管和供应链要求,但人们普遍担心所选路径会像 Python 2→3 那样带来痛苦迁移,尤其是在子模块、CI 系统和长期存在的企业仓库方面。

SHA‑1 的不安全性到底有多严重?

  • 许多人认为 SHA‑1 已经“被攻破”(选择前缀碰撞、Shambles 等),因此依赖它来做完整性校验或签名是不安全的。
  • 也有人说,对真实 Git 仓库的实际攻击仍然极其困难,尤其考虑到 Git 的对象格式和 sha1dc 碰撞检测;更可能的供应链攻击来自维护者被攻陷或基础设施,而不是哈希本身。
  • 对 Git 哈希究竟是“安全”机制还是仅仅是一致性标识符,存在分歧;一些人指出,对提交进行签名并按哈希固定引用,实际上就把它们变成了安全关键项。

将 SHA‑256 设为默认值的影响

  • 支持者:最终必须淘汰 SHA‑1;拖延只会让未来的切换更痛苦。默认值必须改变,否则没人会迁移。
  • 批评者:切换默认值会创建两种不兼容的仓库类型,导致困惑、依赖 40 字符哈希的工具失效,以及对不理解格式的用户出现难以排查的故障。很多人把它类比为 IPv6 或 Python 3 的迁移。

子模块、工具与生态兼容性

  • 一个主要担忧是子模块会出问题:SHA‑1 父仓库与 SHA‑256 子模块(以及反过来)过去被描述为不受支持。
  • 一位评论者通过实验展示了在较新的 Git 中,SHA‑256 仓库里可以使用 SHA‑1 子模块,但长期保证和边缘情况仍不清楚。
  • 大型生态系统(Yocto、Nix、CI/CD、语言包管理器)都依赖提交哈希;全局历史重写会使配置、文档、问题跟踪器等中的引用失效。

代码托管平台与 UX(GitHub、GitLab、自托管)

  • 有人担心代码托管平台会让用户接触到他们并不理解的格式选项,或者在首次 push 时对自动检测处理不当。
  • 也有人反驳说,服务器可以根据第一次 push 推断格式,而且 Git 文档化的哈希迁移方案包含 SHA‑1↔SHA‑256 的映射以实现互操作。

替代设计与提案

  • 常见建议包括:
    • 为每个对象同时存储两种哈希(或单独的“树信任”哈希头),同时保留 SHA‑1 ID 作为地址标识。
    • 使用类似 multihash 的自描述摘要,或像 Fossil 那样允许一个仓库使用多种算法。
    • 保持 SHA‑1 作为默认值;仅在安全或策略需要时再添加 SHA‑256。
  • 反对者指出,混用不同强度的哈希会削弱整体安全性,并增加实现复杂度。

安全模型与未解问题

  • 关于现实攻击路径存在争论:基于碰撞的代码植入与更简单的社会工程或基础设施攻击。
  • 有些人认为这次迁移是必要的卫生措施和面向未来的准备;另一些人则认为这是一种代价高昂的“安全表演”。
  • 许多人仍不清楚:Git 3.0 对 SHA‑1 查找、子模块互操作以及保留现有外部引用,究竟会提供什么精确保证。