哈希密码和加密密码的区别

161
当前票数最高的针对这个问题的评论如下:

另一个不算安全问题,但与安全有关的是,完全不能理解散列密码和加密密码之间的区别。这种情况最常见于程序员试图提供不安全的“提醒我密码”的功能的代码中。

到底有什么区别?我一直以为哈希是加密的一种形式。那么发帖人所指的不安全功能是什么?


一篇关于为什么不应该简单地哈希您的密码/秘密,而是使用HMAC的好文章。http://benlog.com/articles/2008/06/19/dont-hash-secrets/ - Jay Kumar
StackExchange安全博客上这篇《为什么密码应该进行哈希处理》的文章总结得非常好。http://security.blogoverflow.com/2011/11/why-passwords-should-be-hashed/ - David J. Liszewski
@JayKumar:你提供的文章非常误导人。它混淆了密码盐(预期可被攻击者看到)和MAC密钥(预期保持秘密)。David J. Liszewski的链接提供了一个更准确的描述。 - Rufflewind
9个回答

246
哈希是一种单向函数(也就是一种映射)。它是不可逆的,你应用安全哈希算法后无法得到原始字符串。你最多只能生成所谓的“碰撞”,也就是找到一个提供相同哈希值的不同字符串。加密学上安全的哈希算法旨在防止碰撞的发生。你可以通过使用彩虹表攻击安全哈希,但你可以在存储哈希之前对其应用以抵消这种攻击。
加密是一种适当的(双向)函数。它是可逆的,如果你有密钥,你可以解密被篡改的字符串以获得原始字符串。
它所指的不安全功能是,如果你加密密码,你的应用程序会在某处存储密钥,而攻击者如果获取了你的数据库(和/或代码),则可以通过获取密钥和加密文本来获取原始密码,而哈希则不可能。
人们通常说,如果黑客拥有你的数据库或代码,他不需要密码,因此区别无关紧要。这是幼稚的想法,因为你仍然有责任保护用户的密码,主要是因为他们中的大多数人一遍又一遍地使用相同的密码,泄露他们的密码会使他们面临更大的风险。

1
为了清楚起见,要使用哈希获取所需的安全性,它必须是具有特定属性的密码学安全哈希算法,不仅哈希是不可逆的,而且计算上不可行生成任何其他生成相同哈希的字符串。 - Tall Jeff
12
是与否... 为了您应用程序的安全性,哈希碰撞需要难以生成,但非可逆性足以避免密码泄露。 - Dave Sherohman
5
丝滑:你将如何从那个糟糕的哈希函数中恢复原始密码?我建议你重新阅读戴夫的评论。 - Vinko Vrsalovic
1
如果说有什么的话,一个具有大量冲突的哈希函数对于密码的安全性更好,但这显然意味着可以使用更多的密码登录到该账户。 - williamvicary
1
@n00b,salt不能硬编码,因为每个散列项都应该使用单独的盐值。盐值的作用在于,如果UserA和UserB都使用密码“1234”,如果你发现了UserA的密码,你不能告诉UserB使用了相同的密码,因为他们有不同的盐值。保密盐值并不是安全关键,大多数实现只是将盐值连接到表示哈希的二进制块的前面或后面。 - Scott Chamberlain
显示剩余8条评论

38

哈希是一种单向函数,这意味着一旦您对密码进行哈希处理,从哈希值中恢复原始密码非常难。加密是一种双向函数,其中从加密文本中恢复原始文本要容易得多。

普通哈希易被字典攻击破解,攻击者只需预先将字典中的每个单词(或每个长度组合)进行哈希处理,然后使用此新字典查找哈希密码。对于每个存储的哈希密码使用唯一的随机盐,可以使攻击者很难使用此方法。他们基本上需要为您使用的每个盐值创建一个新的唯一字典,这会极大地减缓他们的攻击速度。

使用加密算法存储密码是不安全的,因为如果用户或管理员可以轻松地从加密文本中获取原始密码,则攻击者也可以轻松地执行相同的操作。


14

加密和哈希密码

如上图所示,如果密码被加密,那么明文密码会一直是一个隐藏的秘密,没有人能够提取出来。然而当密码被哈希时,你就可以放心了,因为几乎没有方法可以从哈希值中恢复出密码。


选自 加密和哈希密码 - 哪个更好?

加密有好处吗?

明文密码可以使用对称加密算法(如DES、AES或其他算法)进行加密,并存储在数据库中。 在身份验证(通过用户名和密码确认身份)时,应用程序将解密存储在数据库中的加密密码,并将其与用户提供的密码进行比较以判断是否相等。 在这种类型的密码处理方法中,即使某些人可以访问数据库表,也无法简单地重复使用密码。 但是,这种方法也有坏消息。 如果某种方式获取了您的应用程序使用的密码密钥及其加密算法,则他/她将能够通过解密查看存储在您的数据库中的所有用户密码。 "这是我得到的最好选项",软件开发人员可能会大声呼喊,但是有没有更好的方法?

加密哈希函数(单向转换)

是的,有一个方法,也许您已经错过了重点。 您是否注意到根本不需要解密和比较? 如果有一种单向转换方法,可以将密码转换为某个转换后的字,并且不可能反向操作(从转换后的字生成密码)。 现在,即使有人访问数据库,也无法通过转换后的字还原或提取密码。 在此方法中,几乎没有任何方式可以知道您用户的机密密码;这将保护使用相同密码跨多个应用程序的用户。 什么算法可以用于这种方法?


