Git 3.0 要把 SHA-1 换成 SHA-256,为什么有人把它比作「又一个 IPv6」? Git 3.0 要把 SHA-1 换成 SHA-256为什么有人把它比作「又一个 IPv6」GitButler 的创始人 Scott Chacon 前几天写了一篇博客标题直接把结论摆在脸上Git 3.0’s upcoming SHA-256 default will be a costly mistake。Hacker News 的讨论帖 半天冲到 359 分、342 条评论。Chacon 不是外人。他是《Pro Git》的作者日常做的就是 Git 客户端。他一开口说「这是个代价高昂的错误」评论区立刻分成两派。但真正值得看的不是谁嗓门大而是这场争论把一个老问题重新摆到了台面上当一个系统的标识符变成了所有人依赖的不可变契约换掉它到底是一次升级还是一场生态拆迁先说清楚 Git 为什么要换Git 本质上是一个内容寻址的文件系统。文件、目录、提交全部用哈希值而不是递增序号来命名。Git 官方文档写得很直白用哈希寻址好处是完整性校验极其简单——哪怕只有一个 bit 翻转算出来的哈希对不上名字当场暴露。问题是哈希算法本身会老。2017 年 2 月 23 日SHAttered 攻击演示了第一个真实的 SHA-1 碰撞两份内容不同、哈希相同的 PDF。Git 从 v2.13.0 起默认换成硬化版 SHA-1躲开了那次攻击但官方文档的口径依然谨慎——没人能保证以后不出现新的、并且没有缓解方案的攻击。所以把默认哈希从 SHA-1 换成 SHA-256被写进了 Git 3.0 的计划。争议一碰撞攻击到底算不算威胁Chacon 的核心论点之一是Git 里真正的威胁是「第二原像攻击」而不是「碰撞攻击」。这两种攻击确实不是一回事。碰撞攻击是主动造出一对文件让它们哈希相同第二原像攻击是拿到一份已知文件硬凑出另一份哈希也相同的文件——后者难得多。他的理由是 Git 对象在哈希前会带一个头部类似blob 1234\0攻击者没法直接复用公开的碰撞样本成本会被推高。这条立刻被顶到了榜首。一位用户列出三点反驳其中第二点最要命碰撞攻击在 Git 里完全够用。场景是两个仓库引用同一个提交哈希但检出后的代码内容不同——这就是代码走私而校验哈希根本没有意义因为它们确实一模一样。评论区另一位补了一刀在一个人人都会对陌生人的 PR 执行git fetch的世界里「只要你 fetch 了就已经中招」不能当成安全边界。争议二真正的难点在密码学之外比起密码学细节迁移工程才是这场争论真正的火药桶。Git 官方文档里其实已经写了一套相当克制的方案新旧命名可以并存老提交用 SHA-1 名字依然有效维护一张 SHA-1 与 SHA-256 的双向映射表并且刻意做成一一对应这样换算是可逆的、能按需重算不必把所有对象重新哈希一遍。但一一对应也带来了硬约束。文档明确写着不允许混合仓库子模块必须和父仓库使用同一种算法。再叠上现实一层——GitHub 目前根本不支持 SHA-256 仓库的 push而这正是拖住 3.0 的主要原因之一。对照之下有一组数据特别刺眼。Fossil SCMSQLite 团队做的版本控制系统在 SHAttered 公布后第 6 天——2017 年 3 月 1 日——就加上了 SHA3-256 选项如今新仓库全部默认。更关键的是没有仓库被重建也没有超链接失效。一边是 6 天一边是从 2017 年谈到今天的多年规划。差距不在密码学在生态规模。替代方案和一条更值得记的批评Chacon 提了一个有意思的想法独立树哈希头。不改寻址方式而是用另一种算法独立地把树内容再算一遍哈希把两个哈希一起签名——SHA-1 负责检索内容SHA-256 负责独立验证内容。评论区有人觉得这个方向值得深挖也有人反驳说它并不能真正替代格式层面的迁移。支持「该换」的声音里同样有一条批评非常值得记如果你只是把 SHA-1 换成 SHA-256那你迟早还得再换一次。真正的问题不是这次选哪个哈希而是 Git 的设计压根没给「加密敏捷性」crypto agility留位置——算法被硬编码进了对象格式换一次就要动整个生态。也有读者站出来为换默认辩护2024 年给一个随机的 SHA-1 哈希找一个碰撞成本大约只有一万美元。对大多数威胁模型来说这等于不可行但它拦不住规模继续扩大——今天不换将来就是明摆着的坑。顺带一提还有一条容易被忽略的实用视角真有组织是因为合规要求才推这件事。SHA-1 在 FIPS 140-2 一类认证里被明确不推荐某些机构甚至一刀切禁用。这也解释了为什么「Git 里哈希不是安全特性」这个技术判断并不能让迁移停下来。一个判断这场争论表面在吵「SHA-1 还安不安全」实质在吵一个更难的工程问题当系统的标识符变成了对外契约算法升级就不再是本地重构而是分布式系统的一致性迁移。Git 的对象名会被写进提交信息、CI 脚本、部署记录、issue 评论。有人举了个很实在的例子迁移之后所有写着「see commit abc1234」的历史提交信息全部失效。这不是安全问题这是引用语义被改掉了。对开发者的启示其实很朴素设计任何 ID schema不只是版本控制系统也包括数据库主键、内容寻址存储、缓存键时把算法版本位留出来。一代人换一次的东西值得在格式里预留一个版本号而不是等到下一次被迫全量迁移。至于这场争论本身值不值得信——与其只读博客和评论区不如自己拿一套固定的对照测试跑一遍如果需要在多个模型或工具之间做这种横向对比likeai520.cc 这类 API 中转可以省掉一部分逐家接入和验证的工作。能跑、能对比、能被验证的结论才值得写进你的技术选型。主要参考GitButler 原文、Hacker News 讨论帖id49924179、Git 官方 hash-function-transition 文档、SHAttered 攻击、Fossil SCM 迁移记录