Allow upgrading between different SCrypt encodings

Fixes gh-7057
This commit is contained in:
Lars Grefer 2019-06-28 23:41:51 +02:00 committed by Rob Winch
parent 742df2cd1d
commit e95effc839
2 changed files with 54 additions and 0 deletions

View File

@ -135,6 +135,30 @@ public class SCryptPasswordEncoder implements PasswordEncoder {
return decodeAndCheckMatches(rawPassword, encodedPassword);
}
@Override
public boolean upgradeEncoding(String encodedPassword) {
if (encodedPassword == null || encodedPassword.isEmpty()) {
return false;
}
String[] parts = encodedPassword.split("\\$");
if (parts.length != 4) {
throw new IllegalArgumentException("Encoded password does not look like SCrypt: " + encodedPassword);
}
long params = Long.parseLong(parts[1], 16);
int cpuCost = (int) Math.pow(2, params >> 16 & 0xffff);
int memoryCost = (int) params >> 8 & 0xff;
int parallelization = (int) params & 0xff;
return cpuCost < this.cpuCost
|| memoryCost < this.memoryCost
|| parallelization < this.parallelization;
}
private boolean decodeAndCheckMatches(CharSequence rawPassword, String encodedPassword) {
String[] parts = encodedPassword.split("\\$");

View File

@ -116,5 +116,35 @@ public class SCryptPasswordEncoderTests {
new SCryptPasswordEncoder(2, 8, 1, -1, 16);
}
@Test
public void upgradeEncoding_nullOrEmptyInput() {
SCryptPasswordEncoder encoder = new SCryptPasswordEncoder();
assertThat(encoder.upgradeEncoding(null)).isFalse();
assertThat(encoder.upgradeEncoding("")).isFalse();
}
@Test
public void upgradeEncoding_sameEncoder() {
SCryptPasswordEncoder encoder = new SCryptPasswordEncoder();
String encoded = encoder.encode("password");
assertThat(encoder.upgradeEncoding(encoded)).isFalse();
}
@Test
public void upgradeEncoding_weakerToStronger() {
SCryptPasswordEncoder weakEncoder = new SCryptPasswordEncoder((int) Math.pow(2, 10), 4, 1, 32, 64);
SCryptPasswordEncoder strongEncoder = new SCryptPasswordEncoder((int) Math.pow(2, 16), 8, 1, 32, 64);
String weakPassword = weakEncoder.encode("password");
String strongPassword = strongEncoder.encode("password");
assertThat(strongEncoder.upgradeEncoding(weakPassword)).isTrue();
assertThat(weakEncoder.upgradeEncoding(strongPassword)).isFalse();
}
@Test(expected = IllegalArgumentException.class)
public void upgradeEncoding_invalidInput() {
new SCryptPasswordEncoder().upgradeEncoding("not-a-scrypt-password");
}
}