1

Spring Security 中的 BCryptPasswordEncoder - l_lOct

 1 month ago
source link: https://www.cnblogs.com/lwwwl/p/18091183
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一、使用BCryptPasswordEncoder加密的值可以解出来吗

  Spring Security 中的 BCryptPasswordEncoder 是一种单向加密算法,它是为了安全性考虑而设计的,因此无法从加密后的密码值"解密"出原始密码。这是出于安全目的的设计。

  BCryptPasswordEncoder 加密过程是不可逆的,即使你有加密后的密码值,也无法通过任何方式获得原始密码。这种单向加密的目的就是为了防止密码泄露后被破解。

  通常,在实际应用中,我们只需要将用户输入的原始密码使用 BCryptPasswordEncoder 进行加密,然后将加密后的密码值存储在数据库中。在用户登录时,将用户输入的密码加密后,与存储在数据库中的加密密码进行比对,如果相同则验证通过,而无需知道原始密码。

  因此,你无法从 BCryptPasswordEncoder 加密后的密码值中"解密"出原始密码。这正是它被设计用于密码加密的目的,以提高系统的安全性。如果你需要知道用户的原始密码,建议在注册时不对密码进行加密,或者提供"忘记密码"的功能让用户重置密码。

二、为什么每次BCryptPasswordEncoder加密的值不一样,却可以都匹配上原始密码

  这是因为 BCryptPasswordEncoder 在加密时会自动添加一个随机的 Salt 值,这个 Salt 值的作用是使得相同的原始密码在每次加密时产生不同的密文,从而增加密码的安全性。

  具体来说,BCryptPasswordEncoder 加密过程包括以下几个步骤:

    1. 生成一个随机的 Salt 值,通常是 16 字节长度。
    2. 将原始密码和 Salt 值进行合并。
    3. 对合并后的值进行 BCrypt 哈希运算,计算出最终的密文。
    4. 将 Salt 值和密文拼接在一起,作为最终的加密结果。

  因此,每次加密相同的原始密码时,由于使用了不同的随机 Salt 值,所以最终的加密结果也是不同的。

  在验证密码时,BCryptPasswordEncoder 会自动从加密结果中提取出 Salt 值,并使用相同的方式对输入的原始密码进行加密,然后比较两个密文是否相同。由于使用了相同的 Salt 值,所以即使每次加密后的结果不同,只要原始密码相同,通过 BCrypt 算法计算出的密文就是相同的。

  这种机制不仅增加了密码的安全性,而且还能防止采用相同密码的不同用户的密文相同,从而增加了"彩虹表"攻击的难度。所以即使每次加密结果不同,BCryptPasswordEncoder 依然能够正确比对密码。

三、BCryptPasswordEncoder 加密结果的格式

  在 BCryptPasswordEncoder 加密后的结果中,前 29 个字符是包含了 Salt 值和其他算法信息的部分,后面的字符串才是实际的密文部分。

  具体来说,BCryptPasswordEncoder 加密结果的格式是:

$算法标识$rounds$salt$密文
  • `$算法标识` 是一个固定的字符串 `$2a$`、`$2b$` 或 `$2y$`等,用于标识使用的哈希算法版本。
  • `$rounds` 是一个十进制数字,表示算法迭代的次数。
  • `$salt` 是一个 22 个字符长的 Base64 编码的字符串,这就是加密时使用的随机 Salt 值。
  • `$密文` 是实际的密文部分,长度为 31 个字符。

  例如,一个典型的 BCryptPasswordEncoder 加密结果可能是:

$2a$10$N9qo8uHh24cuh6zT6ZsEfe6Fzen7kNSNBqh.FkQPvQUNhxfrasXTi

  在这个加密结果中:

  •  `$2a$` 表示使用 BCrypt 算法的版本 2a
  •  `10` 表示迭代次数为 10
  •  `N9qo8uHh24cuh6zT6ZsEfe` 就是 22 个字符长的随机 Salt 值
  •  最后 31 个字符 `6Fzen7kNSNBqh.FkQPvQUNhxfrasXTi` 才是实际的密文部分

  所以,BCryptPasswordEncoder 加密结果中,第 4 到第 25 个字符就是随机生成的 Salt 值。每次加密相同的密码,这部分 Salt 值都会不同,从而导致最终的加密结果也不相同。但在验证时,会自动提取出这个 Salt 值用于计算,所以能够正确比对密码。

四、Salt 值和真实密码合并后的值进行 BCrypt 哈希运算,如果知道salt值和最终的密文可以解出原来的密码吗

  即使知道了Salt值和最终的密文,也无法通过任何方式反解出原始的密码。

  这是因为BCrypt是一种经过加盐(Salting)的单向自适应密钥导出函数(Key Derivation Function),它的设计目的就是使得从密文反推原始密码是计算上不可行的。

  具体来说,BCrypt算法包含以下几个关键设计:

    1. 使用了Eksblowfish算法作为核心,这是一种密钥设置可变的块加密算法,具有良好的密码学性质。
    2. 在密钥设置中引入了可变的迭代次数,默认为2^10次,这使得暴力破解的计算代价大大增加。
    3. 在密钥设置中引入了随机的Salt值,使得相同的密码每次产生的密文都不同,防止彩虹表攻击。
    4. 密钥设置过程是自适应和可变的,可以根据硬件性能动态调整计算代价。
    5. 最终密文使用Base64编码,长度为53个字符,其中包含了Salt和其他算法参数。

  因此,即使已知Salt值和密文,要反解出原始密码,仍然需要进行大量的计算和暴力破解。由于BCrypt算法设计的目的就是使这种破解行为在计算上不可行,所以实际上是无法通过任何方式从Salt和密文中反解出原始密码的。

  这就是BCrypt作为密码哈希算法的设计理念和安全保证。除非原始密码非常简单且Salt和迭代次数设置较低,否则从BCrypt密文中反解是极其困难的。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK