“哈希”到底是什么(又到底是什么)?


38

我听说过“散列”一词在不同的上下文中(在计算世界中)都有不同的含义。例如,在“难于学习Python”这本书中,在字典一章中说:“ Python称它们为“字典”。其他语言称它们为“哈希”。”那么,哈希字典是否有用?

该词的另一种常见用法是与加密有关。我也听说(和阅读)人们在高级编程中使用“哈希”一词作为特定功能。

那到底是什么呢?

任何人(有时间并且有知识的人)都可以友善地解释“哈希(或哈希)”的本质吗?


8
维基百科上有关于哈希表加密哈希函数的详细文章。您在找什么,不是吗?
David Richerby '16

1
您已经列出了术语“哈希”的多种用法,并且还有更多用途。因此,您期望如何确切地回答“这到底是什么?”?
拉斐尔

4
在这种意义上,“哈希”是“哈希表”的缩写,例如,使用哈希来组织密钥的表。这有点像将汽油称为“气体”-您不希望“气体”为气态或具有类似汽油性质的气体,对吗?这种情况一直伴随着语言发生-特别是缩短是单词重叠的非常常见的来源。
a安

1
“这个词没有定义-没有人知道什么是哈希。” - 魔鬼字典
jpmc26 '16

重新思考一下什么是哈希函数:哈希函数只是具有一堆属性的某些函数,但并不是如何定义它才是相关的,而是我们希望它具有的属性-我们从想要的方法中得出使用功能-这是相关的。因为我们希望使用它来快速访问内容,所以我们希望它是可有效计算的。因为我们没有可用的无限空间,所以我们希望共域是有限的。因为我们希望尽可能避免冲突,所以我们希望散列函数均匀散布散列。
G. Bach

Answers:


44

Wikipedia上有关散列函数的文章非常好,但在这里我会介绍一下。


什么是哈希?

“哈希”实际上是一个广义术语,在不同的上下文中具有不同的形式含义。您的问题没有一个完美的答案。我将解释基本的基本概念,并提及该术语的一些最常见用法。

“散列”是被称为散列函数的函数 ,其将输入对象作为对象并输出字符串或数字。输入对象通常是基本数据类型的成员,例如字符串,整数或由其他对象(例如用户定义的结构)组成的较大数据类型。输出通常是数字或字符串。名词“哈希”通常是指此输出。动词“哈希”通常表示“应用哈希函数”。哈希函数应具有的主要属性是:h

  1. 它应该易于计算和
  2. 输出应相对较小。

例:

假设我们要对从0到999,999,999到0到99之间的数字进行哈希处理。一个简单的哈希函数可以是。h(x)=xmod100

常见的其他属性:

根据用例,我们可能希望哈希函数满足其他属性。以下是一些常见的其他属性:

  1. 均匀性:通常,我们希望对象的哈希值是不同的。此外,我们可能希望散列“散布”。如果我想将某些对象散列到100个存储桶中(因此我的散列函数的输出是0-99之间的数字),那么我通常希望大约1/100个对象位于存储桶0中,大约1/100个对象位于存储桶0中桶1,依此类推。

  2. 加密抗碰撞性:有时甚至更远,例如,在加密中,我可能希望使用哈希函数,这样对手在计算上很难找到映射到相同输出的两个不同输入。

  3. 压缩:我经常想将任意大的输入散列为恒定大小的输出或固定数量的存储桶。

  4. 确定性:我可能希望散列函数的输出在两次运行之间不发生变化,即同一对象上散列函数的输出将始终保持不变。这似乎与上面的一致性冲突,但是一种解决方案是随机选择一次哈希函数,而不在运行之间更改它。


一些应用

一个常见的应用是诸如哈希表之类的数据结构,这是一种实现字典的方法。在这里,您分配了一些内存,例如100个“存储桶”。然后,当要求将对(键,值)存储在字典中时,您将该键散列为数字0-99,并将该对存储在内存中的相应存储区中。然后,当要求您查找密钥时,您可以使用相同的哈希函数将该密钥哈希到数字0-99中,并检查该存储桶以查看该密钥是否在其中。如果是这样,则返回其值。

