关于java:Spring BCryptPasswordEncoder为同一输入生成不同的密码

Spring BCryptPasswordEncoder generate different password for same input

我正在使用带弹簧安全的BcryptPasswordEncoder。但问题是,它为相同的输入生成不同的编码密码。

1
2
3
4
5
6
7
8
9
10
11
    String password ="123456";
    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    String encodedPassword = passwordEncoder.encode(password);  
    System.out.print(encodedPassword);


output : $2a$10$cYLM.qoXpeAzcZhJ3oXRLu9Slkb61LHyWW5qJ4QKvHEMhaxZ5qCPi

output2 : $2a$10$KEvYX9yjj0f1X3Wl8S.KPuWzSWGyGM9ubI71NOm3ZNbJcwWN6agvW

output3 : $2a$10$nCmrPtUaOLn5EI73VZ4Ouu1TmkSWDUxxD4N6A.8hPBWg43Vl.RLDC

每次它产生不同的输出。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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));
    }
}


生成的密码经过盐渍处理,因此不同。

请阅读encode()方法的文档,其中它清楚地说明密码是salt格式的。


这是完全正常的,因为bcryptPasswordEncoder使用salt生成密码。你可以在这里和这里阅读关于"加盐"密码背后的想法。

这就是文档对encode方法所说的。

Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or greater hash combined with an 8-byte or greater randomly generated salt.


第2$后面的22个字符表示salt值,请参阅https://en.wikipedia.org/wiki/bcrypt description。"salt"是在散列之前添加到密码中的一些随机数据,因此具有给定参数的给定散列算法在大多数情况下会为同一密码生成不同的散列值(防止所谓的彩虹攻击)。

让我们分析原始问题中显示的第一个输出:江户十一〔一〕号

  • $2a:bcrypt算法的标识符
  • $10:参数,用于轮数,这里是2^10轮。
  • cYLM.qoXpeAzcZhJ3oXRLu:盐(128位)
  • 9Slkb61LHyWW5qJ4QKvHEMhaxZ5qCPi:实际散列值(184位)

salt和hash值都是使用基数64编码的。