Difference between Hashing a Password and Encrypting it
目前投票支持这个问题的最高领导人说:
Another one that's not so much a security issue, although it is security-related, is complete and abject failure to grok the difference between hashing a password and encrypting it. Most commonly found in code where the programmer is trying to provide unsafe"Remind me of my password" functionality.
这到底有什么区别?我一直觉得哈希是一种加密形式。海报所指的不安全功能是什么?
散列是一个单向函数(好吧,是一个映射)。它是不可逆的,您应用了安全哈希算法,并且不能返回原始字符串。您能做的最多的就是生成所谓的"冲突",也就是说,找到一个提供相同哈希的不同字符串。密码学上的安全散列算法是为了防止冲突的发生而设计的。您可以使用彩虹表攻击安全散列,您可以在存储散列之前将盐应用于散列来抵消此攻击。
加密是一种适当的(双向)功能。它是可逆的,如果你有密钥,你可以解密损坏的字符串得到原始字符串。
它所指的不安全功能是,如果加密密码,应用程序将密钥存储在某个地方,并且访问数据库(和/或代码)的攻击者可以通过获取密钥和加密文本来获取原始密码,而使用哈希则不可能。
人们通常说,如果一个破解者拥有你的数据库或代码,他不需要密码,所以区别是没有意义的。这是Na?ve,因为你仍然有责任保护你的用户的密码,主要是因为他们中的大多数一次又一次地使用相同的密码,通过泄露他们的密码使他们面临更大的风险。
散列是一个单向函数,这意味着一旦散列了一个密码,就很难从散列中获得原始密码。加密是一个双向函数,在这个函数中,从加密的文本中获取原始文本要容易得多。
普通散列很容易被字典攻击击败,攻击者只需预先散列字典中的每个单词(或长度不超过一定长度的每个字符组合),然后使用这个新字典查找散列密码。对存储的每个散列密码使用唯一的随机salt会使攻击者更难使用此方法。他们基本上需要为您使用的每一个salt值创建一个新的唯一字典,从而极大地降低它们的攻击速度。
使用加密算法存储密码是不安全的,因为如果用户或管理员更容易从加密文本中获取原始密码,攻击者也更容易做到这一点。
如上图所示,如果密码是加密的,那么它始终是一个隐藏的秘密,用户可以从中提取纯文本密码。但是,当对密码进行哈希处理时,您会感到轻松,因为几乎没有任何方法可以从哈希值中恢复密码。
从加密密码和哈希密码中提取-哪个更好?
加密好吗?纯文本密码可以使用对称加密算法(如DES、AES)或任何其他算法加密,并存储在数据库中。在认证时(用用户名和密码确认身份),应用程序将解密存储在数据库中的加密密码,并与用户提供的密码进行比较,以确保相等。在这种类型的密码处理方法中,即使有人访问数据库表,密码也不能简单地重用。然而,这种方法也有一个坏消息。如果有人以某种方式获得加密算法以及应用程序使用的密钥,他/她将能够通过解密查看存储在数据库中的所有用户密码。"这是我得到的最佳选择",软件开发人员可能会尖叫,但有更好的方法吗?
加密哈希函数(仅单向)是的,可能你错过了这一点。你注意到没有必要解密和比较吗?如果只有一种方法可以将密码转换为某个已转换的字,但无法进行反向操作(从已转换的字生成密码)。现在,即使有人可以访问数据库,也无法使用转换后的单词复制或提取密码。在这种方法中,几乎不会有人知道您的用户的绝密密码;这将保护在多个应用程序中使用相同密码的用户。这种方法可以使用什么算法?
我一直认为加密可以通过两种方式进行转换,一种是最终值可以将您转换为原始值,而通过散列,您将无法从最终结果还原为原始值。
哈希算法本质上通常是加密的,但主要的区别在于加密是通过解密可逆的,而哈希则不是。
加密函数通常接受输入并生成大小相同或稍大的加密输出。
散列函数接受输入并生成一个通常较小的输出,通常也是固定大小的。
虽然不可能获取哈希结果并"dehash"它以返回原始输入,但您通常可以将方法强制到产生相同哈希的对象。
换言之,如果一个身份验证方案获取一个密码,对其进行哈希处理,并将其与所需密码的哈希版本进行比较,则可能不需要您实际知道原始密码,而只需要它的哈希值,并且您可以以暴力的方式强制找到匹配的密码,即使它是不同的密码。
散列函数的创建通常是为了最小化发生冲突的可能性,并使得很难只计算将产生与其他东西相同散列的东西。
散列:
它是一种单向算法,一旦散列就不能回滚,这是它反对加密的最佳点。
加密
如果我们执行加密,将有一个密钥来执行此操作。如果这个密钥被泄露,你的所有密码都可以很容易地解密。
另一方面,即使您的数据库会被黑客攻击,或者您的服务器管理员从数据库中获取数据,并且您使用了哈希密码,黑客也无法破解这些哈希密码。如果我们使用适当的盐散列和pbkdf2额外的安全性,这实际上是不可能的。
如果您想了解如何编写散列函数,可以访问这里。
有许多算法可以执行散列。
MD5-使用消息摘要算法5(MD5)哈希函数。输出哈希的长度为128位。MD5算法是由RonRivest在20世纪90年代早期设计的,现在不是首选方案。
sha1-使用1995年发布的安全哈希算法(sha1)哈希。输出哈希长度为160位。虽然使用最广泛,但这在今天不是首选的选择。
hmacsha256、hmacsha384、hmacsha512-使用sha-2系列的功能sha-256、sha-384和sha-512。SHA-2于2001年出版。输出散列长度分别为256、384和512位,如散列函数的名称所示。
理想情况下,你应该两者兼顾。
首先散列单向安全的密码。用盐来增加安全性。
然后加密散列,以防密码散列数据库受到攻击。
与其他答案一样正确,在引用所在的上下文中,哈希是一种用于保护信息的工具,加密是一种获取信息的过程,使未经授权的人很难阅读/使用。
这里有一个原因,你可能想使用一个对另一个-密码检索。
如果您只存储用户密码的散列值,则不能提供"忘记密码"功能。