如果我在使用git时发生哈希冲突,实际上会发生什么?
例如,我设法用相同的sha1校验和提交两个文件,git会注意到它还是损坏其中一个文件?
可以改进git来使其兼容吗,还是我必须更改为新的哈希算法?
(请不要通过讨论这种可能性的可能性来避免这个问题-谢谢)
如果我在使用git时发生哈希冲突,实际上会发生什么?
例如,我设法用相同的sha1校验和提交两个文件,git会注意到它还是损坏其中一个文件?
可以改进git来使其兼容吗,还是我必须更改为新的哈希算法?
(请不要通过讨论这种可能性的可能性来避免这个问题-谢谢)
Answers:
SHA-1哈希是一个40进制字符串...每个字符4位乘以40 ... 160位。现在我们知道10位大约是1000位(准确地说是1024位),这意味着有10000000000000000000000000000000000000000000000000000000000000000 SHA-1哈希... 10 48。
这相当于什么?月亮大约由10个组成 47个原子组成。因此,如果我们有10个卫星...而您在其中一个卫星上随机选择一个原子...然后继续在它们上随机选择一个原子...那么您可能会两次选择相同的原子是两个给定的git commit将具有相同的SHA-1哈希的可能性。
扩展这个我们可以问一个问题...
在开始担心冲突之前,您需要在存储库中进行多少次提交?
这与所谓的“生日攻击”有关,后者又称为“生日悖论”或“生日问题”,它指出当您从给定集合中随机选择时,您极有可能需要很少的选择采了两次 但是“令人惊讶地很少”在这里是一个相对的术语。
维基百科上有一张关于生日悖论碰撞概率的表格。没有用于40个字符的哈希的条目。但是对32个字符和48个字符的条目进行插值会使我们落在5 * 10 22 git commit 的范围内,发生冲突的可能性为0.1%。那就是五千亿次不同的提交,或五十个Zetta提交,在您甚至有0.1%的机会发生碰撞之前。
仅这些提交的哈希字节总和就比一年内在地球上生成的所有数据都多,这意味着您需要比YouTube流视频输出更快的代码。祝你好运。:D
关键是除非有人故意造成碰撞,否则随机发生碰撞的可能性非常小,您可以忽略此问题
好的,假设确实发生了这种可能性,或者假设有人设法裁定了故意的SHA-1哈希冲突。那会发生什么呢?
在这种情况下,有人进行了试验是一个很好的答案。我将引用该答案:
- 如果已经存在具有相同散列的Blob,那么您将根本不会收到任何警告。一切似乎都还可以,但是当您按下,有人克隆或还原时,您将丢失最新版本(与上述内容一致)。
- 如果树对象已经存在,并且您使用相同的哈希值创建了一个Blob:一切似乎都很正常,直到您尝试推送或有人克隆您的存储库为止。然后,您将看到存储库已损坏。
- 如果提交对象已经存在,并且您使用相同的哈希值创建了Blob:与#2相同-损坏
- 如果Blob已经存在,并且您使用相同的哈希值创建了一个提交对象,则在更新“ ref”时它将失败。
- 如果blob已经存在,并且您使用相同的哈希值创建树对象。创建提交时它将失败。
- 如果树对象已经存在,并且您使用相同的哈希值创建了一个提交对象,则在更新“ ref”时它将失败。
- 如果树对象已经存在,并且您使用相同的哈希值创建树对象,那么一切都会好起来的。但是,当您提交时,所有存储库都将引用错误的树。
- 如果提交对象已经存在,并且您使用相同的哈希值创建了一个提交对象,那么一切都会好起来的。但是,当您提交时,将永远不会创建该提交,并且HEAD指针将移至旧的提交。
- 如果提交对象已经存在,并且您使用相同的哈希值创建树对象,则在创建提交时它将失败。
如您所见,有些情况不好。特别是案例2和案例3弄乱了您的存储库。但是,故障似乎仍然存在于该存储库中,并且攻击/怪诞的可能性不可能传播到其他存储库。
同样,故意碰撞的问题似乎也被认为是真正的威胁,因此,例如GitHub正在采取措施来防止它。
如果两个文件在git中具有相同的哈希值,则将这些文件视为相同。在绝对不可能的情况下,您总是可以退回一次提交,并更改文件中的某些内容,这样它们就不会再发生冲突了……
在没有解释为什么不是问题的情况下,实际上不可能用正确的“但是”来回答这个问题。如果不能真正掌握哈希的真正含义,就不可能做到这一点。它比您在CS程序中可能遇到的简单情况要复杂得多。
这里对信息论有一个基本的误解。如果通过丢弃一些信息(即哈希)将大量信息减少为更少量,则可能会发生与数据长度直接相关的冲突。数据越短,则可能会越少。现在,绝大多数冲突将变得乱七八糟,从而使它们实际发生的可能性更大(您永远都不会检查出乱七八糟的东西……即使二进制映像有些结构化)。最后,机会很少。要回答您的问题,是的,git会将它们视为相同,更改哈希算法将无济于事,它将需要某种“第二次检查”,但最终,您将需要尽可能多的“其他检查”数据因为数据长度是100%可以确定的...请记住,您将是99.99999...。到非常长的数字。...确保像您描述的那样进行简单检查。SHA-x是加密上强的散列,这意味着通常不难有意创建两个彼此非常相似且具有相同散列的源数据集。数据中的一点变化应该在散列输出中产生多个(最好是尽可能多的)变化,这也意味着很难(但并非完全不可能)从散列中恢复到完整的冲突,从而从那组冲突中拉出原始消息-除了少数冲突之外,其余所有消息都是乱码,如果消息长度很大,那么仍然有很多可以筛选的消息。加密哈希的缺点是它们的计算速度很慢...通常。
那么,那对Git意味着什么呢?不多。散列很少(相对于其他所有散列)完成,以至于运算的总体代价较低。发生两次碰撞的机会非常低,这不是现实的机会,因此不会立即被发现(即,您的代码很可能突然停止构建),从而允许用户解决问题(备份版本,并再次进行更改,由于时间的变化,您几乎肯定会获得不同的哈希值,该哈希值也以git的形式提供。如果您在git中存储任意二进制文件,那么对您来说可能是一个真正的问题,这实际上并不是主要用途模型。如果您想这样做...最好使用传统数据库。
考虑这一点没有错-这是一个很好的问题,很多人只是因为“不太可能不值得考虑”而假装-但实际上比这复杂得多。如果确实发生,那么它应该很容易被检测到,在正常的工作流程中不会是无声的损坏。
you'll almost certainly get a different hash because of the time change, which also feeds the hash in git
哈希不是仅基于文件的内容吗?
可以改进git来使其兼容吗,还是我必须更改为新的哈希算法?
任何散列算法都可能发生冲突,因此更改散列函数并不能排除问题,只会使其发生的可能性降低。因此,您应该选择一个非常好的哈希函数(SHA-1已经存在,但是您不想被告知:)
您可以在“ Git如何处理Blob上的SHA-1碰撞? ”中看到很好的研究。
由于SHA1碰撞现在可以(我在引用这个答案与shattered.io),知道了Git 2.13(Q2 2017)将提高/使用的“检测企图制造冲突”变种缓解目前的状况SHA1实现作者:马克·史蒂文斯(CWI)和丹·舒莫(Microsoft)。
请参阅Jeff King()的提交f5f5e7f,提交8325e43,提交c0c2006,提交45a574e,提交28dc98e(2017年3月16日)。(通过合并JUNIOÇ滨野- -在提交48b3693 3月24日2017)peff
gitster
Makefile
:使DC_SHA1
默认我们以前默认使用OpenSSL库中的SHA1实现。
由于我们在最近的“崩溃”声明后要努力防止碰撞攻击,因此请切换默认值以鼓励人们使用DC_SHA1实现。
那些想使用OpenSSL实施的人可以OPENSSL_SHA1=YesPlease
在运行“make
” 时明确要求它。实际上,我们没有Git与对象的碰撞,因此,我们能做的最好的事情就是通过test-sha1运行一个破碎的PDF。这将触发碰撞检查并死亡。
可以改进Git来使其兼容吗,还是我必须更改为新的哈希算法?
2017年12月使用Git 2.16 更新(2018年第一季度):支持替代SHA的工作正在进行中:请参阅“ 为什么Git不使用更现代的SHA? ”。
您将能够使用另一种哈希算法:SHA1不再是Git的唯一算法。
Git 2.18(Q2 2018)记录了该过程。
见提交5988eb6,提交45fa195通过(2018年3月26日)ÆvarArnfjörðBjarmason( )avar
。
(通过合并JUNIOÇ滨野- gitster
-在提交d877975 4月11日2018)
doc
hash-function-transition
:阐明“破碎”的含义尝试弄清楚“破碎”攻击在实践中对Git意味着什么。
文本的先前版本没有提及Git已经对该特定攻击进行了缓解的任何方法,粉碎的研究人员声称,它将检测到密码分析冲突攻击。我可能误会了一些细微差别,但据我所知,新文本准确地总结了git中SHA-1的当前情况。即git不再使用SHA-1,而是使用Hardened-SHA-1(它们恰好在99.99999999999 ...%的时间内产生相同的输出)。
因此,先前的文本在断言以下方面是错误的:
[...]由于[不完整]的结果,SHA-1不再被认为是加密安全的[...]
事实并非如此。我们可以缓解SHATHETED的问题,但是 我们认为,应谨慎处理
NewHash
SHA-1或Hardened-SHA-1中将来的漏洞。
因此,新文档现在显示为:
Git v2.13.0及更高版本随后默认情况下移至强化的SHA-1实现,该漏洞不易受到SHAttered攻击。
因此,Git实际上已经迁移到了不是SHA-1且没有共享漏洞的新哈希中,它的新哈希函数恰好为所有已知输入产生了完全相同的输出,除了SHAttered发布的两个PDF之外。研究人员,以及由这些研究人员编写的新实现声称可以检测未来的密码分析碰撞攻击。
无论如何,将SHA-1的任何变体移到新的哈希表上都是谨慎的做法。无法保证将来不会再发布有关SHA-1的攻击,并且这些攻击可能没有可行的缓解措施。
如果要真正破坏SHA-1及其变体,就不能再认为Git的哈希函数在密码上是安全的。这将影响哈希值的通信,因为我们无法相信给定的哈希值表示说话者想要的内容的已知良好版本。
注意:同一份文档(2018年第三季度,Git 2.19)现在将`` 新哈希''显式引用为SHA-256:请参见``为什么Git不使用更现代的SHA? ''
Google现在声称在某些前提下有可能发生SHA-1碰撞: https //security.googleblog.com/2017/02/announcing-first-sha1-collision.html
由于git使用SHA-1来检查文件完整性,因此这意味着git中的文件完整性受到损害。
IMO,git绝对应该使用更好的哈希算法,因为现在有可能发生故意的冲突。
哈希冲突极不可能发生,以至于令人震惊!全世界的科学家都在努力实现这一目标,但尚未实现。但是对于某些算法(例如MD5),它们还是成功的。
SHA-256具有2 ^ 256个可能的哈希。大约是10 ^ 78。或更确切地说,发生碰撞的机会大约为
1:10000亿000000000 000000000000 000000000000
赢得彩票的机会约为1:14Mio。与SHA-256发生碰撞的机会就像连续11天赢得彩票!
数学解释:14000000 ^ 11〜2 ^ 256
此外,宇宙大约有10 ^ 80个原子。仅比SHA-256组合多100倍。
即使是MD5,机会也很小。不过,数学家设法造成了碰撞:
d131dd02c5e6eec4 693d9a0698aff95c 2fcab5 8 712467eab 4004583eb8fb7f89 55ad340609f4b302 83e4888325 7 1415a 085125e8f7cdc99f d91dbdf280373c5b d8823e3156348f5b ae6dacd436c919c6 dd53e2 b 487da03fd 02396306d248cda0 e99f33420f577ee8 ce54b67080 a 80d1e c69821bcb6a88393 96f965 2 b6ff72a70
与MD5相同
d131dd02c5e6eec4 693d9a0698aff95c 2fcab5 0 712467eab 4004583eb8fb7f89 55ad340609f4b302 83e4888325 f 1415a 085125e8f7cdc99f d91dbd7280373c5b d8823e3156348f5b ae6dacd436c919c6 dd53e2 3 487da03fd 02396306d248cda0 e99f33420f577ee8 ce54b67080 2 80d1e c69821bcb6a88393 96f965 a b6ff72a70
这并不意味着MD5的算法已经破解,因此它的安全性有所降低。您可以故意创建MD5冲突,但是偶然的MD5冲突的机会仍然是2 ^ 128,这仍然很多。
您不必担心碰撞。哈希算法是检查文件相同性的第二种最安全的方法。唯一安全的方法是二进制比较。
好吧,我想我们现在知道会发生什么—您应该期望您的存储库会损坏(源)。
我最近在BSD讨论组中找到了2013-04-29的帖子
http://openbsd-archive.7691.n7.nabble.com/Why-does-OpenBSD-use-CVS-td226952.html
海报声称:
我使用git rebase遇到一次哈希冲突。
不幸的是,他没有提供任何证据。但是也许您想与他联系并询问他有关此事件的信息。
但是,从更一般的角度来看,由于生日攻击,pow(2,80)中发生SHA-1哈希冲突的机会为1。
这听起来很多,而且肯定比世界上所有Git存储库中单个文件的版本总数之和还要多。
但是,这仅适用于实际保留在版本历史记录中的版本。
如果开发人员非常依赖于变基,则每次为分支运行变基时,该分支的所有版本(或该分支的变基部分)中的所有提交都会获得新的哈希值。对于每个用“ git filter-branch”修改的文件,情况也是如此。因此,“哈希值”和“过滤器分支”对于随着时间的推移生成的哈希数可能是很大的乘数,即使实际上并没有全部保留它们:通常,在重新定基础后(尤其是为了“清理”分支的目的) ),原来的分支将被丢弃。
但是,如果碰撞发生在调整基准或过滤器分支期间,则仍可能产生不利影响。
另一件事是估计git存储库中散列实体的总数,并查看它们与pow(2,80)有多远。
假设我们有大约80亿人,并且所有人都将运行git并将他们的内容保持在每人100个git存储库中的版本。让我们进一步假设平均存储库有100个提交和10个文件,并且每个提交中只有一个文件更改。
对于每个修订,我们至少对于树对象和提交对象本身都有一个哈希。连同更改的文件,我们每个修订版有3个哈希,因此每个存储库有300个哈希。
对于80亿人口的100个存储库,得出的pow(2,47)与pow(2,80)仍然相去甚远。
但是,这不包括上述假定的乘法效果,因为我不确定如何将其包括在此估计中。可能会大大增加碰撞的机会。尤其是如果很多人将非常长的提交历史(例如Linux Kernel)的大型存储库基于微小的更改重新建立了基础,而这些更改却为所有受影响的提交创建了不同的哈希值。
I've been informed by the git Gods that the chances of a SHA1 collision is the same as the Earth being sucked up into the black hole created by the CERN accelerator. If this is indeed true, then there's no need for that extra memcmp.
,来源:lwn.net/Articles/307281