Why BCryptPasswordEncoder from Spring generate different outputs for same input?

前端 未结 4 2058
你的背包
你的背包 2020-12-13 19:03

I am using BCryptPasswordEncoder with Spring security. My expectation was that for the same input I will always get the same output. But for the same input I get different o

相关标签:
4条回答
  • 2020-12-13 19:38

    The 22 characters directly after the 2nd $ represent the salt value, see https://en.wikipedia.org/wiki/Bcrypt#Description . "Salt" is some random data added to the password before hashing, so a given hash algorithm with given parameters will in most cases produce different hash values for the same password (protection against so called rainbow attacks).

    Let's dissect the first output shown in the original question: $2a$10$cYLM.qoXpeAzcZhJ3oXRLu9Slkb61LHyWW5qJ4QKvHEMhaxZ5qCPi

    • $2a : Identifier for BCrypt algorithm
    • $10 : Parameter for number of rounds, here 2^10 rounds
    • cYLM.qoXpeAzcZhJ3oXRLu : Salt (128 bits)
    • 9Slkb61LHyWW5qJ4QKvHEMhaxZ5qCPi : Actual hash value (184 bits)

    The salt and the hash value are both encoded using Radix-64.

    0 讨论(0)
  • 2020-12-13 19:49

    That is perfectly normal because BCryptPasswordEncoder uses a salt to generate the password. You can read about the idea behind "salting" a password here and here.

    This is what the documentation says for the encode method

    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.

    0 讨论(0)
  • 2020-12-13 19:58
    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));
        }
    }
    
    0 讨论(0)
  • 2020-12-13 20:00

    The generated password are salted and therefore different.

    Please read the documentation for the encode() method where it clearly states the the password is salted.

    0 讨论(0)
提交回复
热议问题