据我所知,基本问题是散列的缺陷是密码在散列中。非对称加密的缺陷是密码被加密并且可以被反转。
我看到的帖子说不使用非对称加密并使用更好的哈希算法(bcrypt/scrypt/etc)来“安全”。
相反,如果您使用非对称加密(例如 Rijndael/AES)并使用用户提供的密码(可以散列以获得更好的值)加密每个用户唯一的已知明文值并存储结果会怎样。
那么这不会提供一个可以存储的加密字符串来保护用户的密码不被恢复吗?还是有一些我遗漏/忽略的固有缺陷?
据我所知,基本问题是散列的缺陷是密码在散列中。非对称加密的缺陷是密码被加密并且可以被反转。
我看到的帖子说不使用非对称加密并使用更好的哈希算法(bcrypt/scrypt/etc)来“安全”。
相反,如果您使用非对称加密(例如 Rijndael/AES)并使用用户提供的密码(可以散列以获得更好的值)加密每个用户唯一的已知明文值并存储结果会怎样。
那么这不会提供一个可以存储的加密字符串来保护用户的密码不被恢复吗?还是有一些我遗漏/忽略的固有缺陷?
我看不出你在解决什么问题。想象一下,如果您的数据库遭到入侵,将会发生什么。攻击者将拥有此加密字符串、盐和(可能)加密密钥。
是什么让他们无法解密任何用户的盐或密码并获得密码?
很难发明出比专业人士开发的算法更安全的东西,并且已经“实战”多年(即 bcrypt)。
目前最好的解决方案之一是在散列算法中添加盐+ 胡椒(不是 md5,也不是 sha1,因为据报道它们已损坏。有关其状态的更多信息,请单击此处获取 md5和此处获取 sha1。此外,StackOverflow 上的这个答案完成了我的话)。
此外,如果您使用BCrypt作为您的散列算法,则会为可能的攻击者增加一定程度的复杂性,因为破解的时间会随着时间的推移而降低:
“bcrypt 是一种自适应哈希:随着时间的推移,它可以变得越来越慢,因此它仍然能够抵抗针对哈希和盐的特定暴力搜索攻击。”
您描述的解决方案实际上是散列。
考虑哈希函数MD5。它从长度为 128 位的传统固定值(“IV”)开始工作。然后,对于每个 512 位输入数据块,计算一个压缩函数,将当前 128 位状态和 512 位消息块作为输入,并输出下一个 128 位状态。如果您查看 MD5 压缩功能的工作原理,您会发现它类似于使用 512 位消息块作为密钥的分组密码(具有四个子字的广义Feistel 方案)。所以MD5真的像你描述的那样运行:加密一个固定的值,以密码为密钥。如果固定值是用户特定的,那么它就是一种“盐”(这对密码散列很有用)。
所以你的问题是:我们不能用分组密码构建一个散列函数吗?答案是:是的,但需要一些小心。典型的分组密码(例如AES)是为加密而设计的,并且已在该上下文中分析了其安全性。当您将块密码转换为如上所述的哈希函数时,您依赖于块密码以尚未彻底探索的方式鲁棒 - 您需要密码能够抵抗相关密钥攻击,这是非-就加密而言的问题,但对于散列函数可能是致命的。例如,众所周知,AES 在相关密钥方面有些弱,因此在散列函数中“按原样”使用它不一定是一个好主意。
Whirlpool和Skein是两个重用分组密码的哈希函数——在这两种情况下,都是专门的分组密码,针对特定情况下的阻力进行了优化。
不管哈希函数设计的细节如何,任何密码存储系统都有一个很大的明显弱点,那就是它存储密码,或者至少是密码验证令牌(可以用来确定给定密码是否正确的东西)或不)。密码来自人类的大脑;他们不可能强大。枚举大多数潜在密码是很有可能的。
验证密码的服务器不可避免地包含足够的信息来验证密码。因此,如果攻击者可以获得服务器磁盘的转储,那么他也获得了这种权力,并且可以“在家”尝试密码。这是离线字典攻击。唯一已知的防御(可以说,唯一可能的防御)是使每个密码验证固有地变慢,最好以可配置的方式。这就是bcrypt 的重点:密码散列使用数百万个基本操作,没有任何已知的捷径,因此攻击者每次尝试都必须付出高昂的代价。
从分组密码构建的自制散列函数将失败——除非您将其定义为不使用一种加密,而是使用一百万次连续加密。它仍然是自制的(这在密码学中非常糟糕;不要相信自制的设计),但至少它在字典攻击方面不会那么弱。
散列主要用于保护 Web 应用程序的数据库。使用它们是因为它们速度快!一般来说,加密并不快。
因此,如果您编写 Web 应用程序,则需要哈希而不是加密!如果您正在创建类似密码管理器的东西,您可以使用像 AES 这样的强对称加密算法!
如果您需要更多解释或任何其他帮助,请随时发表评论!!!