使用bcrypt生成的Rails密码是否可移植?

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

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

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

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

或者换句话说 – 使用Rails的has_secure_password生成的bcrypt-ruby密码has_secure_password可移植?

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

是的,密码是可移植的。 使用的格式是标准的“crypt编码”格式,也用作RFC 2307的一部分(在RFC 2307中,字符串将以“{CRYPT}”为前缀)。 我使用过Perl库Authen::Passphrase ,可以根据RoR数据库中的bcrypt-hashed版本快速validation密码。

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

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

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

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

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