Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why BCryptPasswordEncoder from Spring generate different outputs for same input?

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 output. You could test it with the code snippet below:

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

Could someone explain, why BCryptPasswordEncoder behave like this?

like image 946
Bhavesh Avatar asked Sep 15 '14 09:09

Bhavesh


People also ask

What is the use of BCryptPasswordEncoder?

Class BCryptPasswordEncoder Implementation of PasswordEncoder that uses the BCrypt strong hashing function. Clients can optionally supply a "strength" (a.k.a. log rounds in BCrypt) and a SecureRandom instance. The larger the strength parameter the more work will have to be done (exponentially) to hash the passwords.

Which Passwordencoders is recommended for production usage?

Password Encoding using BCryptPasswordEncoder The BCryptPasswordEncoder provides strength as a constructor argument to compute the hash. The larger value shows the longer time to hash but stronger password. We can also pass SecureRandom to randomize the generated hashes.

How do I use BCryptPasswordEncoder in spring boot?

Bootstrap: @Autowired private BCryptPasswordEncoder bCryptPasswordEncoder; @GetMapping("/test") public void fillDatabse() { String encodedPw=bCryptPasswordEncoder. encode("test"); Password p = new Password(encodedPw);

How do I decrypt BCryptPasswordEncoder in Java?

BCryptPasswordEncoder is a single-way password encoder. The one-way encoding algorithm is used to encrypt a password. There's no way to decrypt the password. Alternatively, the one-way password encoder returns the same encrypted string if you call the encoding algorithm with the same password.


Video Answer


4 Answers

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));     } } 
like image 173
blueberry0xff Avatar answered Oct 18 '22 09:10

blueberry0xff


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.

like image 44
Uwe Plonus Avatar answered Oct 18 '22 10:10

Uwe Plonus


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.

like image 32
user1364368 Avatar answered Oct 18 '22 10:10

user1364368


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.

like image 37
geoand Avatar answered Oct 18 '22 08:10

geoand