确定性哈希函数能够容易地被解密吗?

7
可能的重复问题: 是否可以解密MD5哈希值? 是否可以反向SHA1? 我提出了这个问题:如何处理大型电子表格,得到了很好的答案并且按照建议进行了操作。我使用了这个链接:http://splinter.com.au/blog/?p=86,在Excel电子表格中对一列中的约300,000个不同元素进行了哈希。
=SHA1HASH('The quick brown fox jumps over the lazy dog')

然后你会得到:

2fd4e1c67a2d28fced849ee1bb76e7391b93eb12

你不能向后退吗?

我的意思是,如果它每次都以相同的方式加密相同的文本,那还有什么意义呢?

如果你知道哈希算法,是否可能向后推导?

请简单地解释一下哈希是如何工作的?如何将20GB转换为40个字符的哈希值?对20GB硬盘进行哈希需要很长时间吗?


5
这个问题更好的标题应该是“哈希值能轻松解密吗?” - matt b
1
谁告诉你可以倒退? - kennytm
3
你尝试过往回走吗?你找到了一个实际上确实能够往回走的函数吗? - S.Lott
3
你能否逆转熵? - herzmeister
1
对于简单哈希,其思想是将非常广泛的值范围映射到一些具有良好分布的小量上。对于加密哈希,其思想是使查找哈希值的命中值变得困难。 - ony
显示剩余7条评论
11个回答

24

通用回答

密码哈希函数是不能轻易被反向的。因此有时也称之为单向函数。没有回头路。

你也应该小心地使用“解密”这个词。哈希函数不同于加密。可能的哈希值集合通常比可能的输入集合小,所以多个输入映射到相同的输出。

对于任何哈希函数,给定输出,你无法知道用于生成此特定输出的众多输入中的哪一个。

对于像SHA1这样的密码哈希函数,甚至很难找到一个产生该输出的输入。

反转密码哈希的最简单方法是猜测输入并进行哈希操作,以查看是否产生了正确的输出。如果你猜错了,就再猜一次。另一种方法是使用彩虹表

关于使用哈希来加密社会安全号码(SSN)

考虑到SSNs的可能输入值数量相对较小,攻击是可能的。如果你担心人们能够获取SSNs,那么最好不要在你的应用程序中存储或使用SSN,尤其不要将它们用作标识符。相反,你可以找到或创建另一个标识符,例如电子邮件地址、登录名、GUID或仅仅是递增的数字。使用SSN可能很诱人,因为它已经存在,并且乍一看似乎是一个唯一且不变的标识符,但实际上使用它只会引起问题。如果你绝对需要存储它,那么请使用强大的非确定性加密与秘密密钥,并确保你保存了该密钥。


4
不可能通过哈希算法实现。 - blockhead
2
+1,一旦你用黑色,就再也回不去了。 - VoodooChild
2
@Zak 这是在假设你知道这里的目标是社会安全号码。 - blockhead
1
@user 彩虹表在SO答案中进行完整教程有些复杂(但是互联网上有很多关于它们的信息,所以可以搜索)。一般的想法是你预先计算出大量候选明文的哈希值,然后使用巧妙的方法进行反向查找,找到对应于给定哈希值的明文。然而,这种技术很容易被“加盐”明文(在哈希之前以独特但确定性的方式修改每个明文)所击败。 - Tyler McHenry
1
@user29823498750932874509823745:如果你创建一个函数将社会安全号码映射到唯一值,使得任何人知道这个函数后都可以调用它并查看在你的数据库中存在哪些价值。我能想到的只有两种方法来防止别人这样做:a)防止他人知道该函数。但如果你需要将函数包含在Excel文件中,则无法实现此目标。b)让你的函数变得非常缓慢,以至于暴力破解不可行。请参见“密钥强化”:en.wikipedia.org/wiki/Key_strengthening。两种选项都不理想... - Mark Byers
显示剩余9条评论