请注意,您还可以通过其他方式实现字典,例如使用二叉搜索树(如果您的对象是可比较的)。

另一个实用的应用是校验和,它是检查两个文件是否相同的方法(例如,文件未从其先前版本中损坏)。由于哈希函数不太可能将两个输入映射到相同的输出,因此您需要计算并存储第一个文件的哈希,通常以字符串表示。此哈希很小,也许只有几十个ASCII字符。然后,当您获得第二个文件时,对它进行哈希处理并检查输出是否相同。如果是这样,几乎可以肯定它是逐字节完全相同的文件。

密码学的另一个应用是,这些散列应该很难“反转”-也就是说,给定输出和哈希函数,计算上很难找出导致该输出的输入。密码的一种用法是:而不是存储密码本身,而是存储密码的加密哈希(可能包含其他成分)。然后,当用户输入密码时,您需要计算其哈希值并检查它是否与正确的哈希值匹配;如果是这样,则说明密码正确。(现在,即使是能够查看并找出保存在服务器上的哈希的人,也没有那么容易的时间假装成为用户。)这种应用可能是输出与输入一样长或更长的情况,因为输入太短了。


1
很好的解释,但我不同意“非常不可能”。请参阅:programmers.stackexchange.com/questions/49550/…确实会发生冲突,有时甚至经常发生冲突。
奥利维尔·杜拉克

8
还应注意,在密码学的上下文中,术语“哈希”非常强烈地表示“单向”操作,在实践中不能轻易逆转。如果可以轻松地将其反转,则称为“加密”。这就是为什么Security.SE上的人员会告诉您始终对客户密码进行哈希处理,而不要对其进行加密的原因。
Ixrec

4
没有“散布”的散列仍然是散列,可能对您的应用程序来说不是一个很好的散列。
停止Harming Monica

1
当然,这些都是好点。
usul 2016年

10

散列函数是一个函数,它的输入,并产生固定大小的值。例如,您可能具有一个哈希函数stringHash,该函数可以接受string任意长度的a并生成一个32位整数。

通常,可以说哈希函数的输出是哈希(也称为哈希值或哈希和)是正确的。但是,有时人们将函数本身称为hash。这在技术上是不正确的,但是通常被忽略,因为通常(在上下文中)人们认为哈希函数哈希函数

哈希函数的典型用法是实现哈希表。哈希表是一种将值与通常称为键的其他值相关联的数据结构。它通过在键上使用哈希函数来生成固定大小的哈希值,以用于快速查找其存储的数据来实现此目的。我不会对其进行详细说明,但是这里的关键事实是它被称为哈希表,因为它依赖于哈希函数来产生哈希值(哈希)。

这是造成一些混乱的地方,因为有些人(再次,有些不正确)将哈希表称为哈希。在其他的答案说,有时一个给定的语言的实施的哈希表指的是哈希表哈希(尤其是Perl中做到这一点,但我希望其他语言做的一样好)。其他语言选择将其哈希表的实现称为字典。Python是这些语言之一,但是由于它们在语言中的根深蒂固,许多Python用户将术语字典缩写为“ dict”。

因此,尽管术语“ 哈希”的正确用法是指由哈希函数产生的哈希值,但人们有时也会非正式地使用该术语来指代哈希函数哈希表,从而造成混乱。


2
我不确定将哈希表或哈希函数称为“哈希” 是否真的不正确(例如,使用“华盛顿”来表示“美国”似乎并不差,例如“华盛顿谨慎地欢迎中国的声明”。但是我同意这很令人困惑,并且很高兴您在回答中对此很清楚。
David Richerby '16

1
@DavidRicherby形式上,我正式地说,工作“哈希”是未定义的。“哈希函数”,“哈希值”,“哈希表”和“对字符串进行哈希”都具有精确的数学定义,但“哈希”不明确。同样,我知道您所说的“华盛顿”是什么意思,但是如果我将“华盛顿”解释为“乔治华盛顿”或“丹泽尔华盛顿”而不是“华盛顿市”,那您的句子还是有意义的,这是一种高度非正式的方式指联邦政府。底线:请注意不要将“了解您的意思”混淆为严格的正式定义。
Mike Ounsworth

@DavidRicherby那不是真正的类比。错误是值得商but的,但非正式性却不是。
法老

2

散列函数广泛地是图像小于域的任何函数。这种函数的输出f(x)可以称为“的散列x”。

在计算机科学中,我们通常会遇到哈希函数的两种应用。

第一种是用于哈希表之类的数据结构的,我们要在其中将键域(例如32位整数或任意长度的字符串)映射到数组索引(例如0到100之间的整数)。目的是使数据结构的性能最大化。通常需要的哈希函数的属性是简单性和均匀的输出分布。

Perl称其内置的关联数组类型为“ hash”,这似乎是造成您困惑的原因。我不知道有其他语言可以做到这一点。松散地,数据结构可以看作是哈希函数本身(其中域是键的当前集合),但也可以实现为哈希表。

第二个用于加密:消息身份验证,密码/签名验证等。该域通常是任意字节字符串。在这里,我们关注的是安全性-有时有时会故意降低性能-有用的属性是碰撞和原像抵抗。


我仍然反对您的第一句话,因为用SHA-512哈希32个字符的密码时,输入空间实际上小于输出空间。将哈希函数链接在一起时,域和范围是相同的;输入空间的大小无关紧要。Pharap的答案具有正确的定义:“散列函数是具有固定长度输出的任何函数”。就是这样,这就是您所需要的,您正在谈论的所有其他条件也由此暗示。
Mike Ounsworth

@MikeOunsworth,但SHA-512的域是任意长度的二进制字符串。我想我可以窃取Pharaps的用语,但是我试图为OP的利益明确条件。我实际上不确定“固定长度”是否必要,也没有明确定义。
停止Harming Monica

@OrangeDog好的,但是我可以将SHA-512包装在一个称为的函数中MikesHash(),该函数接受长度为12的字符串并将其传递给SHA-512,然后返回输出。我很确定它MikesHash()仍然符合哈希函数的定义。(实际上,您是对的,我们使用的哈希函数接受任意长度的输入,但我认为,如果不是这样,则不会失败。)
Mike Ounsworth

同样,@ MikeOunsworth我可以包装它,以便在msb为1时将输出截断或填充。输出不再是固定长度的,但它仍然是哈希函数吗?
停止Harming Monica

@OrangeDog我会拒绝。我一直以来的观点是,散列函数必须映射到固定大小的输出,但输入大小无关紧要。我们已经离题很远了。您的答案包含很多内容,请谨慎对待您的正式定义;-)
Mike Ounsworth

0

很好的问题,罗勒·阿吉斯(Basil Ajith),

这是我对今天正在处理的东西的哈希表示什么的观点。

*

使用校验和来验证tarball与下载页面是否一致

*

在此处输入图片说明 戴上审计员的帽子,我的意思是巫师长袍

hash是一个值/字符串/任何形式/标签,请确保其在计算机上与下载源相同。


3
这只是哈希的一种用途。还有许多其他用途。
Yuval Filmus

欢迎光临本站!接受的答案已经涵盖了使用加密哈希作为校验和,因此您的答案不会添加任何新内容,同时会占用大量屏幕空间。
David Richerby '18年

-1

我将尝试添加其他人的简短摘要。

哈希函数

有一种特殊的函数,称为哈希函数。

“ SHA256是众所周知的哈希函数,具有加密安全性”

三种主要应用是:*哈希表,*校验和(例如在硬盘驱动器或ADSL协议中的数据完整性检查),*和密码术(各种形式的密码认证,包括但不限于数字签名和安全密码存储)。

哈希表

哈希表是用于快速搜索的数据结构。它在内部使用哈希函数,因此使用名称。

“数据库在内部使用哈希表和搜索树来加快搜索请求的执行速度”

杂凑

  1. 字典抽象数据类型

“哈希”是Perl中内置词典的正式名称。它们在内部是哈希表,因此是名称。“此子例程接受哈希作为其第一个参数”。这些天可以用于任何关联数组,而不必用于哈希表。

  1. 对某些输入应用哈希函数的结果

“提供了.iso映像的MD5哈希值,以在下载后检查其完整性”。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.