哈希码和校验和 - 有什么区别?

141

我的理解是,哈希码和校验和是类似的东西 - 它们都是计算数据块的数字值,这个数字值是相对唯一的。

也就是说,两个数据块生成相同的数字哈希/校验和的概率非常低,可以在应用程序中忽略。

那么,哈希码和校验和是同一个东西吗?还是它们之间有重要的区别?


4
总结以下回答:散列码将输入缩小为一个较小的数字,以最小化冲突的可能性。而校验和则以一种最小化冲突的方式将输入缩小到一个小数字。您可以通过任意重新表述该描述来使它们听起来不同。 - Dan Stahlke
4
@DanStahlke - 不,下面的答案并不是这样说的。 是的,它们都将输入缩小到较小的数字。 但是有很多种方法可以做到这一点,如何选择要使用的算法呢?这取决于你的目标。 总结前两个答案:校验和的目标是“检测最常见的错误”。选择能够产生不同校验和的算法,以检测在你的场景中“最常见”的任何错误。如果你担心会切换一两个位,你可以选择一个保证检测该特定错误的算法!这是非常具体的一种权衡。 - ToolmakerSteve
1
@DanStahlke - 另一方面,哈希码涵盖了可能的广泛权衡。如果我们指的是用于制作哈希表的值,我们知道会有碰撞,很多碰撞。这是一个非常不同的权衡(而不是校验和)。我们试图平均减少碰撞。我们不保证任何事情。可能有一些输入仅相差一个位,但产生相同的哈希值。如果平均我们得到良好的哈希值分布,则完全可以接受。但对于校验和来说是不可接受的。 - ToolmakerSteve
更多关于哈希值的用途和重点。 - CGTheLegend
@DanStahlke的评论并不是为了总结问题的现有答案。如果您认为这样的总结会有用,您可以将总结作为一个独立的答案发布。请参阅帮助中心:"不建议使用评论进行以下任何操作:[...]回答问题或提供现有答案的替代解决方案;而是发布一个实际的答案(或编辑以扩展现有答案);" - undefined
13个回答

91
我会说checksum必须是一个hashcode。然而,并非所有的哈希码都适合作为校验和。
校验和有一个特殊的目的-验证或检查数据的完整性(一些校验和可以超越这个范围,允许进行error-correction)。 "好"的校验和易于计算,并且可以检测到许多类型的数据损坏(例如,一个、两个、三个错误位)。
哈希码只是描述了将数据映射到某个值的mathematical function。当用作数据结构中的索引手段(例如哈希表)时,低碰撞概率是可取的。

7
也许一个可以用作另一个,但考虑到它们有不同的设计目标,这会混淆问题。 - Wim Coenen
8
@gumbo:不是每个哈希码都是校验和。请参考下面MSalters关于字符串的例子。 - MarcH

46

它们各自有不同的用途:

  • 哈希码 - 设计为在其范围内随机(以最小化哈希表等中的冲突)。加密哈希码也被设计为计算上不可逆转。
  • 校验和 - 设计用于检测数据中最常见的错误,通常计算速度很快(用于有效地对数据流进行校验和)。

在实际应用中,同样的函数通常都能胜任这两个目的。特别地,如果你能承担计算成本,那么具有密码学强度的哈希码就是一个好的校验和(一个随机错误几乎不可能破坏强哈希函数)。


1
另外值得一提的是,非加密版本的哈希码可能会在计算时间(接近于CRC)和错误检测之间提供良好的平衡,无论是故意的还是通信错误/比特腐败(因为CRC不能期望检测到故意篡改,因为相对容易地故意设计碰撞)。 - gaborous
2
对我来说,你回答中的关键短语是校验和被设计用于检测最常见的错误。没错,这就是它的作用。它是一种哈希算法,被选择为产生不同值以检测可能的数据损坏。这是一个特定的目的,并导致特定的算法,这些算法针对所关心的扰动类型进行优化。 - ToolmakerSteve
一个功能性校验和可能在其整个域中有很多冲突,只要你检查的错误不太可能导致这样的冲突。例如,你的校验和中可能存在一些周期性,但你并不关心,因为错误永远不会带你到那里。(一个很好的例子是奇偶校验,它只能保护单比特错误。)因此,一个好的校验和的定义本质上取决于错误模型。 - Jonathan Jeffrey

26

确实存在一些差异:

  • 校验和只需要在输入不同的情况下(尽可能频繁地)产生不同的结果,但计算速度也同样重要。
  • 哈希码(用于哈希表)具有相同的要求,并且此外它们还应该均匀分布在代码空间中,特别是对于类似的输入。
  • 加密哈希具有更为严格的要求,即给定一个哈希值,您不能构造出一个生成此哈希值的输入。计算时间其次,并且根据应用程序的不同,甚至可能希望哈希值计算得非常缓慢(以抵御暴力攻击)。