1
好的,但是当您登录服务时,您的密码是以明文/加密形式发送的,因为如果将其作为哈希值发送到服务器进行比较,黑客可以只需将哈希值发送到服务器即可登录。这就是为什么需要将用于比较的密码加密发送到服务器,然后在那里进行解密和哈希处理。这样安全吗?只要密码不以未经哈希处理的形式长期存储,并且在不再需要时从任何内存中删除所有加密/明文密码的出现即可。 - AgentM

8

我一直认为加密可以双向转换,以便最终值可以带您回到原始值,而哈希则无法从最终结果还原到原始值。


8
哈希算法通常具有加密性质,但主要区别在于加密可以通过解密进行反转,而哈希则不行。
加密函数通常需要输入并产生相同或稍大的输出。
哈希函数需要输入并产生通常更小的输出,通常也是固定大小的。
虽然无法将哈希结果“去哈希”以获取原始输入,但您通常可以用穷举法找到一个产生相同哈希值的输入。
换句话说,如果身份验证方案采用密码,对其进行哈希处理,并将其与所需密码的哈希版本进行比较,则可能不需要实际知道原始密码,只需要知道其哈希值,并且即使是不同的密码,您也可以用穷举法找到一个匹配的密码。
哈希函数通常被创建为最小化碰撞机会,并使计算出与其他内容相同哈希值的东西变得困难。

6

散列

它是一种单向算法,一旦散列就无法回滚,这是它与加密的优点所在。

加密

如果我们执行加密,将需要一个密钥。如果此密钥泄漏,则所有密码都可以轻松解密。

另一方面,即使您的数据库被黑客攻击或服务器管理员从数据库中取出数据并使用了散列密码,黑客也无法破解这些散列密码。如果我们使用适当的盐和PBKDF2进行散列,并提供额外的安全保护,那么这实际上几乎不可能。

如果您想查看如何编写哈希函数,可以访问此处

有许多算法可用于执行散列。

  1. MD5 - 使用消息摘要算法 5 (MD5) 哈希函数。输出哈希长度为 128 位。MD5 算法由 Ron Rivest 在 1990 年代初设计,今天已不再是首选选项。

  2. SHA1 - 使用于 1995 年发布的安全散列算法 (SHA1) 哈希。输出哈希长度为 160 位。虽然最广泛使用,但今天已不再是首选选项。

  3. HMACSHA256HMACSHA384HMACSHA512 - 使用 SHA-2 家族的函数 SHA-256、SHA-384 和 SHA-512。SHA-2 发布于 2001 年。哈希函数名称表示的输出哈希长度分别为 256、384 和 512 位。


5

理想情况下,您应该同时执行两个操作。

首先对密码进行哈希处理,以进行单向安全保护。使用盐巴来增加安全性。

然后对哈希值进行加密,以防止字典攻击,如果您的密码哈希数据库被攻破。


3
用什么加密它?如果黑客攻击得如此彻底,以至于他们进入了存储所有用户密码(哈希、加密或其他方式)的数据库,那么他们不就能够找到解密它们所需的密钥吗? - Luc
6
这条评论不应该被踩。其中提出了一个可能性,不能轻易排除数据库受到攻击而应用程序没有受到影响。因此,加密哈希值是一种额外的安全层。 - Arie
2
@Luc 我不同意你之前的观点。我见过太多未妥善处理的 SQL 注入攻击,并没有危及应用程序代码(或配置文件)。因此,我现在认为添加一个密钥是有帮助的,可以采用加密或者 pepper 的形式,但这绝不能取代哈希。更详细的答案请参考这里:https://security.stackexchange.com/a/31846/10863 - Luc

1

尽管其他答案可能是正确的,但在引用所在的上下文中,哈希是一种可用于保护信息的工具,加密是将信息进行处理,使得未经授权的人难以阅读或使用。


-10

以下是你可能想使用其中一种的原因 - 密码找回。

如果你只存储用户密码的哈希值,那么你无法提供“忘记密码”功能。


18
你显然没有仔细阅读接受的答案。认真阅读:你不应该提供密码“找回”功能,而应该提供密码“重置”功能。我多年来一直管理许多网站,包括vBulletin、phpBB、e107、IPB、blogspot和甚至是我自己定制的CMS。作为管理员,你永远不需要拥有别人的预先散列密码。你只是不需要。你也不应该拥有它。如果你不同意我的观点,请让我向你保证:你是错误的。 - Lakey
3
抱歉因为太生气了而发脾气。我看到太多网站直接以明文方式存储密码,这让我感到沮丧。顺便提一下:一些注重安全的网站喜欢让用户定期更换密码。他们想确保人们不会将密码从“Password1”更改为“Password2”。因此,他们要保留明文密码,以便在以后进行比较。这不是好的做法。在这种情况下,他们需要先对密码进行分析,制作一堆类似的密码--对每个密码进行哈希--然后只存储哈希值。 - Lakey
7
没问题,这让我回去重新阅读了问题并进行了进一步的研究,所以一切都不算浪费时间 :-) 当时写那个答案的时候,我不确定自己在想什么。谢谢! - Philtron

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