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

时间:2014-09-15 09:06:30

标签: java spring spring-security bcrypt

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

    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

每次产生不同的输出。

5 个答案:

答案 0 :(得分:21)

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));
    }
}

答案 1 :(得分:13)

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

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

答案 2 :(得分:5)

这是完全正常的,因为BCryptPasswordEncoder使用salt来生成密码。您可以阅读“腌制”密码herehere背后的想法。

这是文档针对encode方法

所说的内容
  

对原始密码进行编码。通常,一个好的编码算法会应用SHA-1或更大的哈希值以及一个8字节或更大的随机生成的盐。

答案 3 :(得分:1)

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

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

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

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

答案 4 :(得分:0)

BCrypt 输出是: $2a$10$cYLM.qoXpeAzcZhJ3oXRLu9Slkb61LHyWW5qJ4QKvHEMhaxZ5qCPi

$2a$ 表示哈希算法

10$ 是日志轮次

以下是盐和散列密码

由于 Spring 每次都会生成不同的盐,因此您的输出是不一样的。您可以参考的 BCrypt 语法 https://en.wikipedia.org/wiki/Bcrypt#Description