Why BCryptPasswordEncoder from Spring generate different outputs for same input?

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

The 22 characters directly after the 3rd $ 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.


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.