1
我认为校验和对于不同的输入具有不同的优点是没有任何好处的。它们只是用于检查完整性,而不是用于哈希。 - user541686
1
@Mehrdad:你怎么建议在不同的输入下检查完整性而不会得到不同的结果? - Michael Borgwardt
嗯,也许我说错了?我指的是你说“尽可能远”这部分 - 我只是在说它们没有像哈希那样不可预测或“远”的理由。只要输入在经历典型变化时校验和有一些变化,那么它就是一个好的校验和。相比之下,哈希的目标也是尽可能均匀/随机/不可预测/“远”地分布到它们的值域中。 - user541686
我觉得你误解了我的“尽可能”的意思 - 我只是想表达碰撞应该尽量少,虽然这是不可避免的。我会更改措辞。 - Michael Borgwardt
@Mehrdad - 起初我不理解。如果校验和在可能的校验和值上没有良好的分布,那意味着有一些校验和值会被返回给比其他校验和更多的输入值(而不是其他校验和)。但是,这减少了校验和的实用性吗?[这增加了扰动数据返回相同结果的几率,对吗?] 嗯,我错了,你是对的:校验和只需要能够检测到可能的扰动。这可能不需要在所有值上具有均匀分布。 - ToolmakerSteve
1
@ToolmakerSteve:已经过去5年了,但是是的,我想那就是我所指的。校验和并不是用来防止对手攻击的。即使您可以找到一个1 KB字符串,它产生与1 MB字符串相同的校验和,这对于校验和来说也不是真正的问题,因为这种情况发生的概率几乎为零。 - user541686

19

哈希码和校验码都用于从数据项中创建短数字值。区别在于,即使对数据项进行了小修改,校验码值也应该发生改变。对于哈希值,要求仅是真实世界的数据项应具有不同的哈希值。

一个明显的例子是字符串。字符串的校验码应包括每个位,顺序很重要。另一方面,哈希码通常可以实现为长度有限的前缀的校验码。这意味着“aaaaaaaaaaba”会与“aaaaaaaaaaab”具有相同的哈希值,但哈希算法可以处理这种冲突。


1
这个答案让我茅塞顿开。所以哈希函数并不关注数据完整性。 - daparic

10
尽管哈希和校验和相似,它们都是基于文件内容创建值,但哈希不同于创建校验和。校验和旨在验证(检查)数据的完整性并识别数据传输错误,而哈希旨在创建数据的唯一数字指纹。
来源:CompTIA® Security+网络安全基础指南-第五版-Mark Ciampa-第191页

7

维基百科很好地解释了:

校验和函数与哈希函数、指纹、随机化函数和加密哈希函数有关。但是,每个概念都具有不同的应用和因此不同的设计目标。检查位和奇偶校验位是校验和的特殊情况,适用于小块数据(例如社会保障号码、银行帐户号码、计算机字、单个字节等)。一些纠错码基于特殊的校验和,不仅可以检测常见错误,而且在某些情况下还可以恢复原始数据。


34
阅读完之后,我仍然想知道它们之间的区别是什么。 - kirk.burleson
@kirk.burleson - 我认为它们是相同的原则,但在实践中总是要做出权衡。在不同的情况下,适用不同的权衡,因此使用不同的方法。这并不是为存在两个不同的词语辩护,只是说如果你搜索校验和的好技术,你可能会找到一个不同的算法集合,而当你搜索哈希码时则可能不同。 - ToolmakerSteve

6

校验和可以防止意外更改。

密码哈希可以防止非常有动机的攻击者。

当您发送数据位时,可能会发生一些位被翻转、删除或插入的意外事件。为了允许接收方检测(或有时纠正)此类意外事件,发送方使用校验和。

但是,如果您假设有人在传输过程中积极且智能地修改消息,并且您想保护自己免受这种攻击者的攻击,则使用密码哈希(我忽略了对哈希进行加密签名、使用辅助渠道等内容,因为问题似乎没有涉及到这个方面)。


3
"密码哈希"这个术语会增加人们对"哈希"和"校验和"之间的混淆。 "密码校验和"是更好的术语,因为它不会引起这种混淆。 - MarcH

5
哈希码和校验和函数的区别在于它们被设计用于不同的目的。
- 校验和用于查找输入中的某些是否已更改。 - 哈希码用于查找输入中的某些是否已更改,并尽可能使个体哈希码值之间有更多的“距离”。 也可能会对哈希函数有进一步要求,与此规则相反,如能够尽早形成哈希码值的树/簇/桶等。 如果添加一些共享初始随机性,则可达到现代加密/密钥交换的概念。
关于概率:
例如,假设输入数据实际上始终在变化(100%的时间)。并且假设您有一个“完美”的哈希/校验和函数,可以生成1位哈希/校验和值。因此,对于随机输入数据,您将50%的时间获得不同的哈希/校验和值。
- 如果您的随机输入数据中恰好有1位发生了变化,则无论输入数据的大小如何,您都将能够100%地检测到变化。 - 如果您的随机输入数据中有2位发生了变化,则检测“变化”的可能性将被除以2,因为两个变化可能相互抵消,没有哈希/校验和函数将检测到2位实际上在输入数据中是不同的。 ...
这意味着,如果您的输入数据中的位数是哈希/校验和值的多倍,则实际获得不同的哈希/校验和值的概率会减小并且不是恒定的。

4

现在这些术语已经可以互换使用了,但在过去,校验和是一种非常简单的技术,您可以将所有数据相加(通常以字节为单位),并在最后添加一个具有该值的字节..然后您就可以知道原始数据是否已经被损坏。类似于检查位,但使用的是字节。


2

当我提到为文件或数据创建的代码(数字或其他)时,我倾向于使用校验和这个词,该代码可用于“检查”文件或数据是否已损坏。我遇到的最常见用法是检查通过网络发送的文件是否已被更改(故意或非故意地)。


1
因为校验和并不是为了难以反转而设计的,这意味着它们并不适用于检查某些东西是否被故意更改。 - benblasdell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接