18
密码学哈希的整个目的在于您无法解密它,同时每次加密方式都是相同的。密码验证是密码学哈希的一个非常常见的用例。假设我有密码“mypass123”,散列值为"aef8976ea17371bbcd"。那么想要验证我的密码的程序或网站可以将散列值"aef8976ea17371bbcd"存储在其数据库中,而不是存储密码。每次我想登录时,该网站或程序会重新对我的密码进行哈希,并确保哈希值匹配。这使得网站或程序避免存储我的实际密码,从而保护我的密码(以防我在其他地方使用),以防数据被窃取或以其他方式受到损害 - 黑客将无法从哈希到密码。
密码学哈希的另一个常见用途是完整性检查。假设某个文件(例如Linux发行版CD的映像)具有已知的公开可用的密码学哈希值。如果您有一个声称与此相同的文件,则可以自行进行哈希处理并查看哈希值是否匹配。在这里,它每次哈希值都相同的事实使您能够独立验证它,而且它是密码学安全的意味着没有人可以实际上创建具有相同哈希值的不同伪造文件(例如,其中包含木马)。
但是请记住哈希和加密之间非常重要的区别:哈希会丢失信息。这就是为什么您无法回退(解密)到哈希值的原因。您可以对20 GiB的文件进行哈希处理,并最终获得40多个字符的哈希值。显然,在此过程中,已经丢失了很多信息。您如何可能将40多个字符“解密”成20 GiB?没有压缩可以实现这么好的效果!但是这也是一个优点,因为为了检查20 GiB文件的完整性,您只需要分发40多个字符的哈希值。

由于信息缺失,许多文件将具有相同的哈希值,但是加密哈希(这就是你所谈论的内容)的关键特征是,尽管信息丢失了,但从一个文件开始构造出一个略微不同的第二个文件,其哈希值相同是计算上不可行的。任何具有相同哈希值的其他文件都将大相径庭,并且不容易与原始文件混淆。


这是一个很好的答案!谢谢。如果您知道哈希算法,是否可能反向操作? - Alex Gordon
不,你不能倒退,这就是重点。原因是哈希会丢失信息。我已经将其编辑到我的答案中了。 - Tyler McHenry
1
“哈希会丢失信息”,所以你无法回溯! - FrustratedWithFormsDesigner
@user29823498750932874509823745- 你不能“倒退”,即反转数学公式,应用哈希函数并重新生成原始输入。但是,你可以创建一个包含所有可能输入的表格,运行它们通过哈希函数,并将输入+哈希结果存储在表格中。使用此表格来反向查找可能生成此输出的输入。正如Tyler所提到的,几个不同的输入将给你相同的输出。即使你有时间/存储来生成这样的表格,你仍然有许多可能的输入可供选择。 - bta
2
用户的目标是社会安全号码。在这里,每个人都应该提醒他对哈希进行加盐处理。 - Zak

10
我理解你的意思是,你试图隐藏社会安全号码,但担心SHA1HASH加密算法被人轻易解密。因为如果有人知道你使用SHA1HASH算法来创建唯一标识符,他们可以快速生成所有SSN号码的列表,并进行SHA1HASH运算,然后与记录中的ID进行比较,从而轻松获取用户的SSN。更糟糕的是,他们可以预先生成一个包含所有SSN号码的哈希查找表,并为每个SSN分配一个哈希函数,这就是哈希查找表,而复杂的形式则称为彩虹表。
所以这就是为什么哈希算法发明了第二个功能-盐(salting)。盐基本上是这样做的:你创建一个盐,然后使用盐修改数据。例如,假设你有一个SSN 123-45-6789 ,你可以用字符串“MOONBEAM”对其进行盐处理。生成的新字符串用于哈希运算的是“123-45-6789MOONBEAM”。
现在,即使有人知道你正在使用哈希算法来生成唯一标识符,他们也不知道你将使用哪种盐,因此无法通过预先对所有SSN进行哈希运算并与你的ID进行比较来获取原始的SSN。但是,你可以始终采用用户的SSN,使用盐,并重新对SSN +盐进行哈希运算,以查看用户SSN是否与其ID匹配。
最后,如果你为所有内容只使用一个盐并将其保密,而不是让别人看到盐并通过运行SSN自增 +盐100万次来找到匹配项,他们必须付出更多努力才能检索SSN。这是因为100万个SSN号码的熵相对较低(10^9种组合)。通过添加盐并将其保密,而不仅仅是运行预定义的函数,可以增加安全性。
SHA1HASH(111-11-1111) -> check hash match
SHA1HASH(111-11-1112) -> check hash match
SHA1HASH(111-11-1113) -> check hash match

