Processing time measurement for each BCrypt + stretch count in Java

Double encryption of password with SHA256 (questions can be explained in the comments) gives you valuable insights in exchange for red shame So, let's try the password ~~ encryption ~~ hashing with BCrypt and PBKDF2 that you introduced immediately. This time is BCrypt edition.

Library used

This time, BCrypt ~~ encryption ~~ hashing will be performed using the spring-security that was taught in the comment of the above article. I don't need the whole Spring, so I borrowed only the spring-security jar from mvn repository. ..

First of all, encoding and authentication

String passStr = "password_desu_4";
String hashStr;

//Encode
BCryptPasswordEncoder bpe = new BCryptPasswordEncoder();
hashStr = bpe.encode(passStr);
System.out.println("original string   : " + passStr);
System.out.println("encoded by Bcrypt : " + hashStr);

//Authentication
boolean isMatch = bpe.matches(passStr, hashStr);
System.out.println("result            : " + (isMatch ? "match" : "not match"));

smart!

The result looks like this

original string   : password_desu_4
encoded by Bcrypt : $2a$10$HQwFeyajSohLrmbHTEzJbuHzPgITU7CJ/fQbJfEBCkBJXz5lCk8ke
result            : match

Processing time for each stretch count

You can set the strength by passing an int from 4 to 31 to the constructor of the BCryptPasswordEncoder class. It's strength, not stretch times. It seems to stretch the multiplier of 2 for the argument.

Naturally, the processing time will also increase exponentially. Good luck, it's a 32-bit i7 core laptop.

= strength : 4, streach times : 16 ========
encoding time  : 0.003 sec.
verifying time : 0.002 sec.

= strength : 5, streach times : 32 ========
encoding time  : 0.004 sec.
verifying time : 0.004 sec.

= strength : 6, streach times : 64 ========
encoding time  : 0.007 sec.
verifying time : 0.008 sec.

= strength : 7, streach times : 128 ========
encoding time  : 0.015 sec.
verifying time : 0.014 sec.

= strength : 8, streach times : 256 ========
encoding time  : 0.029 sec.
verifying time : 0.030 sec.

= strength : 9, streach times : 512 ========
encoding time  : 0.058 sec.
verifying time : 0.060 sec.

= strength : 10, streach times : 1024 ========★ Default strength
encoding time  : 0.118 sec.
verifying time : 0.117 sec.

= strength : 11, streach times : 2048 ========
encoding time  : 0.240 sec.
verifying time : 0.231 sec.

= strength : 12, streach times : 4096 ========
encoding time  : 0.462 sec.
verifying time : 0.463 sec.

= strength : 13, streach times : 8192 ========
encoding time  : 0.924 sec.
verifying time : 0.926 sec.

= strength : 14, streach times : 16384 ========
encoding time  : 1.847 sec.
verifying time : 1.840 sec.

= strength : 15, streach times : 32768 ========
encoding time  : 3.702 sec.
verifying time : 3.691 sec.

= strength : 16, streach times : 65536 ========
encoding time  : 7.440 sec.
verifying time : 7.402 sec.

= strength : 17, streach times : 131072 ========
encoding time  : 14.867 sec.
verifying time : 14.776 sec.

= strength : 18, streach times : 262144 ========
encoding time  : 30.416 sec.
verifying time : 29.593 sec.

= strength : 19, streach times : 524288 ========
encoding time  : 60.6590 sec.
verifying time : 60.180 sec.

= strength : 20, streach times : 1048576 ========

It's still on the way, but it's getting harder to wait for processing

Well, the processing time depends on the environment, so it wouldn't make much sense to record the exact number of seconds in my environment. So, the tendency that can be read so far is as follows.

--The time required for hashing and the time required for authentication are approximately the same. ――If strength increases by 1, the processing time will be doubled.

… It's natural because the amount of processing is doubled.

So if you give a simplified theoretical value

strength processing time
20 2 minutes
21 4 minutes
22 8 minutes
23 16 minutes
24 32 minutes
25 1 hour 4 minutes
26 2 hours 8 minutes
27 4 hours 16 minutes
28 8 hours 32 minutes
29 17 hours 4 minutes
30 1 day and 10 hours 8 minutes
31 2 days and 20 hours 16 minutes

Exponential function is scary.

This amount of processing is required for one password, although it will naturally shrink if done in a high-spec environment. The strength is 10 (stretch 1024 times) by default, but even considering the waiting time for normal login, I think that the limit is about 0.5 seconds (strength = 12 in this environment) at most.

This can be a security measure. I realized it for myself. I'm glad I didn't try until ~~ 31 ~~

Full class

import java.math.BigInteger;
import java.util.Date;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class CryptUtil {
	
	/**
	 *Hash with Bcypt while measuring processing time
	 * @param passStr password string
	 * @param strength The number of hashes. 4-31 (how many of 2)
	 */
	public static String testBcryptEncode(String passStr, int strength) {
		
		//Start time
		long startTime = (new Date()).getTime();
		
		//Hashing with BCrypt
		BCryptPasswordEncoder bpe = new BCryptPasswordEncoder(strength);
		String hashStr = bpe.encode(passStr);
		
		//Hashing end time
		long endTime = (new Date()).getTime();
		String timeDelta = String.format("%.4f", ((float)(endTime - startTime) / 1000));
		
	    System.out.println("encoding time  : " + timeDelta + " sec.");
	    
	    return hashStr;
	}
	
	/**
	 *Authentication whether the raw password and hash match while measuring the processing time
	 * @param passStr raw
	 * @param hashStr hash
	 * @param strength
	 */
	public static void testBcyptVerify(String passStr, String hashStr, int strength) {
		
		//Start time
		long startTime = (new Date()).getTime();
		
		//Check if the password matches the hash
		BCryptPasswordEncoder bpe = new BCryptPasswordEncoder(strength);
		boolean isMatch = bpe.matches(passStr, hashStr);
		
		//Verification end time
		long endTime = (new Date()).getTime();
		String timeDelta = String.format("%.4f", ((float)(endTime - startTime) / 1000));
		
		if (isMatch) {
		    System.out.println("verifying time : " + timeDelta + " sec.");
		} else {
			
		}
	}
	
	public static void main(String[] args) {
		
		String passStr = "password_desu_4";
		String hashStr;
		
		//Simple encoding and authentication
		BCryptPasswordEncoder bpe = new BCryptPasswordEncoder();
		hashStr = bpe.encode(passStr);
		System.out.println("original string   : " + passStr);
		System.out.println("encoded by Bcrypt : " + hashStr);
		
		boolean isMatch = bpe.matches(passStr, hashStr);
		System.out.println("result            : " + (isMatch ? "match" : "not match"));		
		
		System.out.println("");
		
		//Time measurement for each strength
		double streachTimes; 

		for (int strength=4; strength<=31; strength++) {
			streachTimes = Math.pow(2, strength);
			System.out.println("= strength : " + strength + ", streach times : " + String.format("%1$.0f", streachTimes) + " ========");
			hashStr = testBcryptEncode(passStr, strength);
			testBcyptVerify(passStr, hashStr, strength);
		}
	}

}

Recommended Posts

Processing time measurement for each BCrypt + stretch count in Java
[Java] Processing time measurement method memo
[Java] for Each and sorted in Lambda
Enable / disable SNI in Java for each communication
Accurate time measurement (Java)
[Java] Make variables in extended for statement and for Each statement immutable
Measured parallel processing in Java
Rock-paper-scissors game for beginners in Java
Date processing in Java (LocalDate: Initialization)
[For beginners] Run Selenium in Java
About file copy processing in Java
Settings for SSL debugging in Java
For the time being, run the war file delivered in Java with Docker
[Socket communication (Java)] Impressions of implementing Socket communication in practice for the first time
Programming for the first time in my life Java 1st Hello World
Memory measurement for Java apps using jstat
Introduction to java for the first time # 2
First steps for deep learning in Java
Key points for introducing gRPC in Java
Learning for the first time java [Introduction]
Impressions and doubts about using java for the first time in Android Studio
[Deep Learning from scratch] in Java 1. For the time being, differentiation and partial differentiation