5

我有一个现有的 Web 应用程序,有几千个用户,我将其移植到 Rails。当我重写和重构这个应用程序时,我可能需要在任意数量的不同服务器上运行它以用于开发、测试和生产目的。

我在我的用户模型中使用 Rails 的内置 has_secure_password 方法,但我担心密码数据的可移植性。我需要将我的数据库的内容从一台机器移动到另一台机器以在不同的环境中进行测试,这非常重要,我可以在每个环境中使用相同的用户和密码集来测试用户身份验证功能。

到目前为止,很容易找到关于 bcrypt-ruby 如何与 Rails 一起工作的答案,has_secure_password但经过数周的搜索,我还没有找到明确的答案。

如果has_secure_password结果是 WorkFactor + Salt + HashedPassword 连接并保存到password_digest数据库列,那么如果移动到任何其他机器(假设任何其他机器在类 Unix 操作系统上运行 Rails),是否可以重新生成并可靠地比较该哈希?

或者换一种说法——bcrypt-ruby 密码是由 Rails 的has_secure_password便携式生成的吗?

后续问题:如果盐总是随机生成(我已经看到相同的密码使用不同的哈希,所以我不认为盐是从密码本身的文本中创建的)那么 Rails 应用程序如何能够可靠地重新哈希登录表单上的密码提交并将其与数据库中的内容进行比较。显然,它必须首先知道盐是什么才能进行比较。它是如何做到的?

4

1 回答 1

5

是的,密码是可移植的。使用的格式是标准的“加密编码”格式,也用作 RFC 2307 的一部分(在 RFC 2307 中,字符串的前缀为“{CRYPT}”)。我使用过一个 Perl 库Authen::Passphrase,该库很乐意根据来自 RoR 数据库的 bcrypt 散列版本验证密码。

对于后续问题: salt 嵌入在存储的值中(连同散列的类型、要使用的 bcrypt 周期数,当然还有散列本身),并且为了验证服务器需要读取存储的值,然后它只是重新使用相同的盐来生成散列部分 - 如果输入密码正确,那么散列将是相同的。身份验证过程不会创建新的随机盐。仅在生成用于存储的全新哈希时才会创建随机盐。

bcrypt 密码很容易拆分成组件供服务器读取(我选择了非现实字符以便更容易看到边界,实际上 salt 和 hash 是 base 64 编码的二进制数据):

 $2a$10$AaBbCcDdEeFfGgHhIiJjKk0987654321098765432109876543210
  • 这部分的意思是“使用 bcrypt,2**10 == 1024 次迭代”:$2a$10$

  • 这部分是 salt: AaBbCcDdEeFfGgHhIiJjKk,总是 22 个字符

  • 这部分是 hash: 0987654321098765432109876543210,总是 31 个字符

于 2013-09-29T15:39:06.710 回答