他们将不得不运行

SHA1HASH(111-11-1111a) -> check hash match
SHA1HASH(111-11-1111b) -> check hash match
SHA1HASH(111-11-1111c) -> check hash match
...
SHA1HASH(111-11-1111azdfg) -> check hash match
SHA1HASH(111-11-1111azdfh) -> check hash match
....
SHA1HASH(111-11-1111zzzzzzzzzzzzzzzz) -> check hash match
SHA1HASH(111-11-1112a) -> check hash match
SHA1HASH(111-11-1112b) -> check hash match

......直到最终到达目的地

SHA1HASH(123-45-6789MOONBEAM) -> check hash match

最终他们成功破解了SSN和SALT。

他们甚至不知道你的SALT有多少个字符,这意味着为了获取一个SSN,他们需要做10^(你的salt字符数)倍的工作量,更别说获取整个表了。

更新: 许多年后,当我回答这个问题时,我发现自己对盐值加密的信息是错误的。请在下面的帖子和评论中查看正确的信息,关于每个条目使用唯一的盐值,因为这仍然是主题串中的第一个帖子。如果您认为我应该在阅读此内容后更改OP,请在下面留言(或点赞),如果达成共识,我将进行更正。


7
盐并不是秘密! 盐应该附加到哈希值上,并用于防止字典攻击的预计算。你所指的更像是HMAC-在这种情况下,你应该使用适当的HMAC而不是这个临时方案。 - Nick Johnson
5
对存储H(SSN || salt)的潜在攻击:如果攻击者将自己(或其他人,或虚构的SSN)注册到系统中,他们可能可以找到与其注册和其SSN哈希相关的行。由于他们已经知道自己的SSN,因此可以使用此信息来暴力破解盐(MOONBEAM)。一旦他们知道盐,就可以相对容易地获取其他SSN。 - Mark Byers
4
@Zak 一个秘密盐只是一个实现不好的HMAC。盐始终与哈希值一起存储。 @Mark 如果正确使用,盐会为每个存储的值随机生成 - 一个条目的盐与另一个条目的盐没有任何关系。 - Nick Johnson
1
@Nick Johnson:除非你说的是传统上使用的非机密盐,否则我们正在谈论两个完全不同的事情...也许我没有表达清楚?我在回答中特别是针对这部分内容:“他们仍然不知道您将要使用的盐”。在我看来,这个答案是有缺陷的,我正在展示对它的攻击。如果你想提出一个不同的方案,我建议你把它作为一个单独的答案发布,这样我就可以在那里评论你的方案,而不是在这里,这样两个不同的方案就不会混淆了。 - Mark Byers
1
如果仅为每个用户存储一个无意义标识符就足够的话,我怀疑OP在第一时间会询问如何对SSN进行哈希。假定他们必须存储SSN的哈希值,那么显然有充分的理由。正如我已经说过的,“秘密盐”并不是盐,而是一个实现不良的HMAC算法。关于知道盐的问题 - 盐变成了散列值的一部分 - HASH(value + salt) + salt。这是非常基本的加密知识。 - Nick Johnson
显示剩余8条评论

7
不,你不能回溯,因为哈希函数没有保留足够的信息。可以把哈希函数想象成将原始文本映射到一个单独的巨大数字。这个数字也可能映射到其他文本,尽管一个好的哈希函数会有很少的冲突。如果原始消息被加密了,那么是可以回溯的。

5

加密和哈希是两个不同的概念。

哈希只是将字符串转换为数字。加密则保留了字符串的内容,以便以后可以解密。无法从哈希值中获取原始字符串,因为其中的内容已经丢失。


除非您已经获得了与哈希匹配的所有字符串,然后浏览它们。 - vlad-ardelean
1
我不擅长数学,但那不是无限字符串吗? - BC.

3

不行。哈希的作用在于它是单向加密(正如其他人所指出的,它并不是真正的“加密”,但请跟我一起理解)。缺点在于,理论上有可能发生“碰撞”,即两个或多个字符串返回相同的哈希值。但通常这个缺点是值得的。


2
一个好的哈希是单向的,也就是说你不应该能够逆向操作。它的目的是提供一个字符串的密钥而不暴露这个字符串。例如,这是一种很好的匹配密码的方法,因为它允许你在不存储密码的情况下进行比较。相反,你可以存储哈希值并且比较输入的结果哈希值。

如果您知道哈希算法,是否可能进行反向操作? - Alex Gordon
可能吧,但许多算法都被设计成非常困难。一些算法会为不同的输入生成相同的哈希值,而且许多(如果不是全部)算法都依赖于输入的长度。你需要对被哈希的数据有很深入的了解才能还原它。 - NG.
1
这是“普通”哈希函数(如Python映射或java.util.HashMap中使用的)和加密哈希函数(如SHA1)之间的区别。普通哈希函数主要针对输入位的扩散(覆盖哈希输出的整个范围)和效率进行优化。加密哈希还添加了不可逆约束,效率作为二级约束。 - Paul Rubel

2

不行,至少不是很容易。

SHA1仍被认为是密码学上安全的。一个哈希算法是安全的,如果它可以容易地进行单向计算,但通过穷举搜索进行另一方向的计算却非常困难。确实,每次加密特定短语时,它将产生相同的哈希值,但有无限数量的短语也会散列到该相同的值。安全性来自于在运行它们全部通过SHA1函数之前,不知道那些其他短语是什么。


2
不,你不能回去了。数一下你可以有多少个不同的哈希值。现在数一下你可以有多少个不同的字符串。前者是有限的,后者是无限的。有许多(确切地说是无限多个)字符串具有相同的SHA1值。然而,重点是很难找到两个文本具有相同的哈希值。
您可以将哈希视为缩短某些内容。例如,使用一个将字符串中所有字母的ASCII代码之和作为哈希函数。只知道字母的ASCII代码之和,就无法确定哈希之前的内容。SHA1也类似,但更复杂。
哈希的重点不是加密内容。哈希的重点是缩短内容,以便检查两个内容是否相同需要更少的时间。那么,如果您知道许多内容具有相同的哈希值,如何确定两个内容确实相同呢?好吧,您无法确定。您只是假设这是如此罕见,以至于不会发生。
但是,哈希不仅仅是用于检查,因为使用哈希检查相等性通常仅用于确认/验证,并且它不是确定性的。如果您看到哈希值相同,则可以根据特定哈希函数的参数估计被哈希对象确实相同的概率。
这就是为什么哈希函数总是为相同的对象产生相同结果是哈希函数最重要的特征。它使您能够验证和比较对象。

1

加密相同的文本以相同的方式是哈希的全部意义。这是一个特性。

如果我有一个密码哈希数据库,那么我可以通过对其进行哈希并查看哈希是否与我为您保存在数据库中的哈希匹配来检查您输入的正确密码。但是,如果有人窃取了我的哈希数据库,除非他们偶然发现一些明文散列到该值,否则他们将无法找出您的密码。


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