devise tree_Devise如何确保您的Rails应用密码安全

devise tree

by Tiago Alves

由蒂亚戈·阿尔维斯(Tiago Alves)

Devise如何确保您的Rails应用密码安全 (How Devise keeps your Rails app passwords safe)

Devise is an incredible authentication solution for Rails with more than 40 million downloads. However, since it abstracts most of the cryptographic operations, it’s not always easy to understand what’s happening behind the scenes.

Devise是Rails令人难以置信的身份验证解决方案, 下载量超过4000万 。 但是,由于它抽象了大多数密码操作,因此了解幕后发生的事情并不总是那么容易。

One of those abstractions culminates in the persistence of an encrypted_password directly on the database. So I’ve always been curious about what it actually represents. Here’s an example:

这些抽象之一最终导致直接在数据库上encrypted_password了password_password。 因此,我一直对它真正代表什么感到好奇。 这是一个例子:

$2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO

$2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO

But what does that gibberish mean?

但是那胡言乱语是什么意思呢?

Devise uses Bcrypt to securely store information. On its website it mentions that it uses “OpenBSD bcrypt() password hashing algorithm, allowing you to easily store a secure hash of your users’ passwords”. But what exactly is this hash? How does it work and how does it keep stored passwords safe?

Devise使用Bcrypt安全地存储信息。 它在其网站上提到它使用“ OpenBSD bcrypt()密码哈希算法,使您可以轻松地存储用户密码的安全哈希 ”。 但是这个哈希到底是什么? 它是如何工作的以及如何确保存储的密码安全?

That’s what I want to show you today.

那就是我今天想告诉你的。

Let’s work backwards — from the stored hash on your database to the encryption and decryption process.

让我们倒退一下-从数据库上存储的哈希到加密和解密过程。

That hash $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO is actually comprised of several components:

哈希$2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO实际上由几个组成部分组成:

  • Bcrypt version (2a) - the version of the bcrypt() algorithm used to produce this hash (stored after the first $ sign)

    Bcrypt版本 ( 2a )-用于产生此哈希值的bcrypt()算法的版本(存储在第一个$符号之后)

  • Cost (11) - the cost factor used to create the hash (stored after the second $ sign)

    成本 ( 11 )-用于创建哈希的成本因子(存储在第二个$符号之后)

  • Salt ($2a$11$yMMbLgN9uY6J3LhorfU9iu) - a random string that when combined with your password makes it unique (first 29 characters)

    Salt ( $2a$11$yMMbLgN9uY6J3LhorfU9iu )-一个随机字符串,与您的密码结合使用时会使其唯一(前29个字符)

  • Checksum (LAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO) - the actual hash portion of the stored encrypted_password (remaining string after the 29 chars)

    校验和 ( LAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO ) -所存储的实际的哈希部encrypted_password (29个字符之后剩余字符串)

Let’s explore the last 3 parameters:

让我们探索最后三个参数:

  • When using Devise, the Cost value is set by a class variable called stretches and the default value is 11. It specifies the number of times the password is hashed. (On your devise.rb initializer, you can configure this to a lower value for the test environment to make your test suite run faster.) *

    使用Devise时, Cost值由一个称为stretchs的类变量设置,默认值为11 。 它指定密码被哈希的次数。 ( devise.rb初始化程序上 ,可以将其配置为测试环境的较低值,以使测试套件运行更快。 )

  • The salt is the random string used to combine with the original password. This is what makes the same password have different values when stored encrypted. (See more below about why that matters and what are Rainbow Table Attacks.) **

    是用于与原始密码组合的随机字符串。 这就是在加密存储时使同一密码具有不同值的原因。 ( 请参阅下面的更多内容,以了解为何如此重要以及什么是Rainbow Table Attack 。)**

  • The checksum is the actual generated hash of the password after being combined with the random salt.

    校验和是密码与随机盐组合后实际生成的哈希值。

When a user registers on your app, they must set a password. Before this password is stored in the database, a random salt is generated via BCrypt::Engine.generate_salt(cost) by taking into account the cost factor previously mentioned. (Note: if the pepper class variable value is set it will append its value to the password before salting it.)

用户在您的应用上注册时,必须设置密码。 在将此密码存储在数据库中之前,考虑到前面提到的成本因素,会通过BCrypt :: Engine.generate_salt(cost)生成随机盐。 (注意:如果设置了pepper 类变量值 ,它将在盐腌之前将其值附加到密码上 。)

With that salt (ex. $2a$11$yMMbLgN9uY6J3LhorfU9iu, which includes the cost factor) it will call BCrypt::Engine.hash_secret(password, salt) that computes the final hash to be stored using the generated salt and the password selected by the user. This final hash (for example, $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO) will in turn be stored in the encrypted_password column of the database.

使用该盐(例如$2a$11$yMMbLgN9uY6J3LhorfU9iu ,其中包括成本因素),它将调用BCrypt :: Engine.hash_secret(password,salt) ,使用生成的盐和由密码选择的密码来计算要存储的最终哈希用户。 此最终散列(例如, $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO )将被依次存储在encrypted_password数据库的列。

But if this hash is nonreversible and the salt is randomly generated on the BCrypt::Password.create call by BCrypt::Engine.generate_salt(cost), how can it be used to sign in the user?

但是,如果此哈希不可逆并且盐在BCrypt::Engine.generate_salt(cost)BCrypt::Password.create调用中随机生成, 如何将其用于登录用户?

That’s where those different hash components are useful. After finding the record that matches the email supplied by the user to sign in, the encrypted password is retrieved and broken down into the different components mentioned above (Bcrypt version, Cost, Salt and Checksum).

那是那些不同的哈希组件有用的地方。 找到与用户提供的用于登录的电子邮件匹配的记录后,将检索加密的密码并将其分解为上述不同的组成部分( Bcrypt版本CostSaltChecksum )。

After this initial preparation, here’s what happens next:

初步准备之后,接下来将发生以下情况:

  1. Fetch the input password (1234)

    获取输入的密码 ( 1234 )

  2. Fetch the salt of the stored password ($2a$11$yMMbLgN9uY6J3LhorfU9iu)

    获取存储的密码的 ( $2a$11$yMMbLgN9uY6J3LhorfU9iu )

  3. Generate the hash from the password and salt using the same bcrypt version and cost factor (BCrypt::Engine.hash_secret(“1234”, “$2a$11$yMMbLgN9uY6J3LhorfU9iu”))

    使用相同的bcrypt版本和成本因子( BCrypt::Engine.hash_secret(“1234”, “$2a$11$yMMbLgN9uY6J3LhorfU9iu”)从密码和salt生成哈希

  4. Check if the stored hash is the same one as the computed on step 3 ($2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO)

    检查存储的哈希值是否与步骤3上计算的哈希值相同( $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO )

And that’s how Devise stores passwords securely and protects you from a range of attacks even if your database is compromised.

这样一来,即使数据库受到威胁,Devise仍可以安全地存储密码并保护您免受一系列攻击。

Get in touch on Twitter @alvesjtiago and let me know if you found this article interesting! Thank you for reading.

在Twitter @alvesjtiago保持联系,如果您发现本文有趣,请告诉我! 感谢您的阅读。

PS: I’m by no means a security or cryptography expert so please do reach out if you find something wrong. I’m hoping that by simplifying some of the concepts it will be easier to understand what’s happening.
PS:我绝不是安全或加密专家,所以如果发现错误,请务必与我们联系。 我希望通过简化一些概念,可以更轻松地了解正在发生的事情。

Thank you @filipepina, @ivobenedito, @jackveiga, @joao_mags and @pedrosmmoreira for the reviews and suggestions. This article is also available at http://blog.tiagoalves.me/how-does-devise-keep-your-passwords-safe.

感谢@filipepina@ivobenedito@jackveiga@joao_mags@pedrosmmoreira的评论和建议。 本文也可以从http://blog.tiagoalves.me/how-does-devise-keep-your-passwords-safe获得

More information about some of the topics.

有关某些主题的更多信息。

Cost factor *

成本因素*

Rainbow Table Attacks **

彩虹桌攻击**

翻译自: https://www.freecodecamp.org/news/how-does-devise-keep-your-passwords-safe-d367f6e816eb/

devise tree

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值