#1188 Create and keep encryption method instance (#1191)

- Avoid creating the same object over and over; instead keep it and only change it on settings reload
This commit is contained in:
ljacqu
2017-04-30 17:41:51 +02:00
committed by Gabriele C
parent e0e4cd112d
commit c803822fa8
5 changed files with 35 additions and 48 deletions
@@ -1,7 +1,6 @@
package fr.xephi.authme.events;
import fr.xephi.authme.security.crypts.EncryptionMethod;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
/**
@@ -13,22 +12,19 @@ public class PasswordEncryptionEvent extends CustomEvent {
private static final HandlerList handlers = new HandlerList();
private EncryptionMethod method;
private String playerName;
/**
* Constructor.
*
* @param method The method used to encrypt the password
* @param playerName The name of the player
*/
public PasswordEncryptionEvent(EncryptionMethod method, String playerName) {
public PasswordEncryptionEvent(EncryptionMethod method) {
super(false);
this.method = method;
this.playerName = playerName;
}
/**
* Return the list of handlers, equivalent to {@link #getHandlers()} and required by {@link Event}.
* Return the list of handlers, equivalent to {@link #getHandlers()} and required by {@link org.bukkit.event.Event}.
*
* @return The list of handlers
*/
@@ -58,14 +54,4 @@ public class PasswordEncryptionEvent extends CustomEvent {
public void setMethod(EncryptionMethod method) {
this.method = method;
}
/**
* Return the name of the player the event has been fired for.
*
* @return The player name
*/
public String getPlayerName() {
return playerName;
}
}
@@ -29,9 +29,9 @@ public class PasswordSecurity implements Reloadable {
private PluginManager pluginManager;
@Inject
private Factory<EncryptionMethod> hashAlgorithmFactory;
private Factory<EncryptionMethod> encryptionMethodFactory;
private HashAlgorithm algorithm;
private EncryptionMethod encryptionMethod;
private Collection<HashAlgorithm> legacyAlgorithms;
/**
@@ -40,7 +40,8 @@ public class PasswordSecurity implements Reloadable {
@PostConstruct
@Override
public void reload() {
this.algorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
HashAlgorithm algorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
this.encryptionMethod = initializeEncryptionMethodWithEvent(algorithm);
this.legacyAlgorithms = settings.getProperty(SecuritySettings.LEGACY_HASHES);
}
@@ -54,8 +55,7 @@ public class PasswordSecurity implements Reloadable {
*/
public HashedPassword computeHash(String password, String playerName) {
String playerLowerCase = playerName.toLowerCase();
EncryptionMethod method = initializeEncryptionMethodWithEvent(algorithm, playerLowerCase);
return method.computeHash(password, playerLowerCase);
return encryptionMethod.computeHash(password, playerLowerCase);
}
/**
@@ -81,14 +81,13 @@ public class PasswordSecurity implements Reloadable {
* @return True if the password matches, false otherwise
*/
public boolean comparePassword(String password, HashedPassword hashedPassword, String playerName) {
EncryptionMethod method = initializeEncryptionMethodWithEvent(algorithm, playerName);
String playerLowerCase = playerName.toLowerCase();
return methodMatches(method, password, hashedPassword, playerLowerCase)
return methodMatches(encryptionMethod, password, hashedPassword, playerLowerCase)
|| compareWithLegacyHashes(password, hashedPassword, playerLowerCase);
}
/**
* Compare the given hash with all available encryption methods to support
* Compare the given hash with the configured legacy encryption methods to support
* the migration to a new encryption method. Upon a successful match, the password
* will be hashed with the new encryption method and persisted.
*
@@ -96,13 +95,13 @@ public class PasswordSecurity implements Reloadable {
* @param hashedPassword The encrypted password to test the clear-text password against
* @param playerName The name of the player
*
* @return True if there was a password match with another encryption method, false otherwise
* @return True if there was a password match with a configured legacy encryption method, false otherwise
*/
private boolean compareWithLegacyHashes(String password, HashedPassword hashedPassword, String playerName) {
for (HashAlgorithm algorithm : legacyAlgorithms) {
EncryptionMethod method = initializeEncryptionMethod(algorithm);
if (methodMatches(method, password, hashedPassword, playerName)) {
hashPasswordForNewAlgorithm(password, playerName);
hashAndSavePasswordWithNewAlgorithm(password, playerName);
return true;
}
}
@@ -132,13 +131,12 @@ public class PasswordSecurity implements Reloadable {
* which may have been changed by an external listener.
*
* @param algorithm The algorithm to retrieve the encryption method for
* @param playerName The name of the player a password will be hashed for
*
* @return The encryption method
*/
private EncryptionMethod initializeEncryptionMethodWithEvent(HashAlgorithm algorithm, String playerName) {
private EncryptionMethod initializeEncryptionMethodWithEvent(HashAlgorithm algorithm) {
EncryptionMethod method = initializeEncryptionMethod(algorithm);
PasswordEncryptionEvent event = new PasswordEncryptionEvent(method, playerName);
PasswordEncryptionEvent event = new PasswordEncryptionEvent(method);
pluginManager.callEvent(event);
return event.getMethod();
}
@@ -154,12 +152,11 @@ public class PasswordSecurity implements Reloadable {
if (HashAlgorithm.CUSTOM.equals(algorithm) || HashAlgorithm.PLAINTEXT.equals(algorithm)) {
return null;
}
return hashAlgorithmFactory.newInstance(algorithm.getClazz());
return encryptionMethodFactory.newInstance(algorithm.getClazz());
}
private void hashPasswordForNewAlgorithm(String password, String playerName) {
HashedPassword hashedPassword = initializeEncryptionMethodWithEvent(algorithm, playerName)
.computeHash(password, playerName);
private void hashAndSavePasswordWithNewAlgorithm(String password, String playerName) {
HashedPassword hashedPassword = encryptionMethod.computeHash(password, playerName);
dataSource.updatePassword(playerName, hashedPassword);
}
@@ -61,10 +61,6 @@ public final class SecuritySettings implements SettingsHolder {
public static final Property<HashAlgorithm> PASSWORD_HASH =
newProperty(HashAlgorithm.class, "settings.security.passwordHash", HashAlgorithm.SHA256);
@Comment("Salt length for the SALTED2MD5 MD5(MD5(password)+salt)")
public static final Property<Integer> DOUBLE_MD5_SALT_LENGTH =
newProperty("settings.security.doubleMD5SaltLength", 8);
@Comment({
"If a password check fails, AuthMe will also try to check with the following hash methods.",
"Use this setting when you change from one hash method to another.",
@@ -75,6 +71,10 @@ public final class SecuritySettings implements SettingsHolder {
public static final Property<Set<HashAlgorithm>> LEGACY_HASHES =
new EnumSetProperty<>(HashAlgorithm.class, "settings.security.legacyHashes");
@Comment("Salt length for the SALTED2MD5 MD5(MD5(password)+salt)")
public static final Property<Integer> DOUBLE_MD5_SALT_LENGTH =
newProperty("settings.security.doubleMD5SaltLength", 8);
@Comment("Number of rounds to use if passwordHash is set to PBKDF2. Default is 10000")
public static final Property<Integer> PBKDF2_NUMBER_OF_ROUNDS =
newProperty("settings.security.pbkdf2Rounds", 10000);