不,不可能反转诸如 MD5 之类的散列函数:给定输出散列值,除非知道有关输入消息的足够信息,否则不可能找到输入消息。
解密不是为散列函数定义的函数;加密和解密是 cipher 的函数,例如 CBC 模式下的 AES;散列函数既不加密也不解密。 哈希函数用于消化输入消息。顾名思义,没有可能的反向算法设计。
MD5 被设计为一种加密安全的单向散列函数。现在很容易为 MD5 生成冲突 - 即使输入消息的大部分是预先确定的。因此 MD5 被正式破解,MD5 不应再被视为加密安全哈希。然而,仍然不可能找到导致哈希值的输入消息:当仅知道 H(X) 时找到 X(并且 X 没有具有至少一个 128 字节的预计算数据块的预计算结构) . 没有针对 MD5 的已知原像攻击。
通常还可以使用暴力破解或(增强的)字典攻击来猜测密码,比较数据库或尝试在所谓的彩虹表中查找密码哈希。如果找到匹配项,则在计算上可以确定输入已找到。散列函数对碰撞攻击也是安全的:找到X' 使得H(X') = H(X) 给定H(X)。因此,如果找到X,则在计算上可以确定它确实是输入消息。否则你毕竟会执行碰撞攻击。彩虹表可用于加速攻击,并且有专门的互联网资源可以帮助您找到给定特定哈希的密码。
当然可以重新使用哈希值H(X) 来验证在其他系统上生成的密码。接收系统唯一需要做的就是存储确定性函数F 的结果,该函数将H(X) 作为输入。当X 提供给系统时,H(X) 和F 可以重新计算并比较结果。换句话说,不需要将哈希值解密以仅验证密码是否正确,您仍然可以将哈希值存储为不同的值。 p>
使用 密码哈希 或 PBKDF(基于密码的密钥派生函数)代替 MD5 很重要。这样的函数指定如何将 salt 与哈希一起使用。这样就不会为相同的密码(来自其他用户或其他数据库)生成相同的哈希值。出于这个原因,密码哈希也不允许使用彩虹表,只要盐足够大并且适当地随机化。
密码哈希还包含一个工作因素(有时使用迭代计数进行配置),可以显着减慢尝试在给定盐和哈希值的情况下查找密码的攻击.这很重要,因为带有盐和哈希值的数据库可能会被盗。最后,密码哈希也可能是memory-hard,因此需要大量内存来计算哈希。这使得攻击者无法使用特殊硬件(GPU、ASIC、FPGA 等)来加快搜索速度。其他输入或配置选项(例如辣椒或并行化量)也可用于密码哈希。
然而,即使H(X) 是密码哈希,它仍然允许任何人验证给定H(X) 的密码。密码哈希仍然是确定性的,所以如果有人知道所有输入和哈希算法本身,那么 X 可以用来计算 H(X) 并且 - 再次 - 可以比较结果。
常用的密码哈希是 bcrypt、scrypt 和 PBKDF2。还有各种形式的 Argon2,它是近期密码哈希竞赛的获胜者。 Here on CrackStation 是一篇关于密码安全的好博文。
有可能使攻击者无法执行哈希计算来验证密码是否正确。为此,胡椒可以用作密码哈希的输入。或者,哈希值当然可以使用诸如 AES 的密码和诸如 CBC 或 GCM 的操作模式进行加密。然而,这需要存储一个秘密/密钥独立并且具有比密码哈希更高的访问要求。