我读到有关Git使用SHA-1摘要作为修订的ID的信息。为什么不使用更新版本的SHA?
我读到有关Git使用SHA-1摘要作为修订的ID的信息。为什么不使用更新版本的SHA?
Answers:
为什么不使用更新版本的SHA?
2017年12月:会的。Git 2.16(Q1 2018)是第一个说明和实现该意图的版本。
注意:请参阅下面的Git 2.19:它将是SHA-256。
Git 2.16将提出一个基础架构,以定义Git中使用的哈希函数,并将开始努力探索各种代码路径中的哈希函数。
参见Ramsay Jones(``)的commit c250e02(2017年11月28日)。
请参见brian m的commit eb0ccfd,commit 78a6766,commit f50e766,abade65(2017年11月12日)。卡尔森(bk2204
)。
(通过合并JUNIOÇ滨野- gitster
-在提交721cc43 12月13日2017)
添加表示哈希算法的结构
由于将来我们希望支持其他哈希算法,因此请添加一个代表哈希算法的结构以及所有必须伴随的数据。
添加一个常数以轻松枚举哈希算法。
实现函数typedefs
以创建可被任何哈希算法使用的抽象API,并包装符合该API的现有SHA1函数。公开十六进制大小和二进制大小的值。
尽管一个值始终是另一个值的两倍,但是这两个值在整个代码库中都非常常用,并提供了两个值,从而提高了可读性。在哈希算法结构中不要为空对象ID包含条目。
由于该值为全零,因此可以使用任何大小合适的全零对象ID,并且无需按哈希值存储给定的ID。当前的哈希函数转换计划设想了一个时间,我们将接受来自用户的输入,这些输入可能采用SHA-1或NewHash格式。
由于我们不知道用户提供了哪个,因此添加一个代表未知算法的常量,使我们能够指示必须查找正确的值。
将哈希算法支持与回购设置集成在一起
在将来的Git版本中,我们计划支持其他哈希算法。
将哈希算法的枚举与存储库设置集成在一起,并将指向枚举数据的指针存储在struct repository中。
当然,我们目前仅支持SHA-1,因此请将此值硬编码在中read_repository_format
。
将来,我们将从配置中枚举此值。添加一个常量,
the_hash_algo
hash_algo
指向存储库全局中的结构指针。
请注意,这是用于将数据序列化到磁盘的哈希,而不是用于向用户显示项目的哈希。
过渡计划预计这些可能会有所不同。
我们可以在以后添加一个其他元素(例如ui_hash_algo
)来提供这种情况。
对于Git 2.19(2018年第三季度),2018年8月更新,Git似乎选择SHA-256作为NewHash。
参见Jonathan Nieder()的commit 0ed8d8d(04 Aug 2018 )。
见提交13f5e09通过(2018年7月25日)ÆvarArnfjörðBjarmason( )。 (由Junio C Hamano合并--在commit 34f2297中,2018年8月20日)artagnon
avar
gitster
doc
hash-function-transition
:选择SHA-256作为NewHash从安全性的角度来看,似乎SHA-256,BLAKE2,SHA3-256,K12等都具有相似的安全性。
从安全角度来看,所有这些都是不错的选择。SHA-256具有许多优点:
它已经存在了一段时间,被广泛使用,并且几乎每个加密库(OpenSSL,mbedTLS,CryptoNG,SecureTransport等)都支持它。
当与SHA1DC进行比较时,即使没有加速,大多数矢量SHA-256实现也确实更快。
如果我们正在使用OpenPGP(甚至我想是CMS)进行签名,那么我们将使用SHA-2,因此当我们的安全性依赖于两个单独的算法时,这两个方法就没有意义了当我们仅依靠一个人时,一个人就可能破坏安全性。
所以SHA-256是。
这样更新哈希函数转换设计文档。在此修补程序之后,没有剩余字符串“
NewHash
”的实例,除了2008年作为的变量名t/t9700/test.pl
与无关。
您可以看到Git 2.20(Q4 2018)正在进行向SHA 256的过渡:
见提交0d7c419,提交dda6346,提交eccb5a5,提交93eb00f,提交d8a3a69,提交fbd0e37,提交f690b6b,提交49d1660,提交268babd,提交fa13080,提交7b5e614,提交58ce21b,提交2f0c9e9,提交825544a(2018年10月15日)由布赖恩米。卡尔森(bk2204
)。
见提交6afedba通过(2018年10月15日)SZEDER的Gabor( )szeder
。
(由合并JUNIOÇ滨野- gitster
-在提交d829d49,2018年10月30日)
替换硬编码的常量
根据需要,使用
GIT_MAX_HEXSZ
或 替换几个基于40的常量the_hash_algo
。
将的所有用法转换GIT_SHA1_HEXSZ
为use,the_hash_algo
以便它们适合任何给定的哈希长度。
代替在十六进制对象ID的大小上使用硬编码常量,而改用parse_oid_hex
解析后的对象ID之后的那一点的计算指针。
GIT_SHA1_HEXSZ
被Git 2.22(Q2 2019)进一步删除/替换并提交d4e568b。
Git 2.21(2019年第一季度)将继续这种过渡,该版本添加了sha-256哈希,并将其插入代码以允许使用“ NewHash”构建Git。
见提交4b4e291,提交27dc04c,提交13eeedb,提交c166599,提交37649b7,提交a2ce0a7,提交50c817e,提交9a3a0ff,提交0dab712,提交47edb64(2018年11月14日),以及提交2f90b9d,提交1ccf07c(2018年10月22日)由布赖恩米。卡尔森(bk2204
)。
(由Junio C gitster
Hamano合并--在commit 33e4ae9中,2019年1月29日)
添加SHA-256支持的基本实现(2019年2月)
SHA-1很弱,我们需要过渡到新的哈希函数。
一段时间以来,我们将此新功能称为NewHash
。
最近,我们决定选择SHA-256作为NewHash
。
选择SHA-256背后的原因在该线程中以及哈希函数转换文档的提交历史中都有概述。添加基于off的SHA-256的基本实现
libtomcrypt
,该实现在公共领域中。
对其进行优化和重组,以满足我们的编码标准。
从SHA-1块实现中提取更新和最终函数,因为我们对所有编译器都知道这些函数正确。此实现比SHA-1慢,但是将来的提交中将引入更多性能更好的实现。在哈希算法列表中连接SHA-256,并添加一个测试算法可以正常工作的测试。
请注意,使用此修补程序,仍无法在Git中切换为使用SHA-256。
需要其他补丁来准备代码以处理更大的哈希算法,并且需要进一步的测试修复。
hash
:使用OpenSSL添加SHA-256实现我们已经有适用于SHA-1的OpenSSL例程,因此也要添加SHA-256的例程。
在Core i7-6600U上,此SHA-256实现与SHA1DC SHA-1实现相比具有优势:
SHA-1: 157 MiB/s (64 byte chunks); 337 MiB/s (16 KiB chunks) SHA-256: 165 MiB/s (64 byte chunks); 408 MiB/s (16 KiB chunks)
sha256
:使用添加SHA-256实现libgcrypt
通常,使用汇编语言编写的加密例程比C语言可以获得更好的性能,SHA-256也是如此。
此外,由于许可原因,大多数Linux发行版无法分发链接到OpenSSL的Git。大多数具有GnuPG的系统也将具有
libgcrypt
,因为它是GnuPG的依赖项。
libgcrypt
对于几KiB或更大的消息,它也比SHA1DC实现更快。为了进行比较,在Core i7-6600U上,此实现以355 MiB / s的速度处理16个KiB块,而SHA1DC以337 MiB / s的速度处理等效的块。
此外,libgcrypt已根据LGPL 2.1许可,该协议与GPL兼容。添加使用libgcrypt的SHA-256实现。
Git 2.24(Q4 2019)继续进行升级
见提交aaa95df,提交be8e172,提交3f34d70,提交fc06be3,提交69fa337,提交3a4d7aa,提交e0cb7cd,提交8d4d86b,提交f6ca67d,提交dd336a5,提交894c0f6,提交4439c7a,提交95518fa,提交e84f357,提交fe9fec4,提交976ff7e,提交703d2d4,提交9d958cc,提交7962e04,提交费用4930(2019年8月18日)by brian m。卡尔森(bk2204
)。
(通过合并JUNIOÇ滨野- gitster
-在提交676278f,2019年10月11日)
代替使用
GIT_SHA1_HEXSZ
和硬编码的常量,切换到使用the_hash_algo
。
使用Git 2.26(Q1 2020),测试脚本已准备好在对象名称将使用SHA-256的那一天。
见提交277eb5a,提交44b6c05,提交7a868c5,提交1b8f39f,提交a8c17e3,提交8320722,提交74ad99b,提交ba1be1a,提交cba472d,提交82d5aeb,提交3c5e65c,提交235d3cd,提交1d86c8f,提交525a7f1,提交7a1bcb2,提交cb78f4f,提交717c939,提交08a9dd8,提交215b60b,提交194264c(2019年12月21日)by brian m。卡尔森(bk2204
)。
(通过合并JUNIOÇ滨野- gitster
-在提交f52ab33,2020年2月5日)
例:
t4204
:使散列大小独立签字人:brian m。卡尔森
使用
$OID_REGEX
而不是硬编码的正则表达式。
因此,不要使用:
grep "^[a-f0-9]\{40\} $(git rev-parse HEAD)$" output
测试正在使用
grep "^$OID_REGEX $(git rev-parse HEAD)$" output
而OID_REGEX
来自提交bdee9cd通过(2018年5月13日),布赖恩·米 卡尔森(bk2204
)。
(由Junio C gitster
Hamano合并--在commit 9472b13中,2018年5月30日,Git v2.18.0-rc0)
t/test-lib
:介绍OID_REGEX
签字人:brian m。卡尔森
当前,我们有一个变量,
$_x40,
其中包含一个与完整的40个字符的十六进制常量匹配的正则表达式。但是,有了
NewHash
,我们将拥有超过40个字符的对象ID。在这种情况下,
$_x40
将是一个令人困惑的名称。创建一个
$OID_REGEX
变量,该变量将始终反映与适当的对象ID匹配的正则表达式,而不管当前哈希的长度如何。
而且,仍在测试中:
见提交f303765,提交edf0424,提交5db24dc,提交d341e08,提交88ed241,提交48c10cc,提交f7ae8e6,提交e70649b,提交a30f93b,提交a79eec2,提交796d138,提交417e45e,提交dfa5f53,提交f743e8f,提交72f936b,提交5df0f11,提交07877f3,提交6025e89,提交7b1a182,提交94db7e3,由brian m。bk2204
提交db12505(2020年2月7日)卡尔森()。
(由Junio C gitster
Hamano合并--在5af345a号提交中,2020年2月17日)
t5703
:使用SHA-256进行测试签字人:brian m。卡尔森
该测试使用的对象ID的长度为40个十六进制字符,导致在以SHA-256作为哈希值运行时,该测试不仅不通过,而且挂起。
使用
test_oid_init
和将此值更改为固定的伪对象IDtest_oid
。此外,请确保使用带有字段的剪切(而不是固定长度)来提取适当长度的对象ID。
一些代码路径被赋予了一个存储库实例作为参数,以便在存储库中工作,但是将the_repository
实例传递给其被调用者,后者已通过Git 2.26(2020年第一季度)进行了清理(某种程度上)。
请参阅Matheus Tavares()的提交b98d188,提交2dcde20,提交7ad5c44,提交c8123e7,提交5ec9b8a,提交a651946,提交eb999b3(2020年1月30日)。(通过合并JUNIOÇ滨野- -在提交78e67cd,2020年2月14日)matheustavares
gitster
sha1-file
:允许check_object_signature()
处理任何回购签字人:Matheus Tavares
某些调用者
check_object_signature()
可以在任意存储库上工作,但存储库不会传递给此函数。而是the_repository
始终在内部使用。
要解决可能存在的不一致,请允许该函数接收结构存储库,并使那些调用程序传递正在处理的存储库。
基于:
sha1-file
:传递git_hash_algo
给hash_object_file()
签字人:Matheus Tavares
允许
hash_object_file()
通过引入上的任意回购工作git_hash_algo
参数。更改在其作用域内具有结构存储库指针的调用者,以git_hash_algo
从所述存储库传递。
对于所有其他呼叫者,请传递the_hash_algo
,已在内部使用hash_object_file()
。
此功能将在以下修补程序中使用,以使其check_object_signature()
能够在任意存储库上使用(反过来,该存储库将用于修复object.c
:parse_object()上的不一致)。
git rev-parse
现在可以打印将使用的哈希值:stackoverflow.com/a/58862319/6309。空树有一个新的SHA2 ID:stackoverflow.com/a/9766506/6309
更新:上面的问题和答案是从2015年开始的。此后,Google宣布了第一次SHA-1冲突:https : //security.googleblog.com/2017/02/announcing-first-sha1-collision.html
显然,我只能从外面推测为什么Git继续使用SHA-1,但这可能是以下原因之一:
unsigned char[20]
缓冲区;-),从一开始就为加密敏捷性进行编程要容易得多,而不是以后对其进行改造。一些链接:
我个人的观点是,尽管实际的攻击可能尚需时日,但即使确实发生,人们也可能最初会通过改变散列算法本身的方式减轻攻击,如果您确实关心安全性,那您应该犯错谨慎选择算法,并不断提高安全性,因为攻击者的能力也只朝一个方向发展,因此将Git用作榜样是不明智的,尤其是作为Git的目的使用SHA-1并不意味着要加密安全。
这是关于从SHA1迁移到Mercurial的紧迫性的讨论,但它也适用于Git:https : //www.mercurial-scm.org/wiki/mpm/SHA1
简而言之:如果您今天不十分勤快,则漏洞比sha1要糟糕得多。但是尽管如此,Mercurial还是在10多年前就开始准备从sha1迁移出去。
多年来,为SHA1的后续产品改型Mercurial的数据结构和协议的工作正在进行中。10年前,随着RevlogNG的推出,Mercurial 0.9在我们的revlog结构中为更大的哈希分配了存储空间。最近引入的bundle2格式支持通过网络交换不同的哈希类型。剩下的剩下的就是选择替换功能和选择向后兼容策略。
如果git在Mercurial之前没有从sha1迁移过来,则始终可以通过使用hg-git保留本地Mercurial镜像来增加另一级别的安全性。