Spring BCryptPasswordEncoder为相同的输入生成不同的密码

Bha*_*esh 19 java spring spring-security bcrypt

我正在使用带有Spring安全性的BCryptPasswordEncoder.但问题是它为同一输入生成不同的编码密码.

String password = "123456"; 
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); 
String encodedPassword = passwordEncoder.encode(password);
System.out.print(encodedPassword);
Run Code Online (Sandbox Code Playgroud)

每次产生不同的输出.

blu*_*xff 27

public static void main(String[] args) {
  // spring 4.0.0
  org.springframework.security.crypto.password.PasswordEncoder encoder
   = new org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder();

   // $2a$10$lB6/PKg2/JC4XgdMDXyjs.dLC9jFNAuuNbFkL9udcXe/EBjxSyqxW
   // true
   // $2a$10$KbQiHKTa1WIsQFTQWQKCiujoTJJB7MCMSaSgG/imVkKRicMPwgN5i
   // true
   // $2a$10$5WfW4uxVb4SIdzcTJI9U7eU4ZwaocrvP.2CKkWJkBDKz1dmCh50J2
   // true
   // $2a$10$0wR/6uaPxU7kGyUIsx/JS.krbAA9429fwsuCyTlEFJG54HgdR10nK
   // true
   // $2a$10$gfmnyiTlf8MDmwG7oqKJG.W8rrag8jt6dNW.31ukgr0.quwGujUuO
   // true

    for (int i = 0; i < 5; i++) {
      // "123456" - plain text - user input from user interface
      String passwd = encoder.encode("123456");

      // passwd - password from database
      System.out.println(passwd); // print hash

      // true for all 5 iteration
      System.out.println(encoder.matches("123456", passwd));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 问题是“有人可以解释为什么 BCryptPasswordEncoder 会这样吗?” - 这个答案不_解释_,而只提供代码,没有一个_解释_字。 (6认同)
  • 本例中的名称“passwd”表示 *encodedPassword*(哈希码),而不是 *rawPassword*,这有点违反直觉。 (3认同)

Uwe*_*nus 16

生成的密码是盐渍的,因此不同.

请阅读encode()方法的文档,其中明确说明密码已被腌制.

  • @Bhavesh 为此存在方法matches()[http://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/apidocs/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoder。 html]。请阅读您要使用的类的文档。 (2认同)

geo*_*and 5

这是完全正常的,因为BCryptPasswordEncoder使用盐来生成密码。您可以在此处此处阅读有关“为密码设置密码”背后的想法的信息

这就是文档对encode方法的说明

编码原始密码。通常,良好的编码算法将SHA-1或更大的哈希值与8字节或更大的随机生成的盐结合使用。


use*_*368 5

第二个$之后的22个字符代表盐值,请参阅https://en.wikipedia.org/wiki/Bcrypt#Description。“盐”是散列之前添加到密码的一些随机数据,因此具有给定参数的给定散列算法在大多数情况下将为同一密码生成不同的散列值(防止所谓的rainbow攻击)。

让我们剖析原始问题中显示的第一个输出: $2a$10$cYLM.qoXpeAzcZhJ3oXRLu9Slkb61LHyWW5qJ4QKvHEMhaxZ5qCPi

  • $2a :BCrypt算法的标识符
  • $10 :轮数的参数,此处为2 ^ 10轮
  • cYLM.qoXpeAzcZhJ3oXRLu :盐(128位)
  • 9Slkb61LHyWW5qJ4QKvHEMhaxZ5qCPi :实际哈希值(184位)

salt和哈希值均使用Radix-64进行编码。