git中的哈希冲突

问题描述 投票:150回答:9

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

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

可以改进git以适应它,或者我是否必须更改为新的哈希算法?

(请不要通过讨论这个问题来转移这个问题 - 谢谢)

git hash sha1 hash-collision
9个回答
81
投票

Picking atoms on 10 Moons

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 000个不同的SHA-1哈希... 1048。

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

在此扩展我们可以问这个问题......

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

这与所谓的“生日攻击”有关,而生日攻击又指的是“生日悖论”或“生日问题”,它指出当你从一个给定的集合中随机挑选时,你很可能在你不太可能之前选择少数选了两次东西。但“令人惊讶的少数”在这里是一个非常相对的术语。

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

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

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

"But when a collision does occur, then what actually happens?"

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

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

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

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

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


63
投票

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

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


25
投票

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

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

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

考虑这个问题并没有错 - 这是一个很好的问题,很多人只是因为“不太可能不值得思考”而被忽略了 - 但它确实比那复杂得多。如果它发生了,它应该是非常容易检测的,它不会是正常工作流程中的沉默腐败。


8
投票

可以改进git以适应它,或者我是否必须更改为新的哈希算法?

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


7
投票

你可以在“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可以改进以适应它,还是我必须改为新的哈希算法?

使用Git 2.16(2018年第一季度)更新2017年12月:支持替代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研究人员称这种攻击将检测到密码分析冲突攻击。

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

因此,前面的文字断言:

[...]作为[SHAttered]的结果,SHA-1不再被视为加密安全[...]

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

所以new documentation现在写道:

随后Git v2.13.0及更高版本默认转移到强化的SHA-1实现,不易受到SHAttered攻击。

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

无论如何,将SHA-1的任何变体移到新哈希都是谨慎的做法。不能保证将来不会发布对SHA-1的未来攻击,这些攻击可能没有可行的缓解措施。

如果要真正破坏SHA-1及其变体,Git的散列函数就不再被认为是加密安全的。这会影响散列值的通信,因为我们不能相信给定的散列值代表了发言者想要的已知良好内容版本。

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


5
投票

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

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

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


2
投票

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

What are the odds?

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

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

数学解释:qazxsw poi ^ 11~2 ^ 256

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

Successful MD5 collision

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

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

MD5与MD5相同

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

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

结论

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


1
投票

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


1
投票

我最近在2013-04-29发现了一个BSD讨论组的帖子

source

海报声称:

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

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

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

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

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

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

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

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

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.