是的,您可以将其存储在单个字段中,并且许多数据库/应用程序将 salt+hash 存储在单个字段/文件等中。
最著名的是 Linux(它不是数据库),它使用以下格式将哈希存储在 /etc/shadow 文件中:
“$id$salt$hashed”,密码哈希的可打印形式,由 crypt (C) 生成,其中“$id”是使用的算法。(在 GNU/Linux 上,“$1$”代表 MD5,“$2a$”代表 Blowfish,“$2y$”代表 Blowfish(正确处理 8 位字符),“$5$”代表 SHA-256,“$6 $" 是 SHA-512,[4] 其他 Unix 可能有不同的值,例如 NetBSD。
(来源:https ://en.wikipedia.org/wiki/Passwd )
盐并不意味着是秘密的(或者至少不比哈希更秘密)。它的主要目的是使暴力攻击更加困难,因为攻击者必须为每个用户使用不同的盐。
但是您的问题更加细致入微-因为您不仅在询问盐,还询问了参数。诸如散列算法、迭代计数和盐之类的东西。无论如何,不要将它存储在代码中,它们仍然属于数据库。
想象一下,您有一群用户,并且您使用 SHA1 作为您的散列算法。因此,您的数据库字段将类似于SHA1:SALT:HASH。
如果你想将你的数据库升级到 BCRYPT,你会怎么做?
通常,您会部署一些代码,以便在用户登录时验证密码,如果有效 - 您将使用更新的算法重新散列密码。现在用户的字段如下所示:BCRYPT:SALT:HASH。
但是有些用户会在 SHA1 上,而其他用户会在 BCRYPT 上,因为这是在用户级别,所以您需要参数来告诉您的代码哪些用户是数据库中的哪些用户。
简而言之,将参数和散列存储在一个字段中是可以的,但无论出于何种原因(效率、更简单的代码等)将它们分开也是可以的。不好的是将其存储在您的代码中:)
TL:博士
Troy Hunt 最近发布了一个播客,建议不要以上述方式迁移到 BCRYPT,更有效的是简单地获取数据库中当前的所有 SHA1 哈希,并使用 BCRYPT 对它们进行哈希处理。
有效地 BCRYPT(SHA1(clear_password))
当用户登录时,您会
BCRYPT(SHA1(clear_password)) == <db_field>
这样,平台上的每个人都可以立即升级,并且您没有具有多种密码哈希格式的数据库。非常干净,非常好。
我认为这个想法很合理,但即使每个人都同时迁移,也不是瞬间完成的。除非您愿意在应用程序上接受一些停机时间(当您重新散列所有密码时),否则仍然会有一些用户使用 BCRYPT 和一些用户使用 SHA1 的时间间隔,因此您的数据库仍应存储散列算法的参数,您的代码将基于它执行。