diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/PasswordEncodingSpringBootApplication.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/PasswordEncodingSpringBootApplication.java index 5a23e82..950eb31 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/PasswordEncodingSpringBootApplication.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/PasswordEncodingSpringBootApplication.java @@ -6,8 +6,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class PasswordEncodingSpringBootApplication { - public static void main(String[] args) { - SpringApplication.run(PasswordEncodingSpringBootApplication.class, args); - } - + public static void main(String[] args) { + SpringApplication.run(PasswordEncodingSpringBootApplication.class, args); + } } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/JdbcUserDetailPasswordService.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/JdbcUserDetailPasswordService.java index d150a1f..61ddb03 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/JdbcUserDetailPasswordService.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/JdbcUserDetailPasswordService.java @@ -9,20 +9,20 @@ import org.springframework.transaction.annotation.Transactional; @Service public class JdbcUserDetailPasswordService implements UserDetailsPasswordService { - private final UserRepository userRepository; + private final UserRepository userRepository; - private final UserDetailsMapper userDetailsMapper; + private final UserDetailsMapper userDetailsMapper; - public JdbcUserDetailPasswordService(UserRepository userRepository, UserDetailsMapper userDetailsMapper) { - this.userRepository = userRepository; - this.userDetailsMapper = userDetailsMapper; - } + public JdbcUserDetailPasswordService( + UserRepository userRepository, UserDetailsMapper userDetailsMapper) { + this.userRepository = userRepository; + this.userDetailsMapper = userDetailsMapper; + } - - @Override - public UserDetails updatePassword(UserDetails user, String newPassword) { - UserCredentials userCredentials = userRepository.findByUsername(user.getUsername()); - userCredentials.setPassword(newPassword); - return userDetailsMapper.toUserDetails(userCredentials); - } + @Override + public UserDetails updatePassword(UserDetails user, String newPassword) { + UserCredentials userCredentials = userRepository.findByUsername(user.getUsername()); + userCredentials.setPassword(newPassword); + return userDetailsMapper.toUserDetails(userCredentials); + } } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/JdbcUserDetailsService.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/JdbcUserDetailsService.java index a9beaa2..4dae702 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/JdbcUserDetailsService.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/JdbcUserDetailsService.java @@ -10,19 +10,19 @@ import org.springframework.transaction.annotation.Transactional; @Transactional public class JdbcUserDetailsService implements UserDetailsService { - private final UserRepository userRepository; + private final UserRepository userRepository; - private final UserDetailsMapper userDetailsMapper; + private final UserDetailsMapper userDetailsMapper; - public JdbcUserDetailsService(UserRepository userRepository, UserDetailsMapper userDetailsMapper) { - this.userRepository = userRepository; - this.userDetailsMapper = userDetailsMapper; - } + public JdbcUserDetailsService( + UserRepository userRepository, UserDetailsMapper userDetailsMapper) { + this.userRepository = userRepository; + this.userDetailsMapper = userDetailsMapper; + } - - @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - UserCredentials userCredentials = userRepository.findByUsername(username); - return userDetailsMapper.toUserDetails(userCredentials); - } + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + UserCredentials userCredentials = userRepository.findByUsername(username); + return userDetailsMapper.toUserDetails(userCredentials); + } } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/UserCredentials.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/UserCredentials.java index 48b48b1..54a2ee0 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/UserCredentials.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/UserCredentials.java @@ -16,16 +16,16 @@ import java.util.Set; @Table(name = "users") public class UserCredentials { - @Id - private String username; + @Id private String username; - private String password; + private String password; - boolean enabled; + boolean enabled; - @ElementCollection - @JoinTable(name = "authorities", joinColumns = {@JoinColumn(name = "username")}) - @Column(name = "authority") - private Set roles; + @ElementCollection + @JoinTable( + name = "authorities", + joinColumns = {@JoinColumn(name = "username")}) + @Column(name = "authority") + private Set roles; } - diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/UserDetailsMapper.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/UserDetailsMapper.java index de6085d..ccb60a7 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/UserDetailsMapper.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/UserDetailsMapper.java @@ -7,12 +7,11 @@ import org.springframework.stereotype.Component; @Component public class UserDetailsMapper { - UserDetails toUserDetails(UserCredentials userCredentials) { + UserDetails toUserDetails(UserCredentials userCredentials) { - return User - .withUsername(userCredentials.getUsername()) - .password(userCredentials.getPassword()) - .roles(userCredentials.getRoles().toArray(String[]::new)) - .build(); - } + return User.withUsername(userCredentials.getUsername()) + .password(userCredentials.getPassword()) + .roles(userCredentials.getRoles().toArray(String[]::new)) + .build(); + } } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/UserRepository.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/UserRepository.java index 61b67d7..b916c2c 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/UserRepository.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/authentication/UserRepository.java @@ -6,5 +6,5 @@ import org.springframework.transaction.annotation.Transactional; @Transactional public interface UserRepository extends JpaRepository { - UserCredentials findByUsername(String username); + UserCredentials findByUsername(String username); } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/configuration/SecurityConfiguration.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/configuration/SecurityConfiguration.java index f32704a..47675a8 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/configuration/SecurityConfiguration.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/configuration/SecurityConfiguration.java @@ -29,73 +29,84 @@ import java.util.Map; @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + private final UserRepository userRepository; + private final UserDetailsMapper userDetailsMapper; + private final BcCryptWorkFactorService bcCryptWorkFactorService; - private final UserRepository userRepository; - private final UserDetailsMapper userDetailsMapper; - private final BcCryptWorkFactorService bcCryptWorkFactorService; + public SecurityConfiguration( + UserRepository userRepository, + UserDetailsMapper userDetailsMapper, + BcCryptWorkFactorService bcCryptWorkFactorService) { + this.userRepository = userRepository; + this.userDetailsMapper = userDetailsMapper; + this.bcCryptWorkFactorService = bcCryptWorkFactorService; + } - public SecurityConfiguration(UserRepository userRepository, UserDetailsMapper userDetailsMapper, BcCryptWorkFactorService bcCryptWorkFactorService) { - this.userRepository = userRepository; - this.userDetailsMapper = userDetailsMapper; - this.bcCryptWorkFactorService = bcCryptWorkFactorService; - } + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception { + httpSecurity + .csrf() + .disable() + .authorizeRequests() + .antMatchers("/registration") + .permitAll() + .anyRequest() + .authenticated() + .and() + .httpBasic(); - @Override - protected void configure(HttpSecurity httpSecurity) throws Exception { - httpSecurity - .csrf().disable() - .authorizeRequests() - .antMatchers("/registration").permitAll() - .anyRequest().authenticated() - .and() - .httpBasic(); + httpSecurity.headers().frameOptions().disable(); + } - httpSecurity.headers().frameOptions().disable(); - } + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth.authenticationProvider(daoAuthenticationProvider()).eraseCredentials(false); + } - @Autowired - public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { - auth - .authenticationProvider(daoAuthenticationProvider()) - .eraseCredentials(false); - } + @Bean + public PasswordEncoder passwordEncoder() { + // we must user deprecated encoder to support their encoding + String encodingId = "bcrypt"; + Map encoders = new HashMap<>(); + encoders.put( + encodingId, new BCryptPasswordEncoder(bcCryptWorkFactorService.calculateStrength())); + encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder()); + encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder()); + encoders.put( + "MD5", + new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5")); + encoders.put( + "noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance()); + encoders.put("pbkdf2", new Pbkdf2PasswordEncoder()); + encoders.put("scrypt", new SCryptPasswordEncoder()); + encoders.put( + "SHA-1", + new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1")); + encoders.put( + "SHA-256", + new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256")); + encoders.put( + "sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder()); + encoders.put("argon2", new Argon2PasswordEncoder()); + return new DelegatingPasswordEncoder(encodingId, encoders); + } - @Bean - public PasswordEncoder passwordEncoder() { - // we must user deprecated encoder to support their encoding - String encodingId = "bcrypt"; - Map encoders = new HashMap<>(); - encoders.put(encodingId, new BCryptPasswordEncoder(bcCryptWorkFactorService.calculateStrength())); - encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder()); - encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder()); - encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5")); - encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance()); - encoders.put("pbkdf2", new Pbkdf2PasswordEncoder()); - encoders.put("scrypt", new SCryptPasswordEncoder()); - encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1")); - encoders.put("SHA-256", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256")); - encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder()); - encoders.put("argon2", new Argon2PasswordEncoder()); + @Bean + public UserDetailsPasswordService userDetailsPasswordService() { + return new JdbcUserDetailPasswordService(userRepository, userDetailsMapper); + } - return new DelegatingPasswordEncoder(encodingId, encoders); - } + public UserDetailsService userDetailsService() { + return new JdbcUserDetailsService(userRepository, userDetailsMapper); + } - @Bean - public UserDetailsPasswordService userDetailsPasswordService() { - return new JdbcUserDetailPasswordService(userRepository, userDetailsMapper); - } - - public UserDetailsService userDetailsService() { - return new JdbcUserDetailsService(userRepository, userDetailsMapper); - } - - @Bean - public DaoAuthenticationProvider daoAuthenticationProvider() { - DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); - daoAuthenticationProvider.setPasswordEncoder(passwordEncoder()); - daoAuthenticationProvider.setUserDetailsPasswordService(userDetailsPasswordService()); - daoAuthenticationProvider.setUserDetailsService(userDetailsService()); - return daoAuthenticationProvider; - } + @Bean + public DaoAuthenticationProvider daoAuthenticationProvider() { + DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); + daoAuthenticationProvider.setPasswordEncoder(passwordEncoder()); + daoAuthenticationProvider.setUserDetailsPasswordService(userDetailsPasswordService()); + daoAuthenticationProvider.setUserDetailsService(userDetailsService()); + return daoAuthenticationProvider; + } } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/Argon2Example.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/Argon2Example.java index 594403c..8705d2f 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/Argon2Example.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/Argon2Example.java @@ -4,15 +4,15 @@ import org.springframework.security.crypto.argon2.Argon2PasswordEncoder; public class Argon2Example { + public String encode(String plainPassword) { + int saltLength = 16; // salt length in bytes + int hashLength = 32; // hash length in bytes + int parallelism = 1; // currently is not supported + int memory = 4096; // memory costs + int iterations = 3; - public String encode(String plainPassword) { - int saltLength = 16; // salt length in bytes - int hashLength = 32; // hash length in bytes - int parallelism = 1; // currently is not supported - int memory = 4096; // memory costs - int iterations = 3; - - Argon2PasswordEncoder argon2PasswordEncoder = new Argon2PasswordEncoder(saltLength, hashLength, parallelism, memory, iterations); - return argon2PasswordEncoder.encode(plainPassword); - } + Argon2PasswordEncoder argon2PasswordEncoder = + new Argon2PasswordEncoder(saltLength, hashLength, parallelism, memory, iterations); + return argon2PasswordEncoder.encode(plainPassword); + } } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/BCryptExample.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/BCryptExample.java index 348f9a3..87dd838 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/BCryptExample.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/BCryptExample.java @@ -6,9 +6,10 @@ import java.security.SecureRandom; public class BCryptExample { - public String encode(String plainPassword) { - int strength = 10; - BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(strength, new SecureRandom()); - return bCryptPasswordEncoder.encode(plainPassword); - } + public String encode(String plainPassword) { + int strength = 10; + BCryptPasswordEncoder bCryptPasswordEncoder = + new BCryptPasswordEncoder(strength, new SecureRandom()); + return bCryptPasswordEncoder.encode(plainPassword); + } } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/Pbkdf2Example.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/Pbkdf2Example.java index a40b1c9..dbd3f43 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/Pbkdf2Example.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/Pbkdf2Example.java @@ -4,13 +4,14 @@ import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder; public class Pbkdf2Example { - public String encode(String plainPassword) { + public String encode(String plainPassword) { - String pepper = "pepper"; // secret key used by password encoding - int iterations = 200000; // number of hash iteration - int hashWidth = 256; // hash with in bits + String pepper = "pepper"; // secret key used by password encoding + int iterations = 200000; // number of hash iteration + int hashWidth = 256; // hash with in bits - Pbkdf2PasswordEncoder pbkdf2PasswordEncoder = new Pbkdf2PasswordEncoder(pepper, iterations, hashWidth); - return pbkdf2PasswordEncoder.encode(plainPassword); - } + Pbkdf2PasswordEncoder pbkdf2PasswordEncoder = + new Pbkdf2PasswordEncoder(pepper, iterations, hashWidth); + return pbkdf2PasswordEncoder.encode(plainPassword); + } } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/SCryptExample.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/SCryptExample.java index 2cb9869..165389a 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/SCryptExample.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/encoder/SCryptExample.java @@ -4,14 +4,15 @@ import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder; public class SCryptExample { - public String encode(String plainPassword) { - int cpuCost = (int) Math.pow(2, 14); // factor to increase CPU costs - int memoryCost = 8; // factor to increases memory usage - int parallelization = 1; // currently nor supported by Spring Security - int keyLength = 32; // key length in bytes - int saltLength = 64; // salt length in bytes + public String encode(String plainPassword) { + int cpuCost = (int) Math.pow(2, 14); // factor to increase CPU costs + int memoryCost = 8; // factor to increases memory usage + int parallelization = 1; // currently nor supported by Spring Security + int keyLength = 32; // key length in bytes + int saltLength = 64; // salt length in bytes - SCryptPasswordEncoder sCryptPasswordEncoder = new SCryptPasswordEncoder(cpuCost, memoryCost, parallelization, keyLength, saltLength); - return sCryptPasswordEncoder.encode(plainPassword); - } + SCryptPasswordEncoder sCryptPasswordEncoder = + new SCryptPasswordEncoder(cpuCost, memoryCost, parallelization, keyLength, saltLength); + return sCryptPasswordEncoder.encode(plainPassword); + } } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/migration/PasswordMigration.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/migration/PasswordMigration.java index 1ab6f8a..ee3b6e3 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/migration/PasswordMigration.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/migration/PasswordMigration.java @@ -13,21 +13,19 @@ import org.springframework.stereotype.Component; @Component public class PasswordMigration { - @Bean - public ApplicationListener authenticationSuccessListener( - PasswordEncoder encoder, - UserDetailsPasswordService userDetailsPasswordService) { - return (AuthenticationSuccessEvent event) -> { - Authentication authentication = event.getAuthentication(); - User user = (User) authentication.getPrincipal(); - String encodedPassword = user.getPassword(); - if (encodedPassword.startsWith("{SHA-1}")) { - CharSequence clearTextPassword = (CharSequence) authentication.getCredentials(); - String newPassword = encoder.encode(clearTextPassword); - userDetailsPasswordService.updatePassword(user, newPassword); - } - ((UsernamePasswordAuthenticationToken) authentication).eraseCredentials(); - }; - } - + @Bean + public ApplicationListener authenticationSuccessListener( + PasswordEncoder encoder, UserDetailsPasswordService userDetailsPasswordService) { + return (AuthenticationSuccessEvent event) -> { + Authentication authentication = event.getAuthentication(); + User user = (User) authentication.getPrincipal(); + String encodedPassword = user.getPassword(); + if (encodedPassword.startsWith("{SHA-1}")) { + CharSequence clearTextPassword = (CharSequence) authentication.getCredentials(); + String newPassword = encoder.encode(clearTextPassword); + userDetailsPasswordService.updatePassword(user, newPassword); + } + ((UsernamePasswordAuthenticationToken) authentication).eraseCredentials(); + }; + } } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/Car.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/Car.java index 98eacfd..a8e2668 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/Car.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/Car.java @@ -11,6 +11,6 @@ import lombok.NoArgsConstructor; @AllArgsConstructor public class Car { - private String name; - private String color; + private String name; + private String color; } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/CarResources.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/CarResources.java index db68b8d..b56932c 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/CarResources.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/CarResources.java @@ -8,19 +8,11 @@ import java.util.Set; @RestController public class CarResources { - // we use this endpoint as authentication test - @GetMapping("/cars") - public Set cars() { - return Set.of( - Car.builder() - .name("vw") - .color("black") - .build(), - Car.builder() - .name("bmw") - .color("white") - .build() - ); - } + // we use this endpoint as authentication test + @GetMapping("/cars") + public Set cars() { + return Set.of( + Car.builder().name("vw").color("black").build(), + Car.builder().name("bmw").color("white").build()); + } } - diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/UserCredentialsDto.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/UserCredentialsDto.java index e38695f..7ccf5bb 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/UserCredentialsDto.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/UserCredentialsDto.java @@ -11,6 +11,6 @@ import lombok.NoArgsConstructor; @NoArgsConstructor public class UserCredentialsDto { - private String username; - private String password; + private String username; + private String password; } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/UserResources.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/UserResources.java index 62b6a16..6d74fb9 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/UserResources.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/resources/UserResources.java @@ -16,24 +16,24 @@ import java.util.Set; @Transactional public class UserResources { - private final UserRepository userRepository; - private final PasswordEncoder passwordEncoder; + private final UserRepository userRepository; + private final PasswordEncoder passwordEncoder; - public UserResources(UserRepository userRepository, PasswordEncoder passwordEncoder) { - this.userRepository = userRepository; - this.passwordEncoder = passwordEncoder; - } + public UserResources(UserRepository userRepository, PasswordEncoder passwordEncoder) { + this.userRepository = userRepository; + this.passwordEncoder = passwordEncoder; + } - - @PostMapping("/registration") - @ResponseStatus(code = HttpStatus.CREATED) - public void register(@RequestBody UserCredentialsDto userCredentialsDto) { - UserCredentials user = UserCredentials.builder() - .enabled(true) - .username(userCredentialsDto.getUsername()) - .password(passwordEncoder.encode(userCredentialsDto.getPassword())) - .roles(Set.of("USER")) - .build(); - userRepository.save(user); - } + @PostMapping("/registration") + @ResponseStatus(code = HttpStatus.CREATED) + public void register(@RequestBody UserCredentialsDto userCredentialsDto) { + UserCredentials user = + UserCredentials.builder() + .enabled(true) + .username(userCredentialsDto.getUsername()) + .password(passwordEncoder.encode(userCredentialsDto.getPassword())) + .roles(Set.of("USER")) + .build(); + userRepository.save(user); + } } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/workfactor/BcCryptWorkFactorService.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/workfactor/BcCryptWorkFactorService.java index 688b358..403e0c7 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/workfactor/BcCryptWorkFactorService.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/workfactor/BcCryptWorkFactorService.java @@ -9,84 +9,93 @@ import java.util.concurrent.TimeUnit; @Component public class BcCryptWorkFactorService { - private static final String TEST_PASSWORD = "my password"; - private static final int GOAL_MILLISECONDS_PER_PASSWORD = 1000; - private static final int MIN_STRENGTH = 4; - private static final int MAX_STRENGTH = 31; + private static final String TEST_PASSWORD = "my password"; + private static final int GOAL_MILLISECONDS_PER_PASSWORD = 1000; + private static final int MIN_STRENGTH = 4; + private static final int MAX_STRENGTH = 31; + /** + * Calculates the strength (a.k.a. log rounds) for the BCrypt Algorithm, so that password encoding + * takes about 1s. This method uses the divide-and-conquer algorithm. + */ + public BcryptWorkFactor calculateStrengthDivideAndConquer() { + return calculateStrengthDivideAndConquer( + new BcryptWorkFactor(MIN_STRENGTH, Integer.MIN_VALUE), + new BcryptWorkFactor(MAX_STRENGTH, Integer.MAX_VALUE)); + } - /** - * Calculates the strength (a.k.a. log rounds) for the BCrypt Algorithm, so that password encoding takes about 1s. - * This method iterates over strength from 4 to 31 and calculates the duration of password encoding for every value of strength. - * It returns the first strength, that takes more than 500s - */ - public int calculateStrength() { - for (int strength = MIN_STRENGTH; strength <= MAX_STRENGTH; strength++) { - - BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(strength); - - Stopwatch stopwatch = Stopwatch.createStarted(); - bCryptPasswordEncoder.encode(TEST_PASSWORD); - stopwatch.stop(); - - long duration = stopwatch.elapsed(TimeUnit.MILLISECONDS); - if (duration >= GOAL_MILLISECONDS_PER_PASSWORD) { - return strength; - } - } - throw new RuntimeException(String.format("Could not find suitable round number for bcrypt encoding. The encoding with %d rounds" + - " takes less than %d ms.", MAX_STRENGTH, GOAL_MILLISECONDS_PER_PASSWORD)); + private BcryptWorkFactor calculateStrengthDivideAndConquer( + BcryptWorkFactor smallFactor, BcryptWorkFactor bigFactor) { + if (bigFactor.getStrength() - smallFactor.getStrength() == 1) { + return getClosestStrength(smallFactor, bigFactor); } - - /** - * Calculates the strength (a.k.a. log rounds) for the BCrypt Algorithm, so that password encoding takes about 1s. - * This method iterate over strength from 4 to 31 and calculates the duration of password encoding for every value of strength. - * When the the duration takes more than 1s, it is compared to previous one and the method returns the strength, tha is closer - * to 1s. - */ - public int calculateStrengthClosestToTimeGoal() { - - long previousDuration = Long.MIN_VALUE; - for (int strength = MIN_STRENGTH; strength <= MAX_STRENGTH; strength++) { - BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(strength); - - Stopwatch stopwatch = Stopwatch.createStarted(); - bCryptPasswordEncoder.encode(TEST_PASSWORD); - stopwatch.stop(); - long currentDuration = stopwatch.elapsed(TimeUnit.MILLISECONDS); - - if (isGreaterThanGoal(currentDuration)) { - return getStrength(previousDuration, currentDuration, strength); - } - previousDuration = currentDuration; - } - throw new RuntimeException(String.format("Could not find suitable round number for bcrypt encoding. The encoding with %d rounds" + - " takes less than %d ms.", MAX_STRENGTH, GOAL_MILLISECONDS_PER_PASSWORD)); + int midStrength = + (bigFactor.getStrength() - smallFactor.getStrength()) / 2 + smallFactor.getStrength(); + long duration = calculateDuration(midStrength); + BcryptWorkFactor midFactor = new BcryptWorkFactor(midStrength, duration); + if (duration < GOAL_MILLISECONDS_PER_PASSWORD) { + return calculateStrengthDivideAndConquer(midFactor, bigFactor); } + return calculateStrengthDivideAndConquer(smallFactor, midFactor); + } - /** - * @param previousDuration duration from previous iteration - * @param currentDuration duration of current iteration - * @param strength current strength - * @return return the current strength, if current duration is closer to GOAL_MILLISECONDS_PER_PASSWORD, otherwise - * current strength-1. - */ - int getStrength(long previousDuration, long currentDuration, int strength) { - if (isPreviousDurationCloserToGoal(previousDuration, currentDuration)) { - return strength - 1; - } else { - return strength; - } + private BcryptWorkFactor getClosestStrength( + BcryptWorkFactor smallFactor, BcryptWorkFactor bigFactor) { + if (isPreviousDurationCloserToGoal(smallFactor.getDuration(), bigFactor.getDuration())) { + return smallFactor; } + return bigFactor; + } - private boolean isGreaterThanGoal(long duration) { - return duration > GOAL_MILLISECONDS_PER_PASSWORD; - } + private long calculateDuration(int strength) { + BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(strength); + Stopwatch stopwatch = Stopwatch.createStarted(); + bCryptPasswordEncoder.encode(TEST_PASSWORD); + stopwatch.stop(); + return stopwatch.elapsed(TimeUnit.MILLISECONDS); + } - /** - * return true, if previousDuration is closer to the goal than currentDuration, false otherwise. - */ - boolean isPreviousDurationCloserToGoal(long previousDuration, long currentDuration) { - return Math.abs(GOAL_MILLISECONDS_PER_PASSWORD - previousDuration) < Math.abs(GOAL_MILLISECONDS_PER_PASSWORD - currentDuration); + /** + * Calculates the strength (a.k.a. log rounds) for the BCrypt Algorithm, so that password encoding + * takes about 1s. This method iterates over strength from 4 to 31 and calculates the duration of + * password encoding for every value of strength. It returns the first strength, that takes more + * than 1s + */ + public int calculateStrength() { + for (int strength = MIN_STRENGTH; strength <= MAX_STRENGTH; strength++) { + + long duration = calculateDuration(strength); + if (duration >= GOAL_MILLISECONDS_PER_PASSWORD) { + return strength; + } } + throw new RuntimeException( + String.format( + "Could not find suitable round number for bcrypt encoding. The encoding with %d rounds" + + " takes less than %d ms.", + MAX_STRENGTH, GOAL_MILLISECONDS_PER_PASSWORD)); + } + + /** + * @param previousDuration duration from previous iteration + * @param currentDuration duration of current iteration + * @param strength current strength + * @return return the current strength, if current duration is closer to + * GOAL_MILLISECONDS_PER_PASSWORD, otherwise current strength-1. + */ + int getStrength(long previousDuration, long currentDuration, int strength) { + if (isPreviousDurationCloserToGoal(previousDuration, currentDuration)) { + return strength - 1; + } else { + return strength; + } + } + + /** + * return true, if previousDuration is closer to the goal than currentDuration, false otherwise. + */ + boolean isPreviousDurationCloserToGoal(long previousDuration, long currentDuration) { + return Math.abs(GOAL_MILLISECONDS_PER_PASSWORD - previousDuration) + < Math.abs(GOAL_MILLISECONDS_PER_PASSWORD - currentDuration); + } } diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/workfactor/BcryptWorkFactor.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/workfactor/BcryptWorkFactor.java new file mode 100644 index 0000000..5eb3f3f --- /dev/null +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/workfactor/BcryptWorkFactor.java @@ -0,0 +1,12 @@ +package io.reflectoring.passwordencoding.workfactor; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class BcryptWorkFactor { + + private int strength; + private long duration; +} diff --git a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/workfactor/Pbkdf2WorkFactorService.java b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/workfactor/Pbkdf2WorkFactorService.java index 3bf734f..1bad448 100644 --- a/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/workfactor/Pbkdf2WorkFactorService.java +++ b/spring-boot/password-encoding/src/main/java/io/reflectoring/passwordencoding/workfactor/Pbkdf2WorkFactorService.java @@ -9,31 +9,33 @@ import java.util.concurrent.TimeUnit; @Component public class Pbkdf2WorkFactorService { - private static final String TEST_PASSWORD = "my password"; - private static final String NO_ADDITIONAL_SECRET = ""; - private static final int GOAL_MILLISECONDS_PER_PASSWORD = 1000; - private static final int HASH_WIDTH = 256; - private static final int ITERATION_STEP = 5000; + private static final String TEST_PASSWORD = "my password"; + private static final String NO_ADDITIONAL_SECRET = ""; + private static final int GOAL_MILLISECONDS_PER_PASSWORD = 1000; + private static final int HASH_WIDTH = 256; + private static final int ITERATION_STEP = 5000; - /** - * Finds the number of Iteration for the {@link Pbkdf2PasswordEncoder} to get the duration of password encoding - * close to 1s. The Calculation does not use any secret (pepper) and applies hash algorithm SHA256. - */ - public int calculateIteration() { + /** + * Finds the number of Iteration for the {@link Pbkdf2PasswordEncoder} to get the duration of + * password encoding close to 1s. The Calculation does not use any secret (pepper) and applies + * hash algorithm SHA256. + */ + public int calculateIteration() { - int iterationNumber = 150000; - while (true) { - Pbkdf2PasswordEncoder pbkdf2PasswordEncoder = new Pbkdf2PasswordEncoder(NO_ADDITIONAL_SECRET, iterationNumber, HASH_WIDTH); + int iterationNumber = 150000; + while (true) { + Pbkdf2PasswordEncoder pbkdf2PasswordEncoder = + new Pbkdf2PasswordEncoder(NO_ADDITIONAL_SECRET, iterationNumber, HASH_WIDTH); - Stopwatch stopwatch = Stopwatch.createStarted(); - pbkdf2PasswordEncoder.encode(TEST_PASSWORD); - stopwatch.stop(); + Stopwatch stopwatch = Stopwatch.createStarted(); + pbkdf2PasswordEncoder.encode(TEST_PASSWORD); + stopwatch.stop(); - long duration = stopwatch.elapsed(TimeUnit.MILLISECONDS); - if (duration > GOAL_MILLISECONDS_PER_PASSWORD) { - return iterationNumber; - } - iterationNumber += ITERATION_STEP; - } + long duration = stopwatch.elapsed(TimeUnit.MILLISECONDS); + if (duration > GOAL_MILLISECONDS_PER_PASSWORD) { + return iterationNumber; + } + iterationNumber += ITERATION_STEP; } + } } diff --git a/spring-boot/password-encoding/src/main/resources/db/migration/V1_2__add user.sql b/spring-boot/password-encoding/src/main/resources/db/migration/V1_2__add user.sql index 6eeef98..254e7c0 100644 --- a/spring-boot/password-encoding/src/main/resources/db/migration/V1_2__add user.sql +++ b/spring-boot/password-encoding/src/main/resources/db/migration/V1_2__add user.sql @@ -1,5 +1,15 @@ -insert into users (username, password, enabled) VALUES ('admin', '{bcrypt}$2a$10$4V9kA793Pi2xf94dYFgKWuw8ukyETxWb7tZ4/mfco9sWkwvBQndxW', true); -insert into users (username, password, enabled) VALUES ('user', '{SHA-256}{4Cc0+yDMHnTUy+zOHeMH7yaPhxvlJT//tQTwEhyegiQ=}446d06130bfc254527a7bbd95b50595a977c0058110f8dccb54bd273d99325b8', true); -insert into users (username, password, enabled) VALUES ('user with working factor 5', '{bcrypt}$2a$05$Zz4rToG8YXKMbuAPgm3qj.HpTFsGEdZHhCf9ikIHAoI5elX7ajNm.', true); -insert into users (username, password, enabled) VALUES ('user with sha1 encoding', '{SHA-1}{6tND0AZfFH3aE1VDg7QkWT6DzFg/NUHtukntgwu8JV4=}804c6e8efebf4e91f88e3baf9fd383e28a21378c', true); -insert into users (username, password, enabled) VALUES ('scrypt user', '{scrypt}$e0801$fUx3MxN07zdH3UyARJqOwv3WiWCvE7f6qRm9A5KQfNo5ovSwxMHknQ4vERO4csj/I3imG2HJQg1HHp7Rqzbp7g==$Fm5F9PSoE/jBYLOmnCJcvX1Euf952r5b3BjAl+SwQMs=', true); \ No newline at end of file +insert into users (username, password, enabled) +VALUES ('admin', '{bcrypt}$2a$10$4V9kA793Pi2xf94dYFgKWuw8ukyETxWb7tZ4/mfco9sWkwvBQndxW', true); +insert into users (username, password, enabled) +VALUES ('user', + '{SHA-256}{4Cc0+yDMHnTUy+zOHeMH7yaPhxvlJT//tQTwEhyegiQ=}446d06130bfc254527a7bbd95b50595a977c0058110f8dccb54bd273d99325b8', + true); +insert into users (username, password, enabled) +VALUES ('user with working factor 5', '{bcrypt}$2a$05$Zz4rToG8YXKMbuAPgm3qj.HpTFsGEdZHhCf9ikIHAoI5elX7ajNm.', true); +insert into users (username, password, enabled) +VALUES ('user with sha1 encoding', + '{SHA-1}{6tND0AZfFH3aE1VDg7QkWT6DzFg/NUHtukntgwu8JV4=}804c6e8efebf4e91f88e3baf9fd383e28a21378c', true); +insert into users (username, password, enabled) +VALUES ('scrypt user', + '{scrypt}$e0801$fUx3MxN07zdH3UyARJqOwv3WiWCvE7f6qRm9A5KQfNo5ovSwxMHknQ4vERO4csj/I3imG2HJQg1HHp7Rqzbp7g==$Fm5F9PSoE/jBYLOmnCJcvX1Euf952r5b3BjAl+SwQMs=', + true); \ No newline at end of file diff --git a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/authentication/UserDetailsMapperTest.java b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/authentication/UserDetailsMapperTest.java index 666ab15..dce400e 100644 --- a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/authentication/UserDetailsMapperTest.java +++ b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/authentication/UserDetailsMapperTest.java @@ -9,24 +9,25 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; class UserDetailsMapperTest { - private UserDetailsMapper userDetailsMapper = new UserDetailsMapper(); + private UserDetailsMapper userDetailsMapper = new UserDetailsMapper(); - @Test - void toUserDetails() { - // given - UserCredentials userCredentials = UserCredentials.builder() - .enabled(true) - .password("password") - .username("user") - .roles(Set.of("USER", "ADMIN")) - .build(); + @Test + void toUserDetails() { + // given + UserCredentials userCredentials = + UserCredentials.builder() + .enabled(true) + .password("password") + .username("user") + .roles(Set.of("USER", "ADMIN")) + .build(); - // when - UserDetails userDetails = userDetailsMapper.toUserDetails(userCredentials); + // when + UserDetails userDetails = userDetailsMapper.toUserDetails(userCredentials); - // then - assertThat(userDetails.getUsername()).isEqualTo("user"); - assertThat(userDetails.getPassword()).isEqualTo("password"); - assertThat(userDetails.isEnabled()).isTrue(); - } -} \ No newline at end of file + // then + assertThat(userDetails.getUsername()).isEqualTo("user"); + assertThat(userDetails.getPassword()).isEqualTo("password"); + assertThat(userDetails.isEnabled()).isTrue(); + } +} diff --git a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/authentication/UserRepositoryTest.java b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/authentication/UserRepositoryTest.java index 4d2bc2a..38970de 100644 --- a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/authentication/UserRepositoryTest.java +++ b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/authentication/UserRepositoryTest.java @@ -9,18 +9,17 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; @DataJpaTest class UserRepositoryTest { - @Autowired - private UserRepository userRepository; + @Autowired private UserRepository userRepository; - @Test - void findUserByUsername() { - // given - String username = "user"; + @Test + void findUserByUsername() { + // given + String username = "user"; - // when - UserCredentials userCredentials = userRepository.findByUsername(username); + // when + UserCredentials userCredentials = userRepository.findByUsername(username); - // then - assertThat(userCredentials).isNotNull(); - } -} \ No newline at end of file + // then + assertThat(userCredentials).isNotNull(); + } +} diff --git a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/Argon2ExampleTest.java b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/Argon2ExampleTest.java index 6c72f7d..cc12d93 100644 --- a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/Argon2ExampleTest.java +++ b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/Argon2ExampleTest.java @@ -6,17 +6,17 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class Argon2ExampleTest { - private Argon2Example argon2Example = new Argon2Example(); + private Argon2Example argon2Example = new Argon2Example(); - @Test - void encode() { - // given - String plainPassword = "password"; + @Test + void encode() { + // given + String plainPassword = "password"; - // when - String actual = argon2Example.encode(plainPassword); + // when + String actual = argon2Example.encode(plainPassword); - // then - assertThat(actual).startsWith("$argon2id$v=19$m=4096,t=3,p=1"); - } -} \ No newline at end of file + // then + assertThat(actual).startsWith("$argon2id$v=19$m=4096,t=3,p=1"); + } +} diff --git a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/BCryptExampleTest.java b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/BCryptExampleTest.java index a2b5c45..7fa6bc0 100644 --- a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/BCryptExampleTest.java +++ b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/BCryptExampleTest.java @@ -6,17 +6,17 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class BCryptExampleTest { - private BCryptExample bcryptExample = new BCryptExample(); + private BCryptExample bcryptExample = new BCryptExample(); - @Test - void encode() { - // given - String plainPassword = "password"; + @Test + void encode() { + // given + String plainPassword = "password"; - // when - String encoded = bcryptExample.encode(plainPassword); + // when + String encoded = bcryptExample.encode(plainPassword); - // then - assertThat(encoded).startsWith("$2a$10"); - } -} \ No newline at end of file + // then + assertThat(encoded).startsWith("$2a$10"); + } +} diff --git a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/Pbkdf2ExampleTest.java b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/Pbkdf2ExampleTest.java index e2a68c6..3ccd734 100644 --- a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/Pbkdf2ExampleTest.java +++ b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/Pbkdf2ExampleTest.java @@ -6,17 +6,17 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class Pbkdf2ExampleTest { - private Pbkdf2Example pbkdf2Example = new Pbkdf2Example(); + private Pbkdf2Example pbkdf2Example = new Pbkdf2Example(); - @Test - void encode() { - // given - String plainPassword = "plainPassword"; + @Test + void encode() { + // given + String plainPassword = "plainPassword"; - // when - String actual = pbkdf2Example.encode(plainPassword); + // when + String actual = pbkdf2Example.encode(plainPassword); - // then - assertThat(actual).hasSize(80); - } -} \ No newline at end of file + // then + assertThat(actual).hasSize(80); + } +} diff --git a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/SCryptExampleTest.java b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/SCryptExampleTest.java index e2ebe7f..0ddb647 100644 --- a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/SCryptExampleTest.java +++ b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/encoder/SCryptExampleTest.java @@ -6,18 +6,18 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class SCryptExampleTest { - private SCryptExample sCryptExample = new SCryptExample(); + private SCryptExample sCryptExample = new SCryptExample(); - @Test - void encode() { - // given - String plainPassword = "password"; + @Test + void encode() { + // given + String plainPassword = "password"; - // when - String actual = sCryptExample.encode(plainPassword); + // when + String actual = sCryptExample.encode(plainPassword); - // then - assertThat(actual).hasSize(140); - assertThat(actual).startsWith("$e0801"); - } -} \ No newline at end of file + // then + assertThat(actual).hasSize(140); + assertThat(actual).startsWith("$e0801"); + } +} diff --git a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/resources/CarResourcesTest.java b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/resources/CarResourcesTest.java index 99a734f..543be98 100644 --- a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/resources/CarResourcesTest.java +++ b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/resources/CarResourcesTest.java @@ -22,73 +22,70 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @Transactional class CarResourcesTest { - @Autowired - private MockMvc mockMvc; + @Autowired private MockMvc mockMvc; - @Autowired - private ObjectMapper objectMapper; + @Autowired private ObjectMapper objectMapper; - @Autowired - private UserRepository userRepository; + @Autowired private UserRepository userRepository; - @Test - void getCarsShouldReturnUnauthorizedIfTheRequestHasNoBasicAuthentication() throws Exception { - mockMvc.perform(get("/cars")) - .andExpect(status().isUnauthorized()); - } + @Test + void getCarsShouldReturnUnauthorizedIfTheRequestHasNoBasicAuthentication() throws Exception { + mockMvc.perform(get("/cars")).andExpect(status().isUnauthorized()); + } - @Test - void getCarsShouldReturnCarsForTheAuthenticatedUser() throws Exception { - mockMvc.perform(get("/cars") - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()); - } + @Test + void getCarsShouldReturnCarsForTheAuthenticatedUser() throws Exception { + mockMvc.perform(get("/cars").with(httpBasic("user", "password"))).andExpect(status().isOk()); + } - @Test - void registrationShouldReturnCreated() throws Exception { + @Test + void registrationShouldReturnCreated() throws Exception { - // register - UserCredentialsDto userCredentialsDto = UserCredentialsDto.builder().username("toyota").password("my secret").build(); - mockMvc.perform(post("/registration") + // register + UserCredentialsDto userCredentialsDto = + UserCredentialsDto.builder().username("toyota").password("my secret").build(); + mockMvc + .perform( + post("/registration") .contentType(MediaType.APPLICATION_JSON_VALUE) .content(objectMapper.writeValueAsString(userCredentialsDto))) - .andExpect(status().isCreated()); - } + .andExpect(status().isCreated()); + } - @Test - void registrationShouldReturnUnauthorizedWithWrongCredentials() throws Exception { + @Test + void registrationShouldReturnUnauthorizedWithWrongCredentials() throws Exception { - mockMvc.perform(get("/cars") - .with(httpBasic("user", "wrong password"))) - .andExpect(status().isUnauthorized()); - } + mockMvc + .perform(get("/cars").with(httpBasic("user", "wrong password"))) + .andExpect(status().isUnauthorized()); + } - @Test - void getCarsShouldUpdatePasswordFromWorkingFactor5toHigherValue() throws Exception { - mockMvc.perform(get("/cars") - .with(httpBasic("user with working factor 5", "password"))) - .andExpect(status().isOk()); + @Test + void getCarsShouldUpdatePasswordFromWorkingFactor5toHigherValue() throws Exception { + mockMvc + .perform(get("/cars").with(httpBasic("user with working factor 5", "password"))) + .andExpect(status().isOk()); - UserCredentials userCredentials = userRepository.findByUsername("user with working factor 5"); - // we don't know what strength the BcCryptWorkFactorService returns, - // but it should be more than 5 - assertThat(userCredentials.getPassword()).doesNotStartWith("{bcrypt}$2a$05"); - } + UserCredentials userCredentials = userRepository.findByUsername("user with working factor 5"); + // we don't know what strength the BcCryptWorkFactorService returns, + // but it should be more than 5 + assertThat(userCredentials.getPassword()).doesNotStartWith("{bcrypt}$2a$05"); + } - @Test - void getCarsShouldUpdateSha1PasswordToBcrypt() throws Exception { - mockMvc.perform(get("/cars") - .with(httpBasic("user with sha1 encoding", "password"))) - .andExpect(status().isOk()); + @Test + void getCarsShouldUpdateSha1PasswordToBcrypt() throws Exception { + mockMvc + .perform(get("/cars").with(httpBasic("user with sha1 encoding", "password"))) + .andExpect(status().isOk()); - UserCredentials userCredentials = userRepository.findByUsername("user with sha1 encoding"); - assertThat(userCredentials.getPassword()).startsWith("{bcrypt}"); - } + UserCredentials userCredentials = userRepository.findByUsername("user with sha1 encoding"); + assertThat(userCredentials.getPassword()).startsWith("{bcrypt}"); + } - @Test - void getCarsShouldReturnOkForScryptUser() throws Exception { - mockMvc.perform(get("/cars") - .with(httpBasic("scrypt user", "password"))) - .andExpect(status().isOk()); - } -} \ No newline at end of file + @Test + void getCarsShouldReturnOkForScryptUser() throws Exception { + mockMvc + .perform(get("/cars").with(httpBasic("scrypt user", "password"))) + .andExpect(status().isOk()); + } +} diff --git a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/workfactor/BcCryptWorkFactorServiceTest.java b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/workfactor/BcCryptWorkFactorServiceTest.java index 6cc2c1d..54e64bd 100644 --- a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/workfactor/BcCryptWorkFactorServiceTest.java +++ b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/workfactor/BcCryptWorkFactorServiceTest.java @@ -1,121 +1,119 @@ package io.reflectoring.passwordencoding.workfactor; import org.junit.jupiter.api.Test; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class BcCryptWorkFactorServiceTest { - private BcCryptWorkFactorService bcCryptWorkFactorService = new BcCryptWorkFactorService(); + private BcCryptWorkFactorService bcCryptWorkFactorService = new BcCryptWorkFactorService(); - @Test - void calculateStrength() { - // given + @Test + void calculateStrength() { + // given - // when - int strength = bcCryptWorkFactorService.calculateStrength(); + // when + int strength = bcCryptWorkFactorService.calculateStrength(); - BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(strength); + // then + assertThat(strength).isBetween(4, 31); + } - // then - assertThat(strength).isBetween(4, 31); - } + @Test + void calculateStrengthBi() { + // given - @Test - void calculateRounds() { - // given + // when + BcryptWorkFactor bcryptWorkFactor = + bcCryptWorkFactorService.calculateStrengthDivideAndConquer(); - // when - int strength = bcCryptWorkFactorService.calculateStrengthClosestToTimeGoal(); + // then + assertThat(bcryptWorkFactor.getStrength()).isBetween(4, 31); + } - // then - assertThat(strength).isBetween(4, 31); - } + @Test + void findCloserToShouldReturnNumber1IfItCloserToGoalThanNumber2() { + // given + int number1 = 950; + int number2 = 1051; - @Test - void findCloserToShouldReturnNumber1IfItCloserToGoalThanNumber2() { - // given - int number1 = 950; - int number2 = 1051; + // when + boolean actual = bcCryptWorkFactorService.isPreviousDurationCloserToGoal(number1, number2); - // when - boolean actual = bcCryptWorkFactorService.isPreviousDurationCloserToGoal(number1, number2); + // then + assertThat(actual).isTrue(); + } - // then - assertThat(actual).isTrue(); - } + @Test + void findCloserToShouldReturnNUmber2IfItCloserToGoalThanNumber1() { + // given + int number1 = 1002; + int number2 = 999; - @Test - void findCloserToShouldReturnNUmber2IfItCloserToGoalThanNumber1() { - // given - int number1 = 1002; - int number2 = 999; + // when + boolean actual = bcCryptWorkFactorService.isPreviousDurationCloserToGoal(number1, number2); - // when - boolean actual = bcCryptWorkFactorService.isPreviousDurationCloserToGoal(number1, number2); + // then + assertThat(actual).isFalse(); + } - // then - assertThat(actual).isFalse(); - } + @Test + void findCloserToShouldReturnGoalIfNumber2IsEqualGoal() { + // given + int number1 = 999; + int number2 = 1000; - @Test - void findCloserToShouldReturnGoalIfNumber2IsEqualGoal() { - // given - int number1 = 999; - int number2 = 1000; + // when + boolean actual = bcCryptWorkFactorService.isPreviousDurationCloserToGoal(number1, number2); - // when - boolean actual = bcCryptWorkFactorService.isPreviousDurationCloserToGoal(number1, number2); + // then + assertThat(actual).isFalse(); + } - // then - assertThat(actual).isFalse(); - } + @Test + void findCloserToShouldReturnGoalIfNumber1IsEqualGoal() { + // given + int number1 = 1000; + int number2 = 1001; - @Test - void findCloserToShouldReturnGoalIfNumber1IsEqualGoal() { - // given - int number1 = 1000; - int number2 = 1001; + // when + boolean actual = bcCryptWorkFactorService.isPreviousDurationCloserToGoal(number1, number2); - // when - boolean actual = bcCryptWorkFactorService.isPreviousDurationCloserToGoal(number1, number2); + // then + assertThat(actual).isTrue(); + } - // then - assertThat(actual).isTrue(); - } + @Test + void getStrengthShouldReturn4IfStrengthIs4() { + // given + int currentStrength = 4; - @Test - void getStrengthShouldReturn4IfStrengthIs4() { - // given - int currentStrength = 4; + // when + int actual = bcCryptWorkFactorService.getStrength(0, 0, currentStrength); - // when - int actual = bcCryptWorkFactorService.getStrength(0, 0, currentStrength); + // then + assertThat(actual).isEqualTo(4); + } - // then - assertThat(actual).isEqualTo(4); - } + @Test + void getStrengthShouldReturnPreviousStrengthIfPreviousDurationCloserToGoal() { + // given - @Test - void getStrengthShouldReturnPreviousStrengthIfPreviousDurationCloserToGoal() { - // given + // when + int actual = bcCryptWorkFactorService.getStrength(980, 1021, 5); - // when - int actual = bcCryptWorkFactorService.getStrength(980, 1021, 5); + // then + assertThat(actual).isEqualTo(4); + } - // then - assertThat(actual).isEqualTo(4); - } + @Test + void getStrengthShouldReturnCurrentStrengthIfCurrentDurationCloserToGoal() { + // given - @Test - void getStrengthShouldReturnCurrentStrengthIfCurrentDurationCloserToGoal() { - // given + // when + int actual = bcCryptWorkFactorService.getStrength(960, 1021, 5); - // when - int actual = bcCryptWorkFactorService.getStrength(960, 1021, 5); - - // then - assertThat(actual).isEqualTo(5); - } -} \ No newline at end of file + // then + assertThat(actual).isEqualTo(5); + } +} diff --git a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/workfactor/Pbkdf2WorkFactorServiceTest.java b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/workfactor/Pbkdf2WorkFactorServiceTest.java index 49f5447..c0b2a59 100644 --- a/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/workfactor/Pbkdf2WorkFactorServiceTest.java +++ b/spring-boot/password-encoding/src/test/java/io/reflectoring/passwordencoding/workfactor/Pbkdf2WorkFactorServiceTest.java @@ -6,17 +6,16 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class Pbkdf2WorkFactorServiceTest { + private Pbkdf2WorkFactorService pbkdf2WorkFactorService = new Pbkdf2WorkFactorService(); - private Pbkdf2WorkFactorService pbkdf2WorkFactorService = new Pbkdf2WorkFactorService(); + @Test + void calculateIteration() { + // given - @Test - void calculateIteration() { - // given + // when + int iterationNumber = pbkdf2WorkFactorService.calculateIteration(); - // when - int iterationNumber = pbkdf2WorkFactorService.calculateIteration(); - - // then - assertThat(iterationNumber).isGreaterThanOrEqualTo(150000); - } -} \ No newline at end of file + // then + assertThat(iterationNumber).isGreaterThanOrEqualTo(150000); + } +}