git中的哈希冲突

时间:2012-05-03 15:16:29

标签: git hash sha1 hash-collision

如果我在使用git时遇到哈希冲突会发生什么?

E.g。我设法提交两个具有相同sha1校验和的文件, 会git注意到它还是损坏了其中一个文件?

可以改进git以使用它,还是我必须更改为新的哈希算法?

(请不要通过讨论这是多么不可能来转移这个问题 - 谢谢)

9 个答案:

答案 0 :(得分:75)

在10个月上拾取原子

SHA-1哈希是一个40十六进制的字符串...每个字符的4位乘以40 ... 160位。现在我们知道10位大约是1000(准确到1024),这意味着有1 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000个不同的SHA-1哈希... 10 48

这相当于什么?月亮由大约10个 47 原子组成。所以,如果我们有10个月亮......然后你在其中一个卫星上随机选择一个原子......然后再继续在它们上面选择一个随机原子...然后你可能会选择相同原子两次,是两个git提交具有相同SHA-1哈希的可能性。

我们可以提出这个问题:

在开始担心碰撞之前,您需要在存储库中进行多少次提交?

这与所谓的“生日攻击”有关,而生日攻击又指的是“生日悖论”或“生日问题”,它指出当你从一个特定的集合中随机挑选时,你需要在你更多可能比没有选择两次。但“令人惊讶的少数”在这里是一个非常相对的术语。

维基百科有a table on the probability of Birthday Paradox collisions。 40个字符的哈希没有条目。但是对于32和48个字符的条目的插值使我们在5 * 10 22 git提交的范围内,以0.1%的碰撞概率。这是五万亿次不同的提交,或五十次 Zettacommits ,然后你甚至有0.1%的机会发生碰撞。

这些提交的散列的字节总和将是比地球上一年生成的所有数据更多的数据,也就是说,您需要比YouTube流出视频更快地生成代码。祝你好运。 :d

关键是,除非有人故意造成碰撞,否则随机发生的概率非常小,你可以忽略这个问题

“但是当碰撞发生时,实际发生了什么?”

好吧,假设不太可能发生,或者假设有人设法定制a deliberate SHA-1 hash collision。那么会发生什么?

在这种情况下,有an excellent answer where someone experimented on it。我会引用那个答案:

  
      
  1. 如果blob已经存在且具有相同的哈希值,则根本不会收到任何警告。一切似乎都没问题,但是当你推,有人克隆,或你还原时,你将失去最新版本(与上面解释的一致)。
  2.   
  3. 如果树对象已经存在并且您使用相同的哈希创建一个blob:一切看起来都很正常,直到您尝试推送或某人克隆您的存储库。然后你会看到回购公司已经腐败了。
  4.   
  5. 如果提交对象已存在且您使用相同的哈希创建一个blob:与#2相同 - 损坏
  6.   
  7. 如果blob已经存在且您使用相同的哈希创建提交对象,则在更新“ref”时它将失败。
  8.   
  9. 如果blob已经存在,并且您使用相同的哈希创建了一个树对象。创建提交时会失败。
  10.   
  11. 如果树对象已经存在并且您使用相同的哈希创建提交对象,则在更新“ref”时它将失败。
  12.   
  13. 如果树对象已经存在并且您使用相同的哈希创建了一个树对象,那么一切都会好起来的。但是当你提交时,所有的存储库都会引用错误的树。
  14.   
  15. 如果提交对象已经存在并且您使用相同的哈希创建提交对象,那么一切似乎都可以。但是当你提交时,永远不会创建提交,并且HEAD指针将被移动到旧提交。
  16.   
  17. 如果提交对象已经存在并且您使用相同的哈希创建树对象,则在创建提交时它将失败。
  18.   

你可能看起来有些情况并不好。特别是情况#2和#3会弄乱您的存储库。但是,似乎故障仍然存在于该存储库中,并且攻击/奇怪的不可能性不会传播到其他存储库。

似乎故意碰撞的问题也被认为是一种真正的威胁,例如GitHub is taking measures to prevent it

答案 1 :(得分:63)

如果两个文件在git中具有相同的哈希值,则会将这些文件视为相同。在极不可能发生这种情况的情况下,您可以随时返回一个提交,并更改文件中的某些内容,以便它们不会再发生冲突......

请参阅Linus Torvalds' post in the thread “Starting to think about sha-256?” in the git mailing list

答案 2 :(得分:25)

用正确的"来回答这个问题是不可能的。但是"没有解释为什么它不是问题。如果没有真正掌握哈希真正的内容,就不可能做到这一点。它比你在CS程序中可能遇到的简单案例更复杂。

这里存在对信息理论的基本误解。如果通过丢弃一些数量(即散列)将大量信息减少到较小的数量,则可能存在与数据长度直接相关的冲突。数据越短,LESS可能就越小。现在,绝大多数的碰撞都是胡言乱语,使它们更有可能实际发生(你永远不会检查胡言乱语......即使二进制图像有点结构化)。最后,机会很遥远。要回答你的问题,是的,git会将它们视为相同,更改哈希算法不会有帮助,它会进行第二次检查"某种程度,但最终,你需要尽可能多的"额外检查"数据作为数据的长度是100%确定...请记住,你将是99.99999 ....到一个非常长的数字....确定与你描述的简单检查。 SHA-x是加密强哈希,这意味着通常很难有意创建两个彼此非常相似的源数据集,并且具有相同的哈希值。数据中的一点变化应该在散列输出中创建多于一个(最好是尽可能多的)变化位,这也意味着从散列到工作的回复非常困难(但并非完全不可能)完整的碰撞集,从而从那组碰撞中拉出原始信息 - 除了少数几个将是胡言乱语,而那些不存在的信息仍然是一个巨大的数字来筛选,如果消息长度是任何重要的长度。加密哈希的缺点是它们的计算速度很慢......总的来说。

那么,对于Git来说,这意味着什么呢?不多。哈希很少(相对于其他所有)完成,因为它们的计算代价总体上低于操作。击中一对碰撞的几率非常低,它不是一个真实的机会,不会被立即检测到(即你的代码很可能突然停止建立),允许用户解决问题(返回修改版本,并再次进行更改,并且由于时间的变化,您几乎肯定会获得不同的哈希值,这也会在git中提供哈希值。如果您在git中存储任意二进制文件,那么它更有可能成为您的真正问题,而这实际上并不是它的主要用途模型。如果你想这样做......你可能最好使用传统的数据库。

考虑到这一点并没有错 - 这是一个很好的问题,很多人只是假装了#34;所以不太可能不值得思考" - 但它真的有点复杂。如果它发生了,它应该是非常容易被发现的,它在正常的工作流程中不会成为沉默的腐败。

答案 3 :(得分:8)

  

可以改进git以使用它,还是我必须更改为新的哈希算法?

任何哈希算法都可能发生冲突,因此更改哈希函数不会排除问题,只会使其不太可能发生。所以你应该选择一个非常好的哈希函数(SHA-1已经存在,但你要求不要被告知:)

答案 4 :(得分:5)

Google现在声称在某些先决条件下可能会发生SHA-1冲突: https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html

由于git使用SHA-1来检查文件完整性,这意味着git中的文件完整性受到了损害。

IMO,git肯定应该使用更好的散列算法,因为现在可以进行故意的碰撞。

答案 5 :(得分:5)

你可以在“How would Git handle a SHA-1 collision on a blob?”中看到一个好的研究。

由于现在可以进行SHA1冲突(正如我在this answer中使用shattered.io引用),请知道Git 2.13(2017年第2季度)将通过“检测尝试创建”来改善/缓解当前情况碰撞“SHA-1 implementation by Marc Stevens (CWI) and Dan Shumow (Microsoft)的变体。

commit f5f5e7fcommit 8325e43commit c0c2006commit 45a574ecommit 28dc98eJeff King (peff)(2017年3月16日)。{
Junio C Hamano -- gitster --于2017年3月24日commit 48b3693合并)

  

Makefile:将DC_SHA1设为默认值

     

我们过去常常使用OpenSSL库中的SHA1实现   默认。
  由于我们在最近的“破碎”声明后试图小心对抗碰撞攻击,因此切换默认值以鼓励人们使用DC_SHA1实现。
  那些想要使用OpenSSL实现的人可以明确要求   运行“OPENSSL_SHA1=YesPlease”时按make运行。

     

我们实际上没有Git-object冲突,所以我们能做的最好的事情是通过test-sha1运行其中一个破碎的PDF。这应该触发碰撞检查并死亡。

  

Git可以改进以适应这种情况,还是我必须更改为新的哈希算法?

2017年12月更新与Git 2.16(2018年第一季度):正在努力支持替代SHA:请参阅“Why doesn't Git use more modern SHA?”。

您将能够使用另一种哈希算法:SHA1不再是Git的唯一哈希算法。

Git 2.18(2018年第二季度)处理的文件。

commit 5988eb6commit 45fa195Ævar Arnfjörð Bjarmason (avar)(2018年3月26日) (由Junio C Hamano -- gitster --合并于commit d877975,2018年4月11日)

  

doc hash-function-transition:澄清什么是Shattered意味着

     

尝试澄清SHAttered攻击在实践中意味着什么   Git的。
  该文本的前一版本没有提及任何Git已经对此特定攻击进行缓解,Shattered研究人员声称该攻击会检测到密码分析冲突攻击。

     

我可能已经弄错了一些细微差别,但据我所知   新文本用SHA-1准确地总结了当前的情况   饭桶。即 git不再使用SHA-1了,它使用了   Hardened-SHA-1 (它们碰巧产生相同的输出   99.99999999999 ...%的时间。)

     

因此,前面的文字在声明:

时是不正确的      
    

[...]作为[SHAttered]的结果,不能考虑SHA-1         加密安全[...]

  
     

事实并非如此。我们对SHAttered进行了缓解,然而   我们认为谨慎行事的是NewHash未来   出现SHA-1或Hardened-SHA-1中的漏洞。

所以new documentation现在读取:

  

Git v2.13.0及其后的版本随后转移到了一个强化的SHA-1   默认情况下实现,不容易受到SHAttered的攻击   攻击。

     

因此,Git实际上已经迁移到不是SHA-1的新哈希   并且不会分享它的漏洞,它的新哈希函数就是这样   碰巧为所有已知输入产生完全相同的输出,   除了由SHAttered研究人员发布的两个PDF和新的   实施(由那些研究人员编写)声称可以检测未来   密码分析碰撞攻击。

     

无论如何,越过SHA-1的任何变体都被认为是谨慎的   到一个新的哈希。无法保证未来对SHA-1的攻击不会   将来发布,这些攻击可能没有可行性   缓解。

     

如果要真正破坏SHA-1及其变体,那就是Git的哈希函数   不能再被视为加密安全了。这个会   影响哈希值的通信,因为我们无法信任   给定的哈希值表示已知的良好内容版本   发言者的意图。

注意:现在同一个文档(Q8 2018,Git 2.19)明确地将“new hash”引用为SHA-256 :请参阅“Why doesn't Git use more modern SHA?”。

答案 6 :(得分:1)

哈希冲突的可能性非常小,以至于真是令人兴奋!世界各地的科学家都在努力实现这一目标,但尚未对其进行管理。对于某些算法,例如MD5,他们成功了。

赔率是多少?

SHA-256 有2 ^ 256个可能的哈希值。这大约是 10 ^ 78 。或者为了更加图形化,碰撞的可能性大约是

1:100 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000

赢得彩票的机会大约是<1> 14 Mio 。与SHA-256发生碰撞的可能性就像在连续11天中赢得彩票一样!

数学解释:14 000 000 ^ 11~2 ^ 256

此外,universe有大约10 ^ 80个原子。这只是SHA-256组合的100倍。

MD5碰撞成功

即使对于 MD5 ,机会也很小。虽然,数学家设法造成了碰撞:

d131dd02c5e6eec4 693d9a0698aff95c 2fcab58712467eab 4004583eb8fb7f89
55ad340609f4b302 83e488832571415a 085125e8f7cdc99f d91dbdf280373c5b
d8823e3156348f5b ae6dacd436c919c6 dd53e2b487da03fd 02396306d248cda0
e99f33420f577ee8 ce54b67080a80d1e c69821bcb6a88393 96f9652b6ff72a70

具有相同的MD5
d131dd02c5e6eec4 693d9a0698aff95c 2fcab50712467eab 4004583eb8fb7f89
55ad340609f4b302 83e4888325f1415a 085125e8f7cdc99f d91dbd7280373c5b
d8823e3156348f5b ae6dacd436c919c6 dd53e23487da03fd 02396306d248cda0
e99f33420f577ee8 ce54b67080280d1e c69821bcb6a88393 96f965ab6ff72a70

这并不意味着MD5现在不太安全,因为它的算法被破解了。您可以故意创建MD5碰撞,但意外MD5碰撞的可能性仍然是2 ^ 128,这仍然很多。

结论

您不必担心碰撞。散列算法是检查文件相同性的第二种最安全的方法。唯一更安全的方法是进行二元比较。

答案 7 :(得分:1)

我想我们现在知道会发生什么 - 你应该期望你的存储库会被破坏(source)。

答案 8 :(得分:1)

我最近在2013-04-29发表了一篇BSD讨论小组的帖子

http://openbsd-archive.7691.n7.nabble.com/Why-does-OpenBSD-use-CVS-td226952.html

海报声称:

  

我使用git rebase进行了一次哈希冲突。

不幸的是,他没有提供他的主张的证据。但也许你想联系他并向他询问这个假设的事件。

但是在更一般的层面上,由于生日攻击,SHA-1哈希冲突的机会在pow(2,80)中为1。

这听起来很多,而且肯定比全世界所有Git存储库中存在的单个文件的总版本数量多。

但是,这仅适用于实际保留在版本历史记录中的版本。

如果开发人员非常依赖于变基,那么每次为分支运行rebase时,该分支的所有版本(或分支的重定位部分)中的所有提交都会获得新的哈希值。对于使用&#34; git filter-branch&#34;修改的每个文件都是如此。因此,&#34; rebase&#34;和&#34; filter-branch&#34;对于随时间生成的哈希数量可能是一个很大的乘数,即使并非所有哈希都实际保留:经常在变基之后(特别是为了#34;清理&#34;分支),原始分支是扔掉了。

但是如果在rebase或filter-branch期间发生碰撞,它仍然会产生不利影响。

另一件事是估计git存储库中哈希实体的总数,并看看它们与pow的距离(2,80)。

假设我们有大约80亿人,他们都将运行git并将他们的东西保存在每人100个git存储库中。让&#39;进一步假设平均存储库有100个提交和10个文件,每个提交只更改其中一个文件。

对于每个修订版,我们至少有一个树对象和提交对象本身的哈希值。与更改的文件一起,每个版本有3个哈希值,因此每个存储库有300个哈希值。

对于80个人的100个存储库,这给了pow(2,47),这仍然远离战争(2,80)。

然而,这不包括上面提到的假设乘法效应,因为我不确定如何将其包含在此估计中。也许它可以大大增加碰撞的机会。特别是如果很长的提交历史(如Linux内核)的非常大的存储库被许多人重新设置用于小的更改,但是为所有受影响的提交创建了不同的哈希值。