最近我在某处读到,虽然 CRC32 和 MD5 都足够统一和稳定,但 CRC32 比 MD5 更有效。MD5 似乎是一种非常常用的散列算法,但如果 CRC32 更快/内存效率更高,那么为什么不使用它呢?
10 回答
MD5是一种单向哈希算法。单向哈希算法通常用于密码学,因为它们具有(按设计)很难找到产生特定哈希值的输入的特性。具体来说,很难做出两个不同的输入来提供相同的单向哈希。那些它们通常被用作一种方式来表明自产生哈希码以来没有故意更改大量数据。由于 MD5 是一种单向哈希算法,因此重点在于安全性而非速度。不幸的是,MD5 现在被认为是不安全的。
CRC32旨在检测数据的意外更改,通常用于网络和存储设备。该算法的目的不是防止故意更改,而是捕捉网络错误和磁盘写入错误等事故。该算法的重点是速度而不是安全性。
来自维基百科关于 MD5 的文章(强调我的):
MD5 是一种广泛使用的加密哈希函数
现在CRC32:
CRC 是一种错误检测码
因此,如您所见,CRC32不是散列算法。这意味着您不应该将它用于散列,因为它不是为此而构建的。
而且我认为谈论通用用途没有多大意义,因为相似的算法用于不同的目的,每种都有明显不同的要求。没有最适合常用的单一算法,相反,您应该选择最适合您的特定用途的算法。
这取决于你的目标。以下是使用 CRC32 与 MD5 可以完成的一些示例:
检测重复文件
如果你想检查两个文件是否相同,CRC32 校验和是要走的路,因为它比 MD5 快。但要小心:CRC 只能可靠地告诉您二进制文件是否不同;它不会告诉你它们是否相同。如果两个文件的哈希值不同,它们就不可能是同一个文件,因此您可以很快将它们拒绝为重复文件。
无论您的密钥是什么,CRC32 校验和都将是 2^32 个不同值之一。假设随机样本文件,两个给定文件的哈希值发生冲突的概率为 1 / 2^32。N 个给定文件之间发生冲突的概率为 (N - 1) / 2^32。
检测恶意软件
如果安全是一个问题,例如下载文件并检查源的哈希值以查看二进制文件是否未损坏,那么 CRC 是一个糟糕的选择。这是因为攻击者可以制作具有相同 CRC 校验和的恶意软件。在这种情况下,MD5 摘要更安全——CRC 不是出于安全考虑。与相同的 MD5 摘要相比,两个不同的二进制文件更有可能具有相同的 CRC 校验和。
保护用户身份验证的密码
同步(单向)加密通常比异步(双向)加密更容易、更快、更安全,因此它是存储密码的常用方法。基本上,密码将与其他数据(盐)组合,然后将对所有这些组合数据进行哈希处理。随机盐大大减少了两个密码相同的机会。默认情况下,对于大多数算法,相同的密码将具有相同的哈希值,因此您必须添加自己的随机性。当然,盐必须在外部保存。
要让用户登录,您只需获取他们在登录时提供的信息。您可以使用他们的用户名从数据库中获取他们的 salt。然后将这个盐与用户密码结合起来,得到一个新的哈希值。如果它与数据库中的匹配,则他们的登录成功。由于您要存储这些密码,因此它们必须非常安全,这意味着 CRC 校验和是不可能的。
加密摘要的计算成本比 CRC 校验和高。此外,像 sha256 这样更好的散列更安全,但散列速度较慢并占用更多数据库空间(它们的散列更长)。
CRC32 和 MD5 之间的一个很大区别是,通常很容易选择一个 CRC32 校验和,然后提出一个哈希到该校验和的消息,即使对消息施加了限制,而 MD5 专门设计用于进行这种排序困难的事情(尽管它正在显示它的年龄 - 现在在某些情况下这是可能的)。
如果您处于这样一种情况,对手可能会决定坐下来创建具有指定 CRC32 哈希值的消息负载,以模仿其他消息,或者只是使哈希表性能非常糟糕,因为所有内容的哈希值都相同值,那么 MD5 将是一个更好的选择。(更好的是,恕我直言,HMAC-MD5 的键值对于使用它的模块来说是唯一的,并且在它之外是未知的)。
CRC 用于防止随机错误,例如在数据传输中。
加密哈希函数旨在防止智能对手伪造消息,尽管 MD5 在这方面已被破坏。
您应该使用 128 位长的 MD5。CRC32 只有 32 位长,其目的是检测错误而不是散列。如果您只需要 32 位哈希函数,您可以选择 MD5 返回的 32 位 LSB/MSB/Whatever。
CRC32(或 CRC8 或 CRC16)用于任何目的的主要原因是它可以廉价地在硬件中实现,作为检测“随机”数据损坏的一种手段。即使在软件实现中,它也可用作检测硬件原因(例如嘈杂的通信线路或不可靠的闪存介质)导致的数据随机损坏的一种方法。它不是防篡改的,通常也不适合测试两个任意文件是否可能相同:如果文件中的每个数据块紧跟该块的 CRC32(某些数据格式会这样做),则每个块对整个文件的 CRC 的影响与全零字节块的效果相同,无论该块中存储了什么数据。
如果有办法快速计算 CRC32,则与其他校验和或散列方法结合使用可能会有所帮助,如果具有相同 CRC 的不同文件可能在其他散列之一中不同,反之亦然,但在许多机器上相对于它们提供的保护量,其他校验和或哈希方法可能更容易计算。
实际上,CRC32并不比 MD5 快。
该 php 脚本运行几个散列算法并测量每个算法计算散列所花费的时间。它表明 MD5 通常是最快的散列算法。而且,它表明在大多数测试用例中,即使是 SHA1 也比 MD5 快。
所以,无论如何,如果你想做一些快速的错误检测,或者寻找随机变化......我总是建议使用 MD5,因为它只是做这一切。
一个人的常见是另一个人的罕见。常见的取决于您所从事的领域。
如果您正在为小项目进行非常快速的传输或计算哈希码,那么 CRC 会更好,因为它们速度更快,并且为错误数据获得相同的 16 位或 32 位 CRC 的机会很小。
如果它是兆字节的数据,例如,linux iso,那么您可能会丢失几兆字节,但最终还是会得到相同的 CRC。MD5 不太可能。出于这个原因,MD5 通常用于大量传输。它速度较慢但更可靠。
所以基本上,如果你要进行一次巨大的传输并在最后检查你是否得到正确的结果,请使用 MD5。如果要以小块传输,则使用 CRC。
我会说,如果你不知道该选择什么,那就去吧md5
。
引起您头痛的可能性较小。