哈希密码时,可以将使用的算法存储在数据库中吗?

信息安全 密码 哈希 数据库
2021-09-09 16:57:43

由于散列密码最近已成为热门话题,因此很自然地期望事情会发生变化,并假设在未来一段时间您可能想要替换/调整系统中使用的算法。这自然会导致为新老用户存储不同类型的哈希。

我想知道如果我只是将数据库中使用的算法存储在每个哈希之前,是否可以接受?类似于 bcrypt 输出的外观:($2a$...算法版本)。如果我按名称存储它sha1$f6238eb6ca...怎么办?

显式公开使用的算法是否会使事情变得更糟?我在想,即使攻击者知道(极少数的)确切算法,破解它的工作顺序或多或少都是相同的,x1 或 x5 没什么大不了的,同样的 O(努力)。但它让我更容易管理。

各位专家怎么看?

更新。我正在考虑另一种选择,例如通过诸如 alg1、alg2 之类的代码来引用特定算法,并在应用程序的其他地方写下这些引用的解释,以便将这些信息放在手边。如果我最初的想法变得不好,这种方法会纠正它吗?

4个回答

当然没关系。这是Kerckhoffs 原理的一个简单应用:保密性不在算法中,而在密钥或密码中。对于初学者,任何有权访问您的实现或其文档,或者知道您的应用程序所构建的库支持什么的人,都知道您的应用程序可能使用什么算法。攻击者最多只能尝试一个小列表。如果有多种可能性,您的应用程序还必须尝试该列表,无缘无故地降低身份验证速度(您自己的工作量增加了与攻击者相同的数量)。

正如您所注意到的,通常的做法是将算法的标识添加到 salt 和 hash 之前。诚然,通常的做法并不总是明智的,但它就是这样。Bcrypt 使用继承自 Unix 实践的数字代码。如果您愿意,您可以使用自己的命名方案,但像往常一样,您应该坚持使用您的库提供的内容,除非您有充分的理由去做自己的事情。

这样做并不会让事情变得更糟,事实上,许多散列存储解决方案正是这样做的(类似于您的 bcrypt 输出示例),以便操作系统(或应用程序)知道使用什么散列算法来与存储的散列进行比较。

安全性不依赖于以任何方式保持算法的秘密 - 它依赖于算法足够强大,以至于在正常情况下两个密码提供相同哈希的机会非常低,并且蛮力比较生成的哈希所需的努力是尽可能高。

通常,仅哈希输出的长度就足以放弃该秘密:

MD5: 128 位
SHA1: 160 位
SHA256: 256 位
SHA512: 512 位

试图对你的算法保密是一场失败的战斗。您希望通过保密获得安全,而不是通过默默无闻获得安全

正如其他人已经解释的那样,试图对算法保密并不是一个好主意。但是,如果您想要额外的保护免受损害数据库而不是可执行代码的攻击,您可以在代码中存储一个秘密的“pepper”值和/或算法,以便攻击者必须弄清楚您到底在做什么在散列之前使用数据。在这种情况下尝试对算法保密仍然提供不了多少安全性(因为它并不难弄清楚),但保持密钥保密将使任何攻击变得相当复杂。

请参阅如何安全地散列密码?有关该主题的更多信息。