mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-28 23:02:15 +00:00
SEC-1890: Add checks for validity of stored bcrypt hash
When checking for a match, the BCryptPasswordEncoder validates the stored hash against a pattern to check that it actually is a bcrypt value.
This commit is contained in:
parent
5d71d2a4fa
commit
3760d792ea
@ -16,6 +16,7 @@
|
|||||||
package org.springframework.security.crypto.bcrypt;
|
package org.springframework.security.crypto.bcrypt;
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ import org.springframework.security.crypto.password.PasswordEncoder;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class BCryptPasswordEncoder implements PasswordEncoder {
|
public class BCryptPasswordEncoder implements PasswordEncoder {
|
||||||
|
private Pattern BCRYPT_PATTERN = Pattern.compile("\\A\\$2a?\\$\\d\\d\\$[./0-9A-Za-z]{53}");
|
||||||
|
|
||||||
private final int strength;
|
private final int strength;
|
||||||
|
|
||||||
@ -71,7 +73,14 @@ public class BCryptPasswordEncoder implements PasswordEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
||||||
return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
|
if (encodedPassword == null || encodedPassword.length() == 0) {
|
||||||
|
throw new IllegalArgumentException("Encoded password cannot be null or empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
|
||||||
|
throw new IllegalArgumentException("Encoded password does not look like BCrypt");
|
||||||
|
}
|
||||||
|
|
||||||
|
return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ import static org.junit.Assert.assertTrue;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
@ -43,13 +45,6 @@ public class BCryptPasswordEncoderTests {
|
|||||||
assertTrue(encoder.matches("passw\u9292rd", result));
|
assertTrue(encoder.matches("passw\u9292rd", result));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void matchesLengthChecked() {
|
|
||||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
|
||||||
String result = encoder.encode("password");
|
|
||||||
assertFalse(encoder.matches("password", result.substring(0,result.length()-2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void notMatches() {
|
public void notMatches() {
|
||||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||||
@ -57,4 +52,43 @@ public class BCryptPasswordEncoderTests {
|
|||||||
assertFalse(encoder.matches("bogus", result));
|
assertFalse(encoder.matches("bogus", result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void customStrength() {
|
||||||
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(8);
|
||||||
|
String result = encoder.encode("password");
|
||||||
|
assertTrue(encoder.matches("password", result));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void customRandom() {
|
||||||
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(8, new SecureRandom());
|
||||||
|
String result = encoder.encode("password");
|
||||||
|
assertTrue(encoder.matches("password", result));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void barfsOnNullEncodedValue() {
|
||||||
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||||
|
assertFalse(encoder.matches("password", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void barfsOnEmptyEncodedValue() {
|
||||||
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||||
|
assertFalse(encoder.matches("password", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void barfsOnShortEncodedValue() {
|
||||||
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||||
|
String result = encoder.encode("password");
|
||||||
|
assertFalse(encoder.matches("password", result.substring(0, 4)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void barfsOnBogusEncodedValue() {
|
||||||
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||||
|
assertFalse(encoder.matches("password", "012345678901234567890123456789"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user