#358 Handle hash + salt as one "unit"
- Rename HashResult to EncryptedPassword to reflect its broader use - Use EncryptedPassword in methods that require the hash and the salt, instead of passing them as strings separately - Store EncryptedPassword as field in PlayerAuth; updatePassword() thus processes the entire data in the EncryptedPassword object
This commit is contained in:
parent
9c4a578bec
commit
a3402d573f
@ -43,7 +43,7 @@ import fr.xephi.authme.permission.PlayerPermission;
|
|||||||
import fr.xephi.authme.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
import fr.xephi.authme.security.HashAlgorithm;
|
import fr.xephi.authme.security.HashAlgorithm;
|
||||||
import fr.xephi.authme.security.PasswordSecurity;
|
import fr.xephi.authme.security.PasswordSecurity;
|
||||||
import fr.xephi.authme.security.crypts.HashResult;
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.settings.OtherAccounts;
|
import fr.xephi.authme.settings.OtherAccounts;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.Spawn;
|
import fr.xephi.authme.settings.Spawn;
|
||||||
@ -592,8 +592,9 @@ public class AuthMe extends JavaPlugin {
|
|||||||
ConsoleLogger.showError("Your HashAlgorithm has been detected as plaintext and is now deprecated; " +
|
ConsoleLogger.showError("Your HashAlgorithm has been detected as plaintext and is now deprecated; " +
|
||||||
"it will be changed and hashed now to the AuthMe default hashing method");
|
"it will be changed and hashed now to the AuthMe default hashing method");
|
||||||
for (PlayerAuth auth : database.getAllAuths()) {
|
for (PlayerAuth auth : database.getAllAuths()) {
|
||||||
HashResult hashResult = passwordSecurity.computeHash(HashAlgorithm.SHA256, auth.getHash(), auth.getNickname());
|
EncryptedPassword encryptedPassword = passwordSecurity.computeHash(
|
||||||
auth.setHash(hashResult.getHash());
|
HashAlgorithm.SHA256, auth.getPassword().getHash(), auth.getNickname());
|
||||||
|
auth.setPassword(encryptedPassword);
|
||||||
database.updatePassword(auth);
|
database.updatePassword(auth);
|
||||||
}
|
}
|
||||||
Settings.setValue("settings.security.passwordHash", "SHA256");
|
Settings.setValue("settings.security.passwordHash", "SHA256");
|
||||||
|
|||||||
@ -4,8 +4,7 @@ import fr.xephi.authme.AuthMe;
|
|||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.cache.auth.PlayerCache;
|
import fr.xephi.authme.cache.auth.PlayerCache;
|
||||||
import fr.xephi.authme.security.PasswordSecurity;
|
import fr.xephi.authme.security.PasswordSecurity;
|
||||||
import fr.xephi.authme.security.crypts.HashResult;
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.settings.Settings;
|
|
||||||
import fr.xephi.authme.util.Utils;
|
import fr.xephi.authme.util.Utils;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
@ -135,13 +134,13 @@ public class API {
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
public static boolean registerPlayer(String playerName, String password) {
|
public static boolean registerPlayer(String playerName, String password) {
|
||||||
String name = playerName.toLowerCase();
|
String name = playerName.toLowerCase();
|
||||||
HashResult hashResult = passwordSecurity.computeHash(Settings.getPasswordHash, password, name);
|
EncryptedPassword encryptedPassword = passwordSecurity.computeHash(password, name);
|
||||||
if (isRegistered(name)) {
|
if (isRegistered(name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PlayerAuth auth = PlayerAuth.builder()
|
PlayerAuth auth = PlayerAuth.builder()
|
||||||
.name(name)
|
.name(name)
|
||||||
.hash(hashResult.getHash())
|
.hash(encryptedPassword)
|
||||||
.lastLogin(0)
|
.lastLogin(0)
|
||||||
.realName(playerName)
|
.realName(playerName)
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package fr.xephi.authme.api;
|
|||||||
import fr.xephi.authme.AuthMe;
|
import fr.xephi.authme.AuthMe;
|
||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.cache.auth.PlayerCache;
|
import fr.xephi.authme.cache.auth.PlayerCache;
|
||||||
import fr.xephi.authme.security.crypts.HashResult;
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.util.Utils;
|
import fr.xephi.authme.util.Utils;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
@ -149,14 +149,13 @@ public class NewAPI {
|
|||||||
*/
|
*/
|
||||||
public boolean registerPlayer(String playerName, String password) {
|
public boolean registerPlayer(String playerName, String password) {
|
||||||
String name = playerName.toLowerCase();
|
String name = playerName.toLowerCase();
|
||||||
HashResult result = plugin.getPasswordSecurity().computeHash(password, name);
|
EncryptedPassword result = plugin.getPasswordSecurity().computeHash(password, name);
|
||||||
if (isRegistered(name)) {
|
if (isRegistered(name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PlayerAuth auth = PlayerAuth.builder()
|
PlayerAuth auth = PlayerAuth.builder()
|
||||||
.name(name)
|
.name(name)
|
||||||
.hash(result.getHash())
|
.hash(result)
|
||||||
.salt(result.getSalt())
|
|
||||||
.realName(playerName)
|
.realName(playerName)
|
||||||
.build();
|
.build();
|
||||||
return plugin.getDataSource().saveAuth(auth);
|
return plugin.getDataSource().saveAuth(auth);
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
package fr.xephi.authme.cache.auth;
|
package fr.xephi.authme.cache.auth;
|
||||||
|
|
||||||
import fr.xephi.authme.security.HashAlgorithm;
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.settings.Settings;
|
|
||||||
|
|
||||||
import static com.google.common.base.Objects.firstNonNull;
|
import static com.google.common.base.Objects.firstNonNull;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Strings.nullToEmpty;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -13,14 +11,13 @@ import static com.google.common.base.Strings.nullToEmpty;
|
|||||||
public class PlayerAuth {
|
public class PlayerAuth {
|
||||||
|
|
||||||
private String nickname;
|
private String nickname;
|
||||||
private String hash;
|
private EncryptedPassword password;
|
||||||
private String ip;
|
private String ip;
|
||||||
private long lastLogin;
|
private long lastLogin;
|
||||||
private double x;
|
private double x;
|
||||||
private double y;
|
private double y;
|
||||||
private double z;
|
private double z;
|
||||||
private String world;
|
private String world;
|
||||||
private String salt;
|
|
||||||
private int groupId;
|
private int groupId;
|
||||||
private String email;
|
private String email;
|
||||||
private String realName;
|
private String realName;
|
||||||
@ -41,7 +38,7 @@ public class PlayerAuth {
|
|||||||
* @param realName String
|
* @param realName String
|
||||||
*/
|
*/
|
||||||
public PlayerAuth(String nickname, String ip, long lastLogin, String realName) {
|
public PlayerAuth(String nickname, String ip, long lastLogin, String realName) {
|
||||||
this(nickname, "", "", -1, ip, lastLogin, 0, 0, 0, "world", "your@email.com", realName);
|
this(nickname, new EncryptedPassword(""), -1, ip, lastLogin, 0, 0, 0, "world", "your@email.com", realName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,7 +52,8 @@ public class PlayerAuth {
|
|||||||
* @param realName String
|
* @param realName String
|
||||||
*/
|
*/
|
||||||
public PlayerAuth(String nickname, double x, double y, double z, String world, String realName) {
|
public PlayerAuth(String nickname, double x, double y, double z, String world, String realName) {
|
||||||
this(nickname, "", "", -1, "127.0.0.1", System.currentTimeMillis(), x, y, z, world, "your@email.com", realName);
|
this(nickname, new EncryptedPassword(""), -1, "127.0.0.1", System.currentTimeMillis(), x, y, z, world,
|
||||||
|
"your@email.com", realName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,7 +66,7 @@ public class PlayerAuth {
|
|||||||
* @param realName String
|
* @param realName String
|
||||||
*/
|
*/
|
||||||
public PlayerAuth(String nickname, String hash, String ip, long lastLogin, String realName) {
|
public PlayerAuth(String nickname, String hash, String ip, long lastLogin, String realName) {
|
||||||
this(nickname, hash, "", -1, ip, lastLogin, 0, 0, 0, "world", "your@email.com", realName);
|
this(nickname, new EncryptedPassword(hash), -1, ip, lastLogin, 0, 0, 0, "world", "your@email.com", realName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,7 +80,7 @@ public class PlayerAuth {
|
|||||||
* @param realName String
|
* @param realName String
|
||||||
*/
|
*/
|
||||||
public PlayerAuth(String nickname, String hash, String ip, long lastLogin, String email, String realName) {
|
public PlayerAuth(String nickname, String hash, String ip, long lastLogin, String email, String realName) {
|
||||||
this(nickname, hash, "", -1, ip, lastLogin, 0, 0, 0, "world", email, realName);
|
this(nickname, new EncryptedPassword(hash), -1, ip, lastLogin, 0, 0, 0, "world", email, realName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,7 +94,7 @@ public class PlayerAuth {
|
|||||||
* @param realName String
|
* @param realName String
|
||||||
*/
|
*/
|
||||||
public PlayerAuth(String nickname, String hash, String salt, String ip, long lastLogin, String realName) {
|
public PlayerAuth(String nickname, String hash, String salt, String ip, long lastLogin, String realName) {
|
||||||
this(nickname, hash, salt, -1, ip, lastLogin, 0, 0, 0, "world", "your@email.com", realName);
|
this(nickname, new EncryptedPassword(hash, salt), -1, ip, lastLogin, 0, 0, 0, "world", "your@email.com", realName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,8 +111,9 @@ public class PlayerAuth {
|
|||||||
* @param email String
|
* @param email String
|
||||||
* @param realName String
|
* @param realName String
|
||||||
*/
|
*/
|
||||||
public PlayerAuth(String nickname, String hash, String ip, long lastLogin, double x, double y, double z, String world, String email, String realName) {
|
public PlayerAuth(String nickname, String hash, String ip, long lastLogin, double x, double y, double z,
|
||||||
this(nickname, hash, "", -1, ip, lastLogin, x, y, z, world, email, realName);
|
String world, String email, String realName) {
|
||||||
|
this(nickname, new EncryptedPassword(hash), -1, ip, lastLogin, x, y, z, world, email, realName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -132,8 +131,10 @@ public class PlayerAuth {
|
|||||||
* @param email String
|
* @param email String
|
||||||
* @param realName String
|
* @param realName String
|
||||||
*/
|
*/
|
||||||
public PlayerAuth(String nickname, String hash, String salt, String ip, long lastLogin, double x, double y, double z, String world, String email, String realName) {
|
public PlayerAuth(String nickname, String hash, String salt, String ip, long lastLogin, double x, double y,
|
||||||
this(nickname, hash, salt, -1, ip, lastLogin, x, y, z, world, email, realName);
|
double z, String world, String email, String realName) {
|
||||||
|
this(nickname, new EncryptedPassword(hash, salt), -1, ip, lastLogin,
|
||||||
|
x, y, z, world, email, realName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -147,38 +148,37 @@ public class PlayerAuth {
|
|||||||
* @param lastLogin long
|
* @param lastLogin long
|
||||||
* @param realName String
|
* @param realName String
|
||||||
*/
|
*/
|
||||||
public PlayerAuth(String nickname, String hash, String salt, int groupId, String ip, long lastLogin, String realName) {
|
|
||||||
this(nickname, hash, salt, groupId, ip, lastLogin, 0, 0, 0, "world", "your@email.com", realName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for PlayerAuth.
|
|
||||||
*
|
|
||||||
* @param nickname String
|
|
||||||
* @param hash String
|
|
||||||
* @param salt String
|
|
||||||
* @param groupId int
|
|
||||||
* @param ip String
|
|
||||||
* @param lastLogin long
|
|
||||||
* @param x double
|
|
||||||
* @param y double
|
|
||||||
* @param z double
|
|
||||||
* @param world String
|
|
||||||
* @param email String
|
|
||||||
* @param realName String
|
|
||||||
*/
|
|
||||||
public PlayerAuth(String nickname, String hash, String salt, int groupId, String ip,
|
public PlayerAuth(String nickname, String hash, String salt, int groupId, String ip,
|
||||||
long lastLogin, double x, double y, double z, String world, String email,
|
long lastLogin, String realName) {
|
||||||
String realName) {
|
this(nickname, new EncryptedPassword(hash, salt), groupId, ip, lastLogin,
|
||||||
|
0, 0, 0, "world", "your@email.com", realName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for PlayerAuth.
|
||||||
|
*
|
||||||
|
* @param nickname String
|
||||||
|
* @param password String
|
||||||
|
* @param groupId int
|
||||||
|
* @param ip String
|
||||||
|
* @param lastLogin long
|
||||||
|
* @param x double
|
||||||
|
* @param y double
|
||||||
|
* @param z double
|
||||||
|
* @param world String
|
||||||
|
* @param email String
|
||||||
|
* @param realName String
|
||||||
|
*/
|
||||||
|
public PlayerAuth(String nickname, EncryptedPassword password, int groupId, String ip, long lastLogin,
|
||||||
|
double x, double y, double z, String world, String email, String realName) {
|
||||||
this.nickname = nickname.toLowerCase();
|
this.nickname = nickname.toLowerCase();
|
||||||
this.hash = hash;
|
this.password = password;
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
this.lastLogin = lastLogin;
|
this.lastLogin = lastLogin;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
this.world = world;
|
this.world = world;
|
||||||
this.salt = salt;
|
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.realName = realName;
|
this.realName = realName;
|
||||||
@ -191,237 +191,108 @@ public class PlayerAuth {
|
|||||||
*/
|
*/
|
||||||
public void set(PlayerAuth auth) {
|
public void set(PlayerAuth auth) {
|
||||||
this.setEmail(auth.getEmail());
|
this.setEmail(auth.getEmail());
|
||||||
this.setHash(auth.getHash());
|
this.setPassword(auth.getPassword());
|
||||||
this.setIp(auth.getIp());
|
this.setIp(auth.getIp());
|
||||||
this.setLastLogin(auth.getLastLogin());
|
this.setLastLogin(auth.getLastLogin());
|
||||||
this.setNickname(auth.getNickname());
|
this.setNickname(auth.getNickname());
|
||||||
this.setQuitLocX(auth.getQuitLocX());
|
this.setQuitLocX(auth.getQuitLocX());
|
||||||
this.setQuitLocY(auth.getQuitLocY());
|
this.setQuitLocY(auth.getQuitLocY());
|
||||||
this.setQuitLocZ(auth.getQuitLocZ());
|
this.setQuitLocZ(auth.getQuitLocZ());
|
||||||
this.setSalt(auth.getSalt());
|
|
||||||
this.setWorld(auth.getWorld());
|
this.setWorld(auth.getWorld());
|
||||||
this.setRealName(auth.getRealName());
|
this.setRealName(auth.getRealName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setNickname.
|
|
||||||
*
|
|
||||||
* @param nickname String
|
|
||||||
*/
|
|
||||||
public void setNickname(String nickname) {
|
public void setNickname(String nickname) {
|
||||||
this.nickname = nickname.toLowerCase();
|
this.nickname = nickname.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getNickname.
|
|
||||||
*
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String getNickname() {
|
public String getNickname() {
|
||||||
return nickname;
|
return nickname;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getRealName.
|
|
||||||
*
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String getRealName() {
|
public String getRealName() {
|
||||||
return realName;
|
return realName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setRealName.
|
|
||||||
*
|
|
||||||
* @param realName String
|
|
||||||
*/
|
|
||||||
public void setRealName(String realName) {
|
public void setRealName(String realName) {
|
||||||
this.realName = realName;
|
this.realName = realName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getGroupId.
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public int getGroupId() {
|
public int getGroupId() {
|
||||||
return groupId;
|
return groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getQuitLocX.
|
|
||||||
*
|
|
||||||
* @return double
|
|
||||||
*/
|
|
||||||
public double getQuitLocX() {
|
public double getQuitLocX() {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setQuitLocX.
|
|
||||||
*
|
|
||||||
* @param d double
|
|
||||||
*/
|
|
||||||
public void setQuitLocX(double d) {
|
public void setQuitLocX(double d) {
|
||||||
this.x = d;
|
this.x = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getQuitLocY.
|
|
||||||
*
|
|
||||||
* @return double
|
|
||||||
*/
|
|
||||||
public double getQuitLocY() {
|
public double getQuitLocY() {
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setQuitLocY.
|
|
||||||
*
|
|
||||||
* @param d double
|
|
||||||
*/
|
|
||||||
public void setQuitLocY(double d) {
|
public void setQuitLocY(double d) {
|
||||||
this.y = d;
|
this.y = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getQuitLocZ.
|
|
||||||
*
|
|
||||||
* @return double
|
|
||||||
*/
|
|
||||||
public double getQuitLocZ() {
|
public double getQuitLocZ() {
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setQuitLocZ.
|
|
||||||
*
|
|
||||||
* @param d double
|
|
||||||
*/
|
|
||||||
public void setQuitLocZ(double d) {
|
public void setQuitLocZ(double d) {
|
||||||
this.z = d;
|
this.z = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getWorld.
|
|
||||||
*
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String getWorld() {
|
public String getWorld() {
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setWorld.
|
|
||||||
*
|
|
||||||
* @param world String
|
|
||||||
*/
|
|
||||||
public void setWorld(String world) {
|
public void setWorld(String world) {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getIp.
|
|
||||||
*
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String getIp() {
|
public String getIp() {
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setIp.
|
|
||||||
*
|
|
||||||
* @param ip String
|
|
||||||
*/
|
|
||||||
public void setIp(String ip) {
|
public void setIp(String ip) {
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getLastLogin.
|
|
||||||
*
|
|
||||||
* @return long
|
|
||||||
*/
|
|
||||||
public long getLastLogin() {
|
public long getLastLogin() {
|
||||||
return lastLogin;
|
return lastLogin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setLastLogin.
|
|
||||||
*
|
|
||||||
* @param lastLogin long
|
|
||||||
*/
|
|
||||||
public void setLastLogin(long lastLogin) {
|
public void setLastLogin(long lastLogin) {
|
||||||
this.lastLogin = lastLogin;
|
this.lastLogin = lastLogin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getEmail.
|
|
||||||
*
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String getEmail() {
|
public String getEmail() {
|
||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setEmail.
|
|
||||||
*
|
|
||||||
* @param email String
|
|
||||||
*/
|
|
||||||
public void setEmail(String email) {
|
public void setEmail(String email) {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public EncryptedPassword getPassword() {
|
||||||
* Method getSalt.
|
// TODO #358: Check whether this check is really necessary. It's been here since the first commit.
|
||||||
*
|
/*if (Settings.getPasswordHash == HashAlgorithm.MD5VB) {
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String getSalt() {
|
|
||||||
return this.salt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setSalt.
|
|
||||||
*
|
|
||||||
* @param salt String
|
|
||||||
*/
|
|
||||||
public void setSalt(String salt) {
|
|
||||||
this.salt = salt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getHash.
|
|
||||||
*
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String getHash() {
|
|
||||||
if (Settings.getPasswordHash == HashAlgorithm.MD5VB) {
|
|
||||||
if (salt != null && !salt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.MD5VB) {
|
if (salt != null && !salt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.MD5VB) {
|
||||||
return "$MD5vb$" + salt + "$" + hash;
|
return "$MD5vb$" + salt + "$" + hash;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
return hash;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void setPassword(EncryptedPassword password) {
|
||||||
* Method setHash.
|
this.password = password;
|
||||||
*
|
|
||||||
* @param hash String
|
|
||||||
*/
|
|
||||||
public void setHash(String hash) {
|
|
||||||
this.hash = hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method equals.
|
|
||||||
*
|
|
||||||
* @param obj Object
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (!(obj instanceof PlayerAuth)) {
|
if (!(obj instanceof PlayerAuth)) {
|
||||||
@ -431,11 +302,6 @@ public class PlayerAuth {
|
|||||||
return other.getIp().equals(this.ip) && other.getNickname().equals(this.nickname);
|
return other.getIp().equals(this.ip) && other.getNickname().equals(this.nickname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method hashCode.
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int hashCode = 7;
|
int hashCode = 7;
|
||||||
@ -444,20 +310,14 @@ public class PlayerAuth {
|
|||||||
return hashCode;
|
return hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method toString.
|
|
||||||
*
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return ("Player : " + nickname + " | " + realName
|
return "Player : " + nickname + " | " + realName
|
||||||
+ " ! IP : " + ip
|
+ " ! IP : " + ip
|
||||||
+ " ! LastLogin : " + lastLogin
|
+ " ! LastLogin : " + lastLogin
|
||||||
+ " ! LastPosition : " + x + "," + y + "," + z + "," + world
|
+ " ! LastPosition : " + x + "," + y + "," + z + "," + world
|
||||||
+ " ! Email : " + email
|
+ " ! Email : " + email
|
||||||
+ " ! Hash : " + hash
|
+ " ! Hash : {" + password.getHash() + ", " + password.getSalt() + "}";
|
||||||
+ " ! Salt : " + salt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -472,8 +332,8 @@ public class PlayerAuth {
|
|||||||
str.append(this.realName).append(d);
|
str.append(this.realName).append(d);
|
||||||
str.append(this.ip).append(d);
|
str.append(this.ip).append(d);
|
||||||
str.append(this.email).append(d);
|
str.append(this.email).append(d);
|
||||||
str.append(this.hash).append(d);
|
str.append(this.password.getHash()).append(d);
|
||||||
str.append(this.salt).append(d);
|
str.append(this.password.getSalt()).append(d);
|
||||||
str.append(this.groupId).append(d);
|
str.append(this.groupId).append(d);
|
||||||
str.append(this.lastLogin).append(d);
|
str.append(this.lastLogin).append(d);
|
||||||
str.append(this.world).append(d);
|
str.append(this.world).append(d);
|
||||||
@ -492,8 +352,7 @@ public class PlayerAuth {
|
|||||||
this.realName = args[1];
|
this.realName = args[1];
|
||||||
this.ip = args[2];
|
this.ip = args[2];
|
||||||
this.email = args[3];
|
this.email = args[3];
|
||||||
this.hash = args[4];
|
this.password = new EncryptedPassword(args[4], args[5]);
|
||||||
this.salt = args[5];
|
|
||||||
this.groupId = Integer.parseInt(args[6]);
|
this.groupId = Integer.parseInt(args[6]);
|
||||||
this.lastLogin = Long.parseLong(args[7]);
|
this.lastLogin = Long.parseLong(args[7]);
|
||||||
this.world = args[8];
|
this.world = args[8];
|
||||||
@ -509,8 +368,7 @@ public class PlayerAuth {
|
|||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
private String name;
|
private String name;
|
||||||
private String realName;
|
private String realName;
|
||||||
private String hash;
|
private EncryptedPassword hash;
|
||||||
private String salt;
|
|
||||||
private String ip;
|
private String ip;
|
||||||
private String world;
|
private String world;
|
||||||
private String email;
|
private String email;
|
||||||
@ -523,8 +381,7 @@ public class PlayerAuth {
|
|||||||
public PlayerAuth build() {
|
public PlayerAuth build() {
|
||||||
return new PlayerAuth(
|
return new PlayerAuth(
|
||||||
checkNotNull(name),
|
checkNotNull(name),
|
||||||
nullToEmpty(hash),
|
firstNonNull(hash, new EncryptedPassword("")),
|
||||||
nullToEmpty(salt),
|
|
||||||
groupId,
|
groupId,
|
||||||
firstNonNull(ip, "127.0.0.1"),
|
firstNonNull(ip, "127.0.0.1"),
|
||||||
lastLogin,
|
lastLogin,
|
||||||
@ -545,14 +402,13 @@ public class PlayerAuth {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder hash(String hash) {
|
public Builder hash(EncryptedPassword hash) {
|
||||||
this.hash = hash;
|
this.hash = hash;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder salt(String salt) {
|
public Builder hash(String hash, String salt) {
|
||||||
this.salt = salt;
|
return hash(new EncryptedPassword(hash, salt));
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder ip(String ip) {
|
public Builder ip(String ip) {
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import fr.xephi.authme.command.CommandService;
|
|||||||
import fr.xephi.authme.command.ExecutableCommand;
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.output.MessageKey;
|
import fr.xephi.authme.output.MessageKey;
|
||||||
import fr.xephi.authme.security.crypts.HashResult;
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
@ -68,11 +68,9 @@ public class ChangePasswordAdminCommand implements ExecutableCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO #358: Do we always pass lowercase name?? In that case we need to do that in PasswordSecurity!
|
// TODO #358: Do we always pass lowercase name?? In that case we need to do that in PasswordSecurity!
|
||||||
HashResult hashResult = commandService.getPasswordSecurity().computeHash(playerPass, playerNameLowerCase);
|
EncryptedPassword encryptedPassword = commandService.getPasswordSecurity().computeHash(playerPass, playerNameLowerCase);
|
||||||
auth.setHash(hashResult.getHash());
|
auth.setPassword(encryptedPassword);
|
||||||
auth.setSalt(hashResult.getSalt());
|
|
||||||
|
|
||||||
// TODO #358: updatePassword(auth) needs to update the salt, too.
|
|
||||||
if (!dataSource.updatePassword(auth)) {
|
if (!dataSource.updatePassword(auth)) {
|
||||||
commandService.send(sender, MessageKey.ERROR);
|
commandService.send(sender, MessageKey.ERROR);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import fr.xephi.authme.cache.auth.PlayerAuth;
|
|||||||
import fr.xephi.authme.command.CommandService;
|
import fr.xephi.authme.command.CommandService;
|
||||||
import fr.xephi.authme.command.ExecutableCommand;
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
import fr.xephi.authme.output.MessageKey;
|
import fr.xephi.authme.output.MessageKey;
|
||||||
import fr.xephi.authme.security.crypts.HashResult;
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
@ -57,13 +57,12 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
|||||||
commandService.send(sender, MessageKey.NAME_ALREADY_REGISTERED);
|
commandService.send(sender, MessageKey.NAME_ALREADY_REGISTERED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashResult hashResult = commandService.getPasswordSecurity()
|
EncryptedPassword encryptedPassword = commandService.getPasswordSecurity()
|
||||||
.computeHash(playerPass, playerNameLowerCase);
|
.computeHash(playerPass, playerNameLowerCase);
|
||||||
PlayerAuth auth = PlayerAuth.builder()
|
PlayerAuth auth = PlayerAuth.builder()
|
||||||
.name(playerNameLowerCase)
|
.name(playerNameLowerCase)
|
||||||
.realName(playerName)
|
.realName(playerName)
|
||||||
.hash(hashResult.getHash())
|
.hash(encryptedPassword)
|
||||||
.salt(hashResult.getSalt())
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (!commandService.getDataSource().saveAuth(auth)) {
|
if (!commandService.getDataSource().saveAuth(auth)) {
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import fr.xephi.authme.command.PlayerCommand;
|
|||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.output.MessageKey;
|
import fr.xephi.authme.output.MessageKey;
|
||||||
import fr.xephi.authme.security.RandomString;
|
import fr.xephi.authme.security.RandomString;
|
||||||
import fr.xephi.authme.security.crypts.HashResult;
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.util.StringUtils;
|
import fr.xephi.authme.util.StringUtils;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -37,7 +37,7 @@ public class RecoverEmailCommand extends PlayerCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String thePass = RandomString.generate(Settings.getRecoveryPassLength);
|
String thePass = RandomString.generate(Settings.getRecoveryPassLength);
|
||||||
HashResult hashNew = commandService.getPasswordSecurity().computeHash(thePass, playerName);
|
EncryptedPassword hashNew = commandService.getPasswordSecurity().computeHash(thePass, playerName);
|
||||||
PlayerAuth auth;
|
PlayerAuth auth;
|
||||||
if (PlayerCache.getInstance().isAuthenticated(playerName)) {
|
if (PlayerCache.getInstance().isAuthenticated(playerName)) {
|
||||||
auth = PlayerCache.getInstance().getAuth(playerName);
|
auth = PlayerCache.getInstance().getAuth(playerName);
|
||||||
@ -57,8 +57,7 @@ public class RecoverEmailCommand extends PlayerCommand {
|
|||||||
commandService.send(player, MessageKey.INVALID_EMAIL);
|
commandService.send(player, MessageKey.INVALID_EMAIL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auth.setHash(hashNew.getHash());
|
auth.setPassword(hashNew);
|
||||||
auth.setSalt(hashNew.getSalt());
|
|
||||||
dataSource.updatePassword(auth);
|
dataSource.updatePassword(auth);
|
||||||
plugin.mail.main(auth, thePass);
|
plugin.mail.main(auth, thePass);
|
||||||
commandService.send(player, MessageKey.RECOVERY_EMAIL_SENT_MESSAGE);
|
commandService.send(player, MessageKey.RECOVERY_EMAIL_SENT_MESSAGE);
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import fr.xephi.authme.cache.auth.PlayerAuth;
|
|||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.security.HashAlgorithm;
|
import fr.xephi.authme.security.HashAlgorithm;
|
||||||
import fr.xephi.authme.security.PasswordSecurity;
|
import fr.xephi.authme.security.PasswordSecurity;
|
||||||
import fr.xephi.authme.security.crypts.HashResult;
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ public class RakamakConverter implements Converter {
|
|||||||
File source = new File(Settings.PLUGIN_FOLDER, fileName);
|
File source = new File(Settings.PLUGIN_FOLDER, fileName);
|
||||||
File ipfiles = new File(Settings.PLUGIN_FOLDER, ipFileName);
|
File ipfiles = new File(Settings.PLUGIN_FOLDER, ipFileName);
|
||||||
HashMap<String, String> playerIP = new HashMap<>();
|
HashMap<String, String> playerIP = new HashMap<>();
|
||||||
HashMap<String, HashResult> playerPSW = new HashMap<>();
|
HashMap<String, EncryptedPassword> playerPSW = new HashMap<>();
|
||||||
try {
|
try {
|
||||||
BufferedReader users;
|
BufferedReader users;
|
||||||
BufferedReader ipFile;
|
BufferedReader ipFile;
|
||||||
@ -64,22 +64,21 @@ public class RakamakConverter implements Converter {
|
|||||||
while ((line = users.readLine()) != null) {
|
while ((line = users.readLine()) != null) {
|
||||||
if (line.contains("=")) {
|
if (line.contains("=")) {
|
||||||
String[] arguments = line.split("=");
|
String[] arguments = line.split("=");
|
||||||
HashResult hashResult = passwordSecurity.computeHash(hash, arguments[1], arguments[0]);
|
EncryptedPassword encryptedPassword = passwordSecurity.computeHash(hash, arguments[1], arguments[0]);
|
||||||
playerPSW.put(arguments[0], hashResult);
|
playerPSW.put(arguments[0], encryptedPassword);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
users.close();
|
users.close();
|
||||||
for (Entry<String, HashResult> m : playerPSW.entrySet()) {
|
for (Entry<String, EncryptedPassword> m : playerPSW.entrySet()) {
|
||||||
String playerName = m.getKey();
|
String playerName = m.getKey();
|
||||||
HashResult psw = playerPSW.get(playerName);
|
EncryptedPassword psw = playerPSW.get(playerName);
|
||||||
String ip = useIP ? playerIP.get(playerName) : "127.0.0.1";
|
String ip = useIP ? playerIP.get(playerName) : "127.0.0.1";
|
||||||
PlayerAuth auth = PlayerAuth.builder()
|
PlayerAuth auth = PlayerAuth.builder()
|
||||||
.name(playerName)
|
.name(playerName)
|
||||||
.realName(playerName)
|
.realName(playerName)
|
||||||
.ip(ip)
|
.ip(ip)
|
||||||
.hash(psw.getHash())
|
.hash(psw)
|
||||||
.salt(psw.getSalt())
|
|
||||||
.lastLogin(System.currentTimeMillis())
|
.lastLogin(System.currentTimeMillis())
|
||||||
.build();
|
.build();
|
||||||
database.saveAuth(auth);
|
database.saveAuth(auth);
|
||||||
|
|||||||
@ -270,24 +270,6 @@ public class CacheDataSource implements DataSource {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateSalt.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#updateSalt(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public synchronized boolean updateSalt(final PlayerAuth auth) {
|
|
||||||
boolean result = source.updateSalt(auth);
|
|
||||||
if (result) {
|
|
||||||
cachedAuths.refresh(auth.getNickname());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method getAllAuthsByName.
|
* Method getAllAuthsByName.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -134,15 +134,6 @@ public interface DataSource {
|
|||||||
*/
|
*/
|
||||||
boolean updateEmail(PlayerAuth auth);
|
boolean updateEmail(PlayerAuth auth);
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateSalt.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
boolean updateSalt(PlayerAuth auth);
|
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
void reload();
|
void reload();
|
||||||
|
|||||||
@ -102,7 +102,7 @@ public class FlatFile implements DataSource {
|
|||||||
BufferedWriter bw = null;
|
BufferedWriter bw = null;
|
||||||
try {
|
try {
|
||||||
bw = new BufferedWriter(new FileWriter(source, true));
|
bw = new BufferedWriter(new FileWriter(source, true));
|
||||||
bw.write(auth.getNickname() + ":" + auth.getHash() + ":" + auth.getIp() + ":" + auth.getLastLogin() + ":" + auth.getQuitLocX() + ":" + auth.getQuitLocY() + ":" + auth.getQuitLocZ() + ":" + auth.getWorld() + ":" + auth.getEmail() + "\n");
|
bw.write(auth.getNickname() + ":" + auth.getPassword() + ":" + auth.getIp() + ":" + auth.getLastLogin() + ":" + auth.getQuitLocX() + ":" + auth.getQuitLocY() + ":" + auth.getQuitLocZ() + ":" + auth.getWorld() + ":" + auth.getEmail() + "\n");
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
return false;
|
return false;
|
||||||
@ -137,25 +137,26 @@ public class FlatFile implements DataSource {
|
|||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
String[] args = line.split(":");
|
String[] args = line.split(":");
|
||||||
if (args[0].equals(auth.getNickname())) {
|
if (args[0].equals(auth.getNickname())) {
|
||||||
|
// Note ljacqu 20151230: This does not persist the salt; it is not supported in flat file.
|
||||||
switch (args.length) {
|
switch (args.length) {
|
||||||
case 4: {
|
case 4: {
|
||||||
newAuth = new PlayerAuth(args[0], auth.getHash(), args[2], Long.parseLong(args[3]), 0, 0, 0, "world", "your@email.com", args[0]);
|
newAuth = new PlayerAuth(args[0], auth.getPassword().getHash(), args[2], Long.parseLong(args[3]), 0, 0, 0, "world", "your@email.com", args[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 7: {
|
case 7: {
|
||||||
newAuth = new PlayerAuth(args[0], auth.getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), "world", "your@email.com", args[0]);
|
newAuth = new PlayerAuth(args[0], auth.getPassword().getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), "world", "your@email.com", args[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 8: {
|
case 8: {
|
||||||
newAuth = new PlayerAuth(args[0], auth.getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], "your@email.com", args[0]);
|
newAuth = new PlayerAuth(args[0], auth.getPassword().getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], "your@email.com", args[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 9: {
|
case 9: {
|
||||||
newAuth = new PlayerAuth(args[0], auth.getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], args[8], args[0]);
|
newAuth = new PlayerAuth(args[0], auth.getPassword().getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], args[8], args[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
newAuth = new PlayerAuth(args[0], auth.getHash(), args[2], 0, 0, 0, 0, "world", "your@email.com", args[0]);
|
newAuth = new PlayerAuth(args[0], auth.getPassword().getHash(), args[2], 0, 0, 0, 0, "world", "your@email.com", args[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -600,18 +601,6 @@ public class FlatFile implements DataSource {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateSalt.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean * @see fr.xephi.authme.datasource.DataSource#updateSalt(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean updateSalt(PlayerAuth auth) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method getAllAuthsByName.
|
* Method getAllAuthsByName.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -6,7 +6,9 @@ import fr.xephi.authme.AuthMe;
|
|||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.security.HashAlgorithm;
|
import fr.xephi.authme.security.HashAlgorithm;
|
||||||
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.util.StringUtils;
|
||||||
|
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -284,13 +286,14 @@ public class MySQL implements DataSource {
|
|||||||
if (!rs.next()) {
|
if (!rs.next()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String salt = !columnSalt.isEmpty() ? rs.getString(columnSalt) : "";
|
String salt = !columnSalt.isEmpty() ? rs.getString(columnSalt) : null;
|
||||||
int group = !salt.isEmpty() && !columnGroup.isEmpty() ? rs.getInt(columnGroup) : -1;
|
String hash = rs.getString(columnPassword);
|
||||||
|
int group = !columnGroup.isEmpty() ? rs.getInt(columnGroup) : -1;
|
||||||
int id = rs.getInt(columnID);
|
int id = rs.getInt(columnID);
|
||||||
pAuth = PlayerAuth.builder()
|
pAuth = PlayerAuth.builder()
|
||||||
.name(rs.getString(columnName))
|
.name(rs.getString(columnName))
|
||||||
.realName(rs.getString(columnRealName))
|
.realName(rs.getString(columnRealName))
|
||||||
.hash(rs.getString(columnPassword))
|
.hash(new EncryptedPassword(hash, salt))
|
||||||
.lastLogin(rs.getLong(columnLastLogin))
|
.lastLogin(rs.getLong(columnLastLogin))
|
||||||
.ip(rs.getString(columnIp))
|
.ip(rs.getString(columnIp))
|
||||||
.locWorld(rs.getString(lastlocWorld))
|
.locWorld(rs.getString(lastlocWorld))
|
||||||
@ -298,7 +301,6 @@ public class MySQL implements DataSource {
|
|||||||
.locY(rs.getDouble(lastlocY))
|
.locY(rs.getDouble(lastlocY))
|
||||||
.locZ(rs.getDouble(lastlocZ))
|
.locZ(rs.getDouble(lastlocZ))
|
||||||
.email(rs.getString(columnEmail))
|
.email(rs.getString(columnEmail))
|
||||||
.salt(salt)
|
|
||||||
.groupId(group)
|
.groupId(group)
|
||||||
.build();
|
.build();
|
||||||
rs.close();
|
rs.close();
|
||||||
@ -328,7 +330,7 @@ public class MySQL implements DataSource {
|
|||||||
ResultSet rs;
|
ResultSet rs;
|
||||||
String sql;
|
String sql;
|
||||||
|
|
||||||
boolean useSalt = !columnSalt.isEmpty() || !auth.getSalt().isEmpty();
|
boolean useSalt = !columnSalt.isEmpty() || !StringUtils.isEmpty(auth.getPassword().getSalt());
|
||||||
sql = "INSERT INTO " + tableName + "("
|
sql = "INSERT INTO " + tableName + "("
|
||||||
+ columnName + "," + columnPassword + "," + columnIp + ","
|
+ columnName + "," + columnPassword + "," + columnIp + ","
|
||||||
+ columnLastLogin + "," + columnRealName
|
+ columnLastLogin + "," + columnRealName
|
||||||
@ -336,12 +338,12 @@ public class MySQL implements DataSource {
|
|||||||
+ ") VALUES (?,?,?,?,?" + (useSalt ? ",?" : "") + ");";
|
+ ") VALUES (?,?,?,?,?" + (useSalt ? ",?" : "") + ");";
|
||||||
pst = con.prepareStatement(sql);
|
pst = con.prepareStatement(sql);
|
||||||
pst.setString(1, auth.getNickname());
|
pst.setString(1, auth.getNickname());
|
||||||
pst.setString(2, auth.getHash());
|
pst.setString(2, auth.getPassword().getHash());
|
||||||
pst.setString(3, auth.getIp());
|
pst.setString(3, auth.getIp());
|
||||||
pst.setLong(4, auth.getLastLogin());
|
pst.setLong(4, auth.getLastLogin());
|
||||||
pst.setString(5, auth.getRealName());
|
pst.setString(5, auth.getRealName());
|
||||||
if (useSalt) {
|
if (useSalt) {
|
||||||
pst.setString(6, auth.getSalt());
|
pst.setString(6, auth.getPassword().getSalt());
|
||||||
}
|
}
|
||||||
pst.executeUpdate();
|
pst.executeUpdate();
|
||||||
pst.close();
|
pst.close();
|
||||||
@ -513,10 +515,22 @@ public class MySQL implements DataSource {
|
|||||||
@Override
|
@Override
|
||||||
public synchronized boolean updatePassword(PlayerAuth auth) {
|
public synchronized boolean updatePassword(PlayerAuth auth) {
|
||||||
try (Connection con = getConnection()) {
|
try (Connection con = getConnection()) {
|
||||||
String sql = "UPDATE " + tableName + " SET " + columnPassword + "=? WHERE " + columnName + "=?;";
|
boolean useSalt = !columnSalt.isEmpty();
|
||||||
PreparedStatement pst = con.prepareStatement(sql);
|
PreparedStatement pst;
|
||||||
pst.setString(1, auth.getHash());
|
if (useSalt) {
|
||||||
pst.setString(2, auth.getNickname());
|
String sql = String.format("UPDATE %s SET %s = ?, %s = ? WHERE %s = ?;",
|
||||||
|
tableName, columnPassword, columnSalt, columnName);
|
||||||
|
pst = con.prepareStatement(sql);
|
||||||
|
pst.setString(1, auth.getPassword().getHash());
|
||||||
|
pst.setString(2, auth.getPassword().getSalt());
|
||||||
|
pst.setString(3, auth.getNickname());
|
||||||
|
} else {
|
||||||
|
String sql = String.format("UPDATE %s SET %s = ? WHERE %s = ?;",
|
||||||
|
tableName, columnPassword, columnName);
|
||||||
|
pst = con.prepareStatement(sql);
|
||||||
|
pst.setString(1, auth.getPassword().getHash());
|
||||||
|
pst.setString(2, auth.getNickname());
|
||||||
|
}
|
||||||
pst.executeUpdate();
|
pst.executeUpdate();
|
||||||
pst.close();
|
pst.close();
|
||||||
return true;
|
return true;
|
||||||
@ -719,35 +733,6 @@ public class MySQL implements DataSource {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateSalt.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#updateSalt(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public synchronized boolean updateSalt(PlayerAuth auth) {
|
|
||||||
if (columnSalt.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try (Connection con = getConnection()) {
|
|
||||||
String sql = "UPDATE " + tableName + " SET " + columnSalt + " =? WHERE " + columnName + "=?;";
|
|
||||||
PreparedStatement pst = con.prepareStatement(sql);
|
|
||||||
pst.setString(1, auth.getSalt());
|
|
||||||
pst.setString(2, auth.getNickname());
|
|
||||||
pst.executeUpdate();
|
|
||||||
pst.close();
|
|
||||||
return true;
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
|
||||||
ConsoleLogger.writeStackTrace(ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method reload.
|
* Method reload.
|
||||||
*
|
*
|
||||||
@ -1045,12 +1030,12 @@ public class MySQL implements DataSource {
|
|||||||
ResultSet rs = st.executeQuery("SELECT * FROM " + tableName);
|
ResultSet rs = st.executeQuery("SELECT * FROM " + tableName);
|
||||||
PreparedStatement pst = con.prepareStatement("SELECT data FROM xf_user_authenticate WHERE " + columnID + "=?;");
|
PreparedStatement pst = con.prepareStatement("SELECT data FROM xf_user_authenticate WHERE " + columnID + "=?;");
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
String salt = !columnSalt.isEmpty() ? rs.getString(columnSalt) : "";
|
String salt = !columnSalt.isEmpty() ? rs.getString(columnSalt) : null;
|
||||||
int group = !salt.isEmpty() && !columnGroup.isEmpty() ? rs.getInt(columnGroup) : -1;
|
int group = !columnGroup.isEmpty() ? rs.getInt(columnGroup) : -1;
|
||||||
PlayerAuth pAuth = PlayerAuth.builder()
|
PlayerAuth pAuth = PlayerAuth.builder()
|
||||||
.name(rs.getString(columnName))
|
.name(rs.getString(columnName))
|
||||||
.realName(rs.getString(columnRealName))
|
.realName(rs.getString(columnRealName))
|
||||||
.hash(rs.getString(columnPassword))
|
.hash(new EncryptedPassword(rs.getString(columnPassword), salt))
|
||||||
.lastLogin(rs.getLong(columnLastLogin))
|
.lastLogin(rs.getLong(columnLastLogin))
|
||||||
.ip(rs.getString(columnIp))
|
.ip(rs.getString(columnIp))
|
||||||
.locWorld(rs.getString(lastlocWorld))
|
.locWorld(rs.getString(lastlocWorld))
|
||||||
@ -1058,7 +1043,6 @@ public class MySQL implements DataSource {
|
|||||||
.locY(rs.getDouble(lastlocY))
|
.locY(rs.getDouble(lastlocY))
|
||||||
.locZ(rs.getDouble(lastlocZ))
|
.locZ(rs.getDouble(lastlocZ))
|
||||||
.email(rs.getString(columnEmail))
|
.email(rs.getString(columnEmail))
|
||||||
.salt(salt)
|
|
||||||
.groupId(group)
|
.groupId(group)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@ -1089,12 +1073,12 @@ public class MySQL implements DataSource {
|
|||||||
ResultSet rs = st.executeQuery("SELECT * FROM " + tableName + " WHERE " + columnLogged + "=1;");
|
ResultSet rs = st.executeQuery("SELECT * FROM " + tableName + " WHERE " + columnLogged + "=1;");
|
||||||
PreparedStatement pst = con.prepareStatement("SELECT data FROM xf_user_authenticate WHERE " + columnID + "=?;");
|
PreparedStatement pst = con.prepareStatement("SELECT data FROM xf_user_authenticate WHERE " + columnID + "=?;");
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
String salt = !columnSalt.isEmpty() ? rs.getString(columnSalt) : "";
|
String salt = !columnSalt.isEmpty() ? rs.getString(columnSalt) : null;
|
||||||
int group = !salt.isEmpty() && !columnGroup.isEmpty() ? rs.getInt(columnGroup) : -1;
|
int group = !columnGroup.isEmpty() ? rs.getInt(columnGroup) : -1;
|
||||||
PlayerAuth pAuth = PlayerAuth.builder()
|
PlayerAuth pAuth = PlayerAuth.builder()
|
||||||
.name(rs.getString(columnName))
|
.name(rs.getString(columnName))
|
||||||
.realName(rs.getString(columnRealName))
|
.realName(rs.getString(columnRealName))
|
||||||
.hash(rs.getString(columnPassword))
|
.hash(new EncryptedPassword(rs.getString(columnPassword), salt))
|
||||||
.lastLogin(rs.getLong(columnLastLogin))
|
.lastLogin(rs.getLong(columnLastLogin))
|
||||||
.ip(rs.getString(columnIp))
|
.ip(rs.getString(columnIp))
|
||||||
.locWorld(rs.getString(lastlocWorld))
|
.locWorld(rs.getString(lastlocWorld))
|
||||||
@ -1102,7 +1086,6 @@ public class MySQL implements DataSource {
|
|||||||
.locY(rs.getDouble(lastlocY))
|
.locY(rs.getDouble(lastlocY))
|
||||||
.locZ(rs.getDouble(lastlocZ))
|
.locZ(rs.getDouble(lastlocZ))
|
||||||
.email(rs.getString(columnEmail))
|
.email(rs.getString(columnEmail))
|
||||||
.salt(salt)
|
|
||||||
.groupId(group)
|
.groupId(group)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package fr.xephi.authme.datasource;
|
|||||||
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
@ -174,15 +175,7 @@ public class SQLite implements DataSource {
|
|||||||
pst.setString(1, user);
|
pst.setString(1, user);
|
||||||
rs = pst.executeQuery();
|
rs = pst.executeQuery();
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
if (rs.getString(columnIp).isEmpty()) {
|
return buildAuthFromResultSet(rs);
|
||||||
return new PlayerAuth(rs.getString(columnName), rs.getString(columnPassword), "192.168.0.1", rs.getLong(columnLastLogin), rs.getDouble(lastlocX), rs.getDouble(lastlocY), rs.getDouble(lastlocZ), rs.getString(lastlocWorld), rs.getString(columnEmail), rs.getString(columnRealName));
|
|
||||||
} else {
|
|
||||||
if (!columnSalt.isEmpty()) {
|
|
||||||
return new PlayerAuth(rs.getString(columnName), rs.getString(columnPassword), rs.getString(columnSalt), rs.getInt(columnGroup), rs.getString(columnIp), rs.getLong(columnLastLogin), rs.getDouble(lastlocX), rs.getDouble(lastlocY), rs.getDouble(lastlocZ), rs.getString(lastlocWorld), rs.getString(columnEmail), rs.getString(columnRealName));
|
|
||||||
} else {
|
|
||||||
return new PlayerAuth(rs.getString(columnName), rs.getString(columnPassword), rs.getString(columnIp), rs.getLong(columnLastLogin), rs.getDouble(lastlocX), rs.getDouble(lastlocY), rs.getDouble(lastlocZ), rs.getString(lastlocWorld), rs.getString(columnEmail), rs.getString(columnRealName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -206,21 +199,25 @@ public class SQLite implements DataSource {
|
|||||||
public synchronized boolean saveAuth(PlayerAuth auth) {
|
public synchronized boolean saveAuth(PlayerAuth auth) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
try {
|
try {
|
||||||
if (columnSalt.isEmpty() && auth.getSalt().isEmpty()) {
|
EncryptedPassword password = auth.getPassword();
|
||||||
pst = con.prepareStatement("INSERT INTO " + tableName + "(" + columnName + "," + columnPassword + "," + columnIp + "," + columnLastLogin + "," + columnRealName + ") VALUES (?,?,?,?,?);");
|
if (columnSalt.isEmpty() && password.getSalt().isEmpty()) {
|
||||||
|
pst = con.prepareStatement("INSERT INTO " + tableName + "(" + columnName + "," + columnPassword +
|
||||||
|
"," + columnIp + "," + columnLastLogin + "," + columnRealName + ") VALUES (?,?,?,?,?);");
|
||||||
pst.setString(1, auth.getNickname());
|
pst.setString(1, auth.getNickname());
|
||||||
pst.setString(2, auth.getHash());
|
pst.setString(2, password.getHash());
|
||||||
pst.setString(3, auth.getIp());
|
pst.setString(3, auth.getIp());
|
||||||
pst.setLong(4, auth.getLastLogin());
|
pst.setLong(4, auth.getLastLogin());
|
||||||
pst.setString(5, auth.getRealName());
|
pst.setString(5, auth.getRealName());
|
||||||
pst.executeUpdate();
|
pst.executeUpdate();
|
||||||
} else {
|
} else {
|
||||||
pst = con.prepareStatement("INSERT INTO " + tableName + "(" + columnName + "," + columnPassword + "," + columnIp + "," + columnLastLogin + "," + columnSalt + "," + columnRealName + ") VALUES (?,?,?,?,?,?);");
|
pst = con.prepareStatement("INSERT INTO " + tableName + "(" + columnName + "," + columnPassword + ","
|
||||||
|
+ columnIp + "," + columnLastLogin + "," + columnSalt + "," + columnRealName
|
||||||
|
+ ") VALUES (?,?,?,?,?,?);");
|
||||||
pst.setString(1, auth.getNickname());
|
pst.setString(1, auth.getNickname());
|
||||||
pst.setString(2, auth.getHash());
|
pst.setString(2, password.getHash());
|
||||||
pst.setString(3, auth.getIp());
|
pst.setString(3, auth.getIp());
|
||||||
pst.setLong(4, auth.getLastLogin());
|
pst.setLong(4, auth.getLastLogin());
|
||||||
pst.setString(5, auth.getSalt());
|
pst.setString(5, password.getSalt());
|
||||||
pst.setString(6, auth.getRealName());
|
pst.setString(6, auth.getRealName());
|
||||||
pst.executeUpdate();
|
pst.executeUpdate();
|
||||||
}
|
}
|
||||||
@ -244,9 +241,19 @@ public class SQLite implements DataSource {
|
|||||||
public synchronized boolean updatePassword(PlayerAuth auth) {
|
public synchronized boolean updatePassword(PlayerAuth auth) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
try {
|
try {
|
||||||
pst = con.prepareStatement("UPDATE " + tableName + " SET " + columnPassword + "=? WHERE " + columnName + "=?;");
|
EncryptedPassword password = auth.getPassword();
|
||||||
pst.setString(1, auth.getHash());
|
boolean useSalt = !columnSalt.isEmpty();
|
||||||
pst.setString(2, auth.getNickname());
|
String sql = "UPDATE " + tableName + " SET " + columnPassword + " = ?"
|
||||||
|
+ (useSalt ? ", " + columnSalt + " = ?" : "")
|
||||||
|
+ " WHERE " + columnName + " = ?";
|
||||||
|
pst = con.prepareStatement(sql);
|
||||||
|
pst.setString(1, password.getHash());
|
||||||
|
if (useSalt) {
|
||||||
|
pst.setString(2, password.getSalt());
|
||||||
|
pst.setString(3, auth.getNickname());
|
||||||
|
} else {
|
||||||
|
pst.setString(2, auth.getNickname());
|
||||||
|
}
|
||||||
pst.executeUpdate();
|
pst.executeUpdate();
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
@ -398,6 +405,7 @@ public class SQLite implements DataSource {
|
|||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
int countIp = 0;
|
int countIp = 0;
|
||||||
try {
|
try {
|
||||||
|
// TODO ljacqu 20151230: Simply fetch COUNT(1) and return that
|
||||||
pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnIp + "=?;");
|
pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnIp + "=?;");
|
||||||
pst.setString(1, ip);
|
pst.setString(1, ip);
|
||||||
rs = pst.executeQuery();
|
rs = pst.executeQuery();
|
||||||
@ -438,33 +446,6 @@ public class SQLite implements DataSource {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateSalt.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean * @see fr.xephi.authme.datasource.DataSource#updateSalt(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean updateSalt(PlayerAuth auth) {
|
|
||||||
if (columnSalt.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
PreparedStatement pst = null;
|
|
||||||
try {
|
|
||||||
pst = con.prepareStatement("UPDATE " + tableName + " SET " + columnSalt + "=? WHERE " + columnName + "=?;");
|
|
||||||
pst.setString(1, auth.getSalt());
|
|
||||||
pst.setString(2, auth.getNickname());
|
|
||||||
pst.executeUpdate();
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
close(pst);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method close.
|
* Method close.
|
||||||
*
|
*
|
||||||
@ -761,14 +742,6 @@ public class SQLite implements DataSource {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateName.
|
|
||||||
*
|
|
||||||
* @param oldOne String
|
|
||||||
* @param newOne String
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#updateName(String, String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void updateName(String oldOne, String newOne) {
|
public void updateName(String oldOne, String newOne) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -787,7 +760,7 @@ public class SQLite implements DataSource {
|
|||||||
/**
|
/**
|
||||||
* Method getAllAuths.
|
* Method getAllAuths.
|
||||||
*
|
*
|
||||||
* @return List<PlayerAuth> * @see fr.xephi.authme.datasource.DataSource#getAllAuths()
|
* @return List<PlayerAuth>
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<PlayerAuth> getAllAuths() {
|
public List<PlayerAuth> getAllAuths() {
|
||||||
@ -798,17 +771,8 @@ public class SQLite implements DataSource {
|
|||||||
pst = con.prepareStatement("SELECT * FROM " + tableName + ";");
|
pst = con.prepareStatement("SELECT * FROM " + tableName + ";");
|
||||||
rs = pst.executeQuery();
|
rs = pst.executeQuery();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
PlayerAuth pAuth;
|
PlayerAuth auth = buildAuthFromResultSet(rs);
|
||||||
if (rs.getString(columnIp).isEmpty()) {
|
auths.add(auth);
|
||||||
pAuth = new PlayerAuth(rs.getString(columnName), rs.getString(columnPassword), "127.0.0.1", rs.getLong(columnLastLogin), rs.getDouble(lastlocX), rs.getDouble(lastlocY), rs.getDouble(lastlocZ), rs.getString(lastlocWorld), rs.getString(columnEmail), rs.getString(columnRealName));
|
|
||||||
} else {
|
|
||||||
if (!columnSalt.isEmpty()) {
|
|
||||||
pAuth = new PlayerAuth(rs.getString(columnName), rs.getString(columnPassword), rs.getString(columnSalt), rs.getInt(columnGroup), rs.getString(columnIp), rs.getLong(columnLastLogin), rs.getDouble(lastlocX), rs.getDouble(lastlocY), rs.getDouble(lastlocZ), rs.getString(lastlocWorld), rs.getString(columnEmail), rs.getString(columnRealName));
|
|
||||||
} else {
|
|
||||||
pAuth = new PlayerAuth(rs.getString(columnName), rs.getString(columnPassword), rs.getString(columnIp), rs.getLong(columnLastLogin), rs.getDouble(lastlocX), rs.getDouble(lastlocY), rs.getDouble(lastlocZ), rs.getString(lastlocWorld), rs.getString(columnEmail), rs.getString(columnRealName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auths.add(pAuth);
|
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
@ -822,7 +786,7 @@ public class SQLite implements DataSource {
|
|||||||
/**
|
/**
|
||||||
* Method getLoggedPlayers.
|
* Method getLoggedPlayers.
|
||||||
*
|
*
|
||||||
* @return List<PlayerAuth> * @see fr.xephi.authme.datasource.DataSource#getLoggedPlayers()
|
* @return List<PlayerAuth>
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<PlayerAuth> getLoggedPlayers() {
|
public List<PlayerAuth> getLoggedPlayers() {
|
||||||
@ -833,17 +797,8 @@ public class SQLite implements DataSource {
|
|||||||
pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnLogged + "=1;");
|
pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnLogged + "=1;");
|
||||||
rs = pst.executeQuery();
|
rs = pst.executeQuery();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
PlayerAuth pAuth;
|
PlayerAuth auth = buildAuthFromResultSet(rs);
|
||||||
if (rs.getString(columnIp).isEmpty()) {
|
auths.add(auth);
|
||||||
pAuth = new PlayerAuth(rs.getString(columnName), rs.getString(columnPassword), "127.0.0.1", rs.getLong(columnLastLogin), rs.getDouble(lastlocX), rs.getDouble(lastlocY), rs.getDouble(lastlocZ), rs.getString(lastlocWorld), rs.getString(columnEmail), rs.getString(columnRealName));
|
|
||||||
} else {
|
|
||||||
if (!columnSalt.isEmpty()) {
|
|
||||||
pAuth = new PlayerAuth(rs.getString(columnName), rs.getString(columnPassword), rs.getString(columnSalt), rs.getInt(columnGroup), rs.getString(columnIp), rs.getLong(columnLastLogin), rs.getDouble(lastlocX), rs.getDouble(lastlocY), rs.getDouble(lastlocZ), rs.getString(lastlocWorld), rs.getString(columnEmail), rs.getString(columnRealName));
|
|
||||||
} else {
|
|
||||||
pAuth = new PlayerAuth(rs.getString(columnName), rs.getString(columnPassword), rs.getString(columnIp), rs.getLong(columnLastLogin), rs.getDouble(lastlocX), rs.getDouble(lastlocY), rs.getDouble(lastlocZ), rs.getString(lastlocWorld), rs.getString(columnEmail), rs.getString(columnRealName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auths.add(pAuth);
|
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
@ -853,4 +808,25 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
return auths;
|
return auths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PlayerAuth buildAuthFromResultSet(ResultSet row) throws SQLException {
|
||||||
|
String salt = !columnSalt.isEmpty() ? row.getString(columnSalt) : null;
|
||||||
|
|
||||||
|
PlayerAuth.Builder authBuilder = PlayerAuth.builder()
|
||||||
|
.name(row.getString(columnName))
|
||||||
|
.email(row.getString(columnEmail))
|
||||||
|
.realName(row.getString(columnRealName))
|
||||||
|
.hash(row.getString(columnPassword), salt)
|
||||||
|
.lastLogin(row.getLong(columnLastLogin))
|
||||||
|
.locX(row.getDouble(lastlocX))
|
||||||
|
.locY(row.getDouble(lastlocY))
|
||||||
|
.locZ(row.getDouble(lastlocZ))
|
||||||
|
.locWorld(row.getString(lastlocWorld));
|
||||||
|
|
||||||
|
String ip = row.getString(columnIp);
|
||||||
|
if (!ip.isEmpty()) {
|
||||||
|
authBuilder.ip(ip);
|
||||||
|
}
|
||||||
|
return authBuilder.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import fr.xephi.authme.ConsoleLogger;
|
|||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.cache.auth.PlayerCache;
|
import fr.xephi.authme.cache.auth.PlayerCache;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||||
|
|
||||||
@ -65,10 +66,8 @@ public class BungeeCordMessage implements PluginMessageListener {
|
|||||||
+ " has registered out from one of your server!");
|
+ " has registered out from one of your server!");
|
||||||
} else if ("changepassword".equals(act)) {
|
} else if ("changepassword".equals(act)) {
|
||||||
final String password = args[2];
|
final String password = args[2];
|
||||||
auth.setHash(password);
|
final String salt = args.length >= 4 ? args[3] : null;
|
||||||
if (args.length == 4) {
|
auth.setPassword(new EncryptedPassword(password, salt));
|
||||||
auth.setSalt(args[3]);
|
|
||||||
}
|
|
||||||
PlayerCache.getInstance().updatePlayer(auth);
|
PlayerCache.getInstance().updatePlayer(auth);
|
||||||
dataSource.updatePassword(auth);
|
dataSource.updatePassword(auth);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import fr.xephi.authme.cache.limbo.LimboCache;
|
|||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.events.AuthMeAsyncPreLoginEvent;
|
import fr.xephi.authme.events.AuthMeAsyncPreLoginEvent;
|
||||||
import fr.xephi.authme.permission.PlayerPermission;
|
import fr.xephi.authme.permission.PlayerPermission;
|
||||||
import fr.xephi.authme.security.PasswordSecurity;
|
|
||||||
import fr.xephi.authme.security.RandomString;
|
import fr.xephi.authme.security.RandomString;
|
||||||
import fr.xephi.authme.output.MessageKey;
|
import fr.xephi.authme.output.MessageKey;
|
||||||
import fr.xephi.authme.output.Messages;
|
import fr.xephi.authme.output.Messages;
|
||||||
@ -138,7 +137,7 @@ public class AsynchronousLogin {
|
|||||||
|
|
||||||
String email = pAuth.getEmail();
|
String email = pAuth.getEmail();
|
||||||
boolean passwordVerified = forceLogin || plugin.getPasswordSecurity()
|
boolean passwordVerified = forceLogin || plugin.getPasswordSecurity()
|
||||||
.comparePassword(password, pAuth.getHash(), pAuth.getSalt(), realName);
|
.comparePassword(password, pAuth.getPassword(), realName);
|
||||||
|
|
||||||
if (passwordVerified && player.isOnline()) {
|
if (passwordVerified && player.isOnline()) {
|
||||||
PlayerAuth auth = PlayerAuth.builder()
|
PlayerAuth auth = PlayerAuth.builder()
|
||||||
@ -147,8 +146,7 @@ public class AsynchronousLogin {
|
|||||||
.ip(getIP())
|
.ip(getIP())
|
||||||
.lastLogin(new Date().getTime())
|
.lastLogin(new Date().getTime())
|
||||||
.email(email)
|
.email(email)
|
||||||
.hash(pAuth.getHash())
|
.hash(pAuth.getPassword())
|
||||||
.salt(pAuth.getSalt())
|
|
||||||
.build();
|
.build();
|
||||||
database.updateSession(auth);
|
database.updateSession(auth);
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import fr.xephi.authme.datasource.DataSource;
|
|||||||
import fr.xephi.authme.output.MessageKey;
|
import fr.xephi.authme.output.MessageKey;
|
||||||
import fr.xephi.authme.output.Messages;
|
import fr.xephi.authme.output.Messages;
|
||||||
import fr.xephi.authme.permission.PlayerPermission;
|
import fr.xephi.authme.permission.PlayerPermission;
|
||||||
import fr.xephi.authme.security.crypts.HashResult;
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@ -97,12 +97,11 @@ public class AsyncRegister {
|
|||||||
m.send(player, MessageKey.MAX_REGISTER_EXCEEDED);
|
m.send(player, MessageKey.MAX_REGISTER_EXCEEDED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final HashResult hashResult = plugin.getPasswordSecurity().computeHash(password, name);
|
final EncryptedPassword encryptedPassword = plugin.getPasswordSecurity().computeHash(password, name);
|
||||||
PlayerAuth auth = PlayerAuth.builder()
|
PlayerAuth auth = PlayerAuth.builder()
|
||||||
.name(name)
|
.name(name)
|
||||||
.realName(player.getName())
|
.realName(player.getName())
|
||||||
.hash(hashResult.getHash())
|
.hash(encryptedPassword)
|
||||||
.salt(hashResult.getSalt())
|
|
||||||
.ip(ip)
|
.ip(ip)
|
||||||
.locWorld(player.getLocation().getWorld().getName())
|
.locWorld(player.getLocation().getWorld().getName())
|
||||||
.locX(player.getLocation().getX())
|
.locX(player.getLocation().getX())
|
||||||
@ -124,12 +123,11 @@ public class AsyncRegister {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void passwordRegister() throws Exception {
|
private void passwordRegister() throws Exception {
|
||||||
final HashResult hashResult = plugin.getPasswordSecurity().computeHash(password, name);
|
final EncryptedPassword encryptedPassword = plugin.getPasswordSecurity().computeHash(password, name);
|
||||||
PlayerAuth auth = PlayerAuth.builder()
|
PlayerAuth auth = PlayerAuth.builder()
|
||||||
.name(name)
|
.name(name)
|
||||||
.realName(player.getName())
|
.realName(player.getName())
|
||||||
.hash(hashResult.getHash())
|
.hash(encryptedPassword)
|
||||||
.salt(hashResult.getSalt())
|
|
||||||
.ip(ip)
|
.ip(ip)
|
||||||
.locWorld(player.getLocation().getWorld().getName())
|
.locWorld(player.getLocation().getWorld().getName())
|
||||||
.locX(player.getLocation().getX())
|
.locX(player.getLocation().getX())
|
||||||
|
|||||||
@ -55,7 +55,7 @@ public class AsynchronousUnregister {
|
|||||||
public void process() {
|
public void process() {
|
||||||
PlayerAuth cachedAuth = PlayerCache.getInstance().getAuth(name);
|
PlayerAuth cachedAuth = PlayerCache.getInstance().getAuth(name);
|
||||||
if (force || plugin.getPasswordSecurity().comparePassword(
|
if (force || plugin.getPasswordSecurity().comparePassword(
|
||||||
password, cachedAuth.getHash(), cachedAuth.getSalt(), player.getName())) {
|
password, cachedAuth.getPassword(), player.getName())) {
|
||||||
if (!plugin.getDataSource().removeAuth(name)) {
|
if (!plugin.getDataSource().removeAuth(name)) {
|
||||||
m.send(player, MessageKey.ERROR);
|
m.send(player, MessageKey.ERROR);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -3,12 +3,10 @@ package fr.xephi.authme.security;
|
|||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.events.PasswordEncryptionEvent;
|
import fr.xephi.authme.events.PasswordEncryptionEvent;
|
||||||
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||||
import fr.xephi.authme.security.crypts.HashResult;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manager class for password-related operations.
|
* Manager class for password-related operations.
|
||||||
*/
|
*/
|
||||||
@ -24,48 +22,53 @@ public class PasswordSecurity {
|
|||||||
this.supportOldAlgorithm = supportOldAlgorithm;
|
this.supportOldAlgorithm = supportOldAlgorithm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashResult computeHash(String password, String playerName) {
|
public EncryptedPassword computeHash(String password, String playerName) {
|
||||||
return computeHash(algorithm, password, playerName);
|
return computeHash(algorithm, password, playerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashResult computeHash(HashAlgorithm algorithm, String password, String playerName) {
|
public EncryptedPassword computeHash(HashAlgorithm algorithm, String password, String playerName) {
|
||||||
EncryptionMethod method = initializeEncryptionMethod(algorithm, playerName);
|
EncryptionMethod method = initializeEncryptionMethod(algorithm, playerName);
|
||||||
return method.computeHash(password, playerName);
|
return method.computeHash(password, playerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean comparePassword(String password, String playerName) {
|
public boolean comparePassword(String password, String playerName) {
|
||||||
|
// TODO ljacqu 20151230: Defining a dataSource.getPassword() method would be more efficient
|
||||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||||
if (auth != null) {
|
if (auth != null) {
|
||||||
return comparePassword(auth.getHash(), auth.getSalt(), password, playerName);
|
return comparePassword(password, auth.getPassword(), playerName);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean comparePassword(String hash, String salt, String password, String playerName) {
|
public boolean comparePassword(String password, EncryptedPassword encryptedPassword, String playerName) {
|
||||||
EncryptionMethod method = initializeEncryptionMethod(algorithm, playerName);
|
EncryptionMethod method = initializeEncryptionMethod(algorithm, playerName);
|
||||||
// User is not in data source, so the result will invariably be wrong because an encryption
|
// User is not in data source, so the result will invariably be wrong because an encryption
|
||||||
// method with hasSeparateSalt() == true NEEDS the salt to evaluate the password
|
// method with hasSeparateSalt() == true NEEDS the salt to evaluate the password
|
||||||
|
String salt = encryptedPassword.getSalt();
|
||||||
if (method.hasSeparateSalt() && salt == null) {
|
if (method.hasSeparateSalt() && salt == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return method.comparePassword(hash, password, salt, playerName)
|
|
||||||
|| supportOldAlgorithm && compareWithAllEncryptionMethods(password, hash, salt, playerName);
|
return method.comparePassword(password, encryptedPassword, playerName)
|
||||||
|
|| supportOldAlgorithm && compareWithAllEncryptionMethods(password, encryptedPassword, playerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare the given hash with all available encryption methods to support the migration to a new encryption method.
|
* Compare the given hash with all available 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.
|
||||||
*
|
*
|
||||||
* @param password The clear-text password to check
|
* @param password The clear-text password to check
|
||||||
* @param hash The hash to text the password against
|
* @param encryptedPassword The encrypted password to test the clear-text password against
|
||||||
* @param salt The salt (or null if none available)
|
* @param playerName The name of the player
|
||||||
* @param playerName The name of the player
|
|
||||||
* @return True if the
|
* @return True if the
|
||||||
*/
|
*/
|
||||||
private boolean compareWithAllEncryptionMethods(String password, String hash, String salt, String playerName) {
|
private boolean compareWithAllEncryptionMethods(String password, EncryptedPassword encryptedPassword,
|
||||||
|
String playerName) {
|
||||||
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
|
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
|
||||||
if (!HashAlgorithm.CUSTOM.equals(algorithm)) {
|
if (!HashAlgorithm.CUSTOM.equals(algorithm)) {
|
||||||
EncryptionMethod method = initializeEncryptionMethodWithoutEvent(algorithm);
|
EncryptionMethod method = initializeEncryptionMethodWithoutEvent(algorithm);
|
||||||
if (method != null && method.comparePassword(hash, password, salt, playerName)) {
|
if (method != null && method.comparePassword(password, encryptedPassword, playerName)) {
|
||||||
hashPasswordForNewAlgorithm(password, playerName);
|
hashPasswordForNewAlgorithm(password, playerName);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -75,8 +78,8 @@ public class PasswordSecurity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the encryption method from the given {@link HashAlgorithm} value and emits a
|
* Get the encryption method from the given {@link HashAlgorithm} value and emit a
|
||||||
* {@link PasswordEncryptionEvent}. The encryption method from the event is returned,
|
* {@link PasswordEncryptionEvent}. The encryption method from the event is then returned,
|
||||||
* which may have been changed by an external listener.
|
* which may have been changed by an external listener.
|
||||||
*
|
*
|
||||||
* @param algorithm The algorithm to retrieve the encryption method for
|
* @param algorithm The algorithm to retrieve the encryption method for
|
||||||
@ -110,14 +113,10 @@ public class PasswordSecurity {
|
|||||||
private void hashPasswordForNewAlgorithm(String password, String playerName) {
|
private void hashPasswordForNewAlgorithm(String password, String playerName) {
|
||||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||||
if (auth != null) {
|
if (auth != null) {
|
||||||
HashResult hashResult = initializeEncryptionMethod(algorithm, playerName)
|
EncryptedPassword encryptedPassword = initializeEncryptionMethod(algorithm, playerName)
|
||||||
.computeHash(password, playerName);
|
.computeHash(password, playerName);
|
||||||
|
auth.setPassword(encryptedPassword);
|
||||||
// TODO #358: updatePassword() should just take the HashResult..., or at least hash & salt. Idem for setHash
|
|
||||||
auth.setSalt(hashResult.getSalt());
|
|
||||||
auth.setHash(hashResult.getHash());
|
|
||||||
dataSource.updatePassword(auth);
|
dataSource.updatePassword(auth);
|
||||||
dataSource.updateSalt(auth);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -520,14 +520,14 @@ public class BCRYPT implements EncryptionMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashResult computeHash(String password, String name) {
|
public EncryptedPassword computeHash(String password, String name) {
|
||||||
String salt = generateSalt();
|
String salt = generateSalt();
|
||||||
return new HashResult(hashpw(password, salt), null);
|
return new EncryptedPassword(hashpw(password, salt), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
public boolean comparePassword(String password, EncryptedPassword hash, String name) {
|
||||||
return checkpw(password, hash);
|
return checkpw(password, hash.getHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -15,11 +15,13 @@ public class BCRYPT2Y extends HexSaltedMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String unusedSalt, String unusedName) {
|
public boolean comparePassword(String password, EncryptedPassword encrypted, String unusedName) {
|
||||||
|
String hash = encrypted.getHash();
|
||||||
if (hash.length() != 60) {
|
if (hash.length() != 60) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// The salt is the first 29 characters of the hash
|
// The salt is the first 29 characters of the hash
|
||||||
|
|
||||||
String salt = hash.substring(0, 29);
|
String salt = hash.substring(0, 29);
|
||||||
return hash.equals(computeHash(password, salt, null));
|
return hash.equals(computeHash(password, salt, null));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,11 +28,11 @@ public class CRAZYCRYPT1 extends UsernameSaltMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashResult computeHash(String password, String name) {
|
public EncryptedPassword computeHash(String password, String name) {
|
||||||
final String text = "ÜÄaeut//&/=I " + password + "7421€547" + name + "__+IÄIH§%NK " + password;
|
final String text = "ÜÄaeut//&/=I " + password + "7421€547" + name + "__+IÄIH§%NK " + password;
|
||||||
final MessageDigest md = HashUtils.getDigest(MessageDigestAlgorithm.SHA512);
|
final MessageDigest md = HashUtils.getDigest(MessageDigestAlgorithm.SHA512);
|
||||||
md.update(text.getBytes(charset), 0, text.length());
|
md.update(text.getBytes(charset), 0, text.length());
|
||||||
return new HashResult(byteArrayToHexString(md.digest()));
|
return new EncryptedPassword(byteArrayToHexString(md.digest()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,8 +20,8 @@ public class CryptPBKDF2 extends HexSaltedMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String unusedSalt, String unusedName) {
|
public boolean comparePassword(String password, EncryptedPassword encryptedPassword, String unusedName) {
|
||||||
String[] line = hash.split("\\$");
|
String[] line = encryptedPassword.getHash().split("\\$");
|
||||||
String salt = line[2];
|
String salt = line[2];
|
||||||
String derivedKey = line[3];
|
String derivedKey = line[3];
|
||||||
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 10000, derivedKey.getBytes());
|
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 10000, derivedKey.getBytes());
|
||||||
|
|||||||
@ -19,8 +19,8 @@ public class CryptPBKDF2Django extends HexSaltedMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String unusedSalt, String unusedName) {
|
public boolean comparePassword(String password, EncryptedPassword encryptedPassword, String unusedName) {
|
||||||
String[] line = hash.split("\\$");
|
String[] line = encryptedPassword.getHash().split("\\$");
|
||||||
String salt = line[2];
|
String salt = line[2];
|
||||||
byte[] derivedKey = DatatypeConverter.parseBase64Binary(line[3]);
|
byte[] derivedKey = DatatypeConverter.parseBase64Binary(line[3]);
|
||||||
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 15000, derivedKey);
|
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 15000, derivedKey);
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package fr.xephi.authme.security.crypts;
|
|||||||
/**
|
/**
|
||||||
* The result of a hash computation. See {@link #salt} for details.
|
* The result of a hash computation. See {@link #salt} for details.
|
||||||
*/
|
*/
|
||||||
public class HashResult {
|
public class EncryptedPassword {
|
||||||
|
|
||||||
/** The generated hash. */
|
/** The generated hash. */
|
||||||
private final String hash;
|
private final String hash;
|
||||||
@ -23,7 +23,7 @@ public class HashResult {
|
|||||||
* @param hash The computed hash
|
* @param hash The computed hash
|
||||||
* @param salt The generated salt
|
* @param salt The generated salt
|
||||||
*/
|
*/
|
||||||
public HashResult(String hash, String salt) {
|
public EncryptedPassword(String hash, String salt) {
|
||||||
this.hash = hash;
|
this.hash = hash;
|
||||||
this.salt = salt;
|
this.salt = salt;
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ public class HashResult {
|
|||||||
*
|
*
|
||||||
* @param hash The computed hash
|
* @param hash The computed hash
|
||||||
*/
|
*/
|
||||||
public HashResult(String hash) {
|
public EncryptedPassword(String hash) {
|
||||||
this(hash, null);
|
this(hash, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12,9 +12,9 @@ public interface EncryptionMethod {
|
|||||||
* @param name The name of the player (sometimes required to generate a salt with)
|
* @param name The name of the player (sometimes required to generate a salt with)
|
||||||
*
|
*
|
||||||
* @return The hash result for the password.
|
* @return The hash result for the password.
|
||||||
* @see HashResult
|
* @see EncryptedPassword
|
||||||
*/
|
*/
|
||||||
HashResult computeHash(String password, String name);
|
EncryptedPassword computeHash(String password, String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash the given password with the given salt for the given player.
|
* Hash the given password with the given salt for the given player.
|
||||||
@ -31,14 +31,13 @@ public interface EncryptionMethod {
|
|||||||
/**
|
/**
|
||||||
* Check whether the given hash matches the clear-text password.
|
* Check whether the given hash matches the clear-text password.
|
||||||
*
|
*
|
||||||
* @param hash The hash to verify
|
* @param password The clear-text password to verify
|
||||||
* @param password The clear-text password to verify the hash against
|
* @param encryptedPassword The hash to check the password against
|
||||||
* @param salt The salt if it is stored separately (null otherwise)
|
* @param name The player name to do the check for (sometimes required for generating the salt)
|
||||||
* @param name The player name to do the check for (sometimes required for generating the salt)
|
|
||||||
*
|
*
|
||||||
* @return True if the password matches, false otherwise
|
* @return True if the password matches, false otherwise
|
||||||
*/
|
*/
|
||||||
boolean comparePassword(String hash, String password, String salt, String name);
|
boolean comparePassword(String password, EncryptedPassword encryptedPassword, String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a new salt to hash a password with.
|
* Generate a new salt to hash a password with.
|
||||||
@ -49,7 +48,7 @@ public interface EncryptionMethod {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether the encryption method requires the salt to be stored separately and
|
* Return whether the encryption method requires the salt to be stored separately and
|
||||||
* passed again to {@link #comparePassword(String, String, String, String)}. Note that
|
* passed again to {@link #comparePassword(String, EncryptedPassword, String)}. Note that
|
||||||
* an encryption method returning {@code false} does not imply that it uses no salt; it
|
* an encryption method returning {@code false} does not imply that it uses no salt; it
|
||||||
* may be embedded into the hash or it may use the username as salt.
|
* may be embedded into the hash or it may use the username as salt.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -20,13 +20,13 @@ public abstract class HexSaltedMethod implements EncryptionMethod {
|
|||||||
public abstract String computeHash(String password, String salt, String name);
|
public abstract String computeHash(String password, String salt, String name);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashResult computeHash(String password, String name) {
|
public EncryptedPassword computeHash(String password, String name) {
|
||||||
String salt = generateSalt();
|
String salt = generateSalt();
|
||||||
return new HashResult(computeHash(password, salt, null));
|
return new EncryptedPassword(computeHash(password, salt, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract boolean comparePassword(String hash, String password, String salt, String name);
|
public abstract boolean comparePassword(String password, EncryptedPassword encryptedPassword, String name);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String generateSalt() {
|
public String generateSalt() {
|
||||||
|
|||||||
@ -13,7 +13,8 @@ public class JOOMLA extends HexSaltedMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String unusedSalt, String unusedName) {
|
public boolean comparePassword(String password, EncryptedPassword encryptedPassword, String unusedName) {
|
||||||
|
String hash = encryptedPassword.getHash();
|
||||||
String[] hashParts = hash.split(":");
|
String[] hashParts = hash.split(":");
|
||||||
return hashParts.length == 2 && hash.equals(computeHash(password, hashParts[1], null));
|
return hashParts.length == 2 && hash.equals(computeHash(password, hashParts[1], null));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,8 @@ public class MD5VB extends HexSaltedMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
public boolean comparePassword(String password, EncryptedPassword encryptedPassword, String name) {
|
||||||
|
String hash = encryptedPassword.getHash();
|
||||||
String[] line = hash.split("\\$");
|
String[] line = hash.split("\\$");
|
||||||
return line.length == 4 && hash.equals(computeHash(password, line[2], name));
|
return line.length == 4 && hash.equals(computeHash(password, line[2], name));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -144,8 +144,8 @@ public class PHPBB extends HexSaltedMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
public boolean comparePassword(String password, EncryptedPassword encryptedPassword, String name) {
|
||||||
return phpbb_check_hash(password, hash);
|
return phpbb_check_hash(password, encryptedPassword.getHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -14,7 +14,8 @@ public class SHA256 extends HexSaltedMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String salt, String playerName) {
|
public boolean comparePassword(String password, EncryptedPassword encryptedPassword, String playerName) {
|
||||||
|
String hash = encryptedPassword.getHash();
|
||||||
String[] line = hash.split("\\$");
|
String[] line = hash.split("\\$");
|
||||||
return line.length == 4 && hash.equals(computeHash(password, line[2], ""));
|
return line.length == 4 && hash.equals(computeHash(password, line[2], ""));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,8 @@ import fr.xephi.authme.security.HashUtils;
|
|||||||
|
|
||||||
public class SMF extends UsernameSaltMethod {
|
public class SMF extends UsernameSaltMethod {
|
||||||
|
|
||||||
public HashResult computeHash(String password, String name) {
|
public EncryptedPassword computeHash(String password, String name) {
|
||||||
return new HashResult(HashUtils.sha1(name.toLowerCase() + password));
|
return new EncryptedPassword(HashUtils.sha1(name.toLowerCase() + password));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,14 +12,14 @@ public abstract class SeparateSaltMethod implements EncryptionMethod {
|
|||||||
public abstract String generateSalt();
|
public abstract String generateSalt();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashResult computeHash(String password, String name) {
|
public EncryptedPassword computeHash(String password, String name) {
|
||||||
String salt = generateSalt();
|
String salt = generateSalt();
|
||||||
return new HashResult(computeHash(password, salt, name), salt);
|
return new EncryptedPassword(computeHash(password, salt, name), salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
public boolean comparePassword(String password, EncryptedPassword encryptedPassword, String name) {
|
||||||
return hash.equals(computeHash(password, salt, null));
|
return encryptedPassword.getHash().equals(computeHash(password, encryptedPassword.getSalt(), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -15,8 +15,8 @@ public abstract class UnsaltedMethod implements EncryptionMethod {
|
|||||||
public abstract String computeHash(String password);
|
public abstract String computeHash(String password);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashResult computeHash(String password, String name) {
|
public EncryptedPassword computeHash(String password, String name) {
|
||||||
return new HashResult(computeHash(password));
|
return new EncryptedPassword(computeHash(password));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -25,8 +25,8 @@ public abstract class UnsaltedMethod implements EncryptionMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
public boolean comparePassword(String password, EncryptedPassword encryptedPassword, String name) {
|
||||||
return hash.equals(computeHash(password));
|
return encryptedPassword.getHash().equals(computeHash(password));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -7,18 +7,18 @@ import fr.xephi.authme.security.crypts.description.Usage;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Common supertype of encryption methods that use a player's username
|
* Common supertype of encryption methods that use a player's username
|
||||||
* (or something based on it) as salt.
|
* (or something based on it) as embedded salt.
|
||||||
*/
|
*/
|
||||||
@Recommendation(Usage.DO_NOT_USE)
|
@Recommendation(Usage.DO_NOT_USE)
|
||||||
@HasSalt(SaltType.USERNAME)
|
@HasSalt(SaltType.USERNAME)
|
||||||
public abstract class UsernameSaltMethod implements EncryptionMethod {
|
public abstract class UsernameSaltMethod implements EncryptionMethod {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract HashResult computeHash(String password, String name);
|
public abstract EncryptedPassword computeHash(String password, String name);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
public boolean comparePassword(String password, EncryptedPassword encryptedPassword, String name) {
|
||||||
return hash.equals(computeHash(password, name).getHash());
|
return encryptedPassword.getHash().equals(computeHash(password, name).getHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -12,8 +12,8 @@ public class WBB4 extends HexSaltedMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String salt, String playerName) {
|
public boolean comparePassword(String password, EncryptedPassword encryptedPassword, String playerName) {
|
||||||
return BCRYPT.checkpw(password, hash, 2);
|
return BCRYPT.checkpw(password, encryptedPassword.getHash(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -117,7 +117,8 @@ public class WORDPRESS extends UnsaltedMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
public boolean comparePassword(String password, EncryptedPassword encryptedPassword, String name) {
|
||||||
|
String hash = encryptedPassword.getHash();
|
||||||
String comparedHash = crypt(password, hash);
|
String comparedHash = crypt(password, hash);
|
||||||
return comparedHash.equals(hash);
|
return comparedHash.equals(hash);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,8 @@ public class XAUTH extends HexSaltedMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String hash, String password, String salt, String playerName) {
|
public boolean comparePassword(String password, EncryptedPassword encryptedPassword, String playerName) {
|
||||||
|
String hash = encryptedPassword.getHash();
|
||||||
int saltPos = (password.length() >= hash.length() ? hash.length() - 1 : password.length());
|
int saltPos = (password.length() >= hash.length() ? hash.length() - 1 : password.length());
|
||||||
String saltFromHash = hash.substring(saltPos, saltPos + 12);
|
String saltFromHash = hash.substring(saltPos, saltPos + 12);
|
||||||
return hash.equals(computeHash(password, saltFromHash, null));
|
return hash.equals(computeHash(password, saltFromHash, null));
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import fr.xephi.authme.cache.auth.PlayerCache;
|
|||||||
import fr.xephi.authme.output.MessageKey;
|
import fr.xephi.authme.output.MessageKey;
|
||||||
import fr.xephi.authme.output.Messages;
|
import fr.xephi.authme.output.Messages;
|
||||||
import fr.xephi.authme.security.PasswordSecurity;
|
import fr.xephi.authme.security.PasswordSecurity;
|
||||||
import fr.xephi.authme.security.crypts.HashResult;
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@ -34,22 +34,21 @@ public class ChangePasswordTask implements Runnable {
|
|||||||
|
|
||||||
final String name = player.getName().toLowerCase();
|
final String name = player.getName().toLowerCase();
|
||||||
PlayerAuth auth = PlayerCache.getInstance().getAuth(name);
|
PlayerAuth auth = PlayerCache.getInstance().getAuth(name);
|
||||||
if (passwordSecurity.comparePassword(oldPassword, auth.getHash(), auth.getSalt(), player.getName())) {
|
if (passwordSecurity.comparePassword(oldPassword, auth.getPassword(), player.getName())) {
|
||||||
HashResult hashResult = passwordSecurity.computeHash(newPassword, name);
|
EncryptedPassword encryptedPassword = passwordSecurity.computeHash(newPassword, name);
|
||||||
auth.setHash(hashResult.getHash());
|
auth.setPassword(encryptedPassword);
|
||||||
auth.setSalt(hashResult.getSalt());
|
|
||||||
|
|
||||||
if (!plugin.getDataSource().updatePassword(auth)) {
|
if (!plugin.getDataSource().updatePassword(auth)) {
|
||||||
m.send(player, MessageKey.ERROR);
|
m.send(player, MessageKey.ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
plugin.getDataSource().updateSalt(auth);
|
|
||||||
PlayerCache.getInstance().updatePlayer(auth);
|
PlayerCache.getInstance().updatePlayer(auth);
|
||||||
m.send(player, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
m.send(player, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
||||||
ConsoleLogger.info(player.getName() + " changed his password");
|
ConsoleLogger.info(player.getName() + " changed his password");
|
||||||
if (Settings.bungee) {
|
if (Settings.bungee) {
|
||||||
final String hash = auth.getHash();
|
final String hash = encryptedPassword.getHash();
|
||||||
final String salt = auth.getSalt();
|
final String salt = encryptedPassword.getSalt();
|
||||||
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable(){
|
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable(){
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package fr.xephi.authme.security;
|
package fr.xephi.authme.security;
|
||||||
|
|
||||||
|
import fr.xephi.authme.security.crypts.EncryptedPassword;
|
||||||
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||||
import fr.xephi.authme.security.crypts.HashResult;
|
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.util.StringUtils;
|
import fr.xephi.authme.util.StringUtils;
|
||||||
import fr.xephi.authme.util.WrapperMock;
|
import fr.xephi.authme.util.WrapperMock;
|
||||||
@ -49,11 +49,11 @@ public class HashAlgorithmIntegrationTest {
|
|||||||
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
|
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
|
||||||
if (!HashAlgorithm.CUSTOM.equals(algorithm)) {
|
if (!HashAlgorithm.CUSTOM.equals(algorithm)) {
|
||||||
EncryptionMethod method = algorithm.getClazz().newInstance();
|
EncryptionMethod method = algorithm.getClazz().newInstance();
|
||||||
HashResult hashResult = method.computeHash("pwd", "name");
|
EncryptedPassword encryptedPassword = method.computeHash("pwd", "name");
|
||||||
assertThat("Salt should not be null if method.hasSeparateSalt(), and vice versa. Method: '"
|
assertThat("Salt should not be null if method.hasSeparateSalt(), and vice versa. Method: '"
|
||||||
+ method + "'", StringUtils.isEmpty(hashResult.getSalt()), equalTo(!method.hasSeparateSalt()));
|
+ method + "'", StringUtils.isEmpty(encryptedPassword.getSalt()), equalTo(!method.hasSeparateSalt()));
|
||||||
assertThat("Hash should not be empty for method '" + method + "'",
|
assertThat("Hash should not be empty for method '" + method + "'",
|
||||||
StringUtils.isEmpty(hashResult.getHash()), equalTo(false));
|
StringUtils.isEmpty(encryptedPassword.getHash()), equalTo(false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,47 +36,42 @@ public abstract class AbstractEncryptionMethodTest {
|
|||||||
/** The encryption method to test. */
|
/** The encryption method to test. */
|
||||||
private EncryptionMethod method;
|
private EncryptionMethod method;
|
||||||
/** Map with the hashes against which the entries in GIVEN_PASSWORDS are tested. */
|
/** Map with the hashes against which the entries in GIVEN_PASSWORDS are tested. */
|
||||||
private Map<String, String> hashes;
|
private Map<String, EncryptedPassword> hashes;
|
||||||
/** The accompanying salts for the hashes in {@link #hashes} if necessary. Can be empty otherwise. */
|
|
||||||
private Map<String, String> salts;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new test for the given encryption method.
|
* Create a new test for the given encryption method.
|
||||||
*
|
*
|
||||||
* @param method The encryption method to test
|
* @param method The encryption method to test
|
||||||
* @param hash0 The pre-generated hash for the first {@link #GIVEN_PASSWORDS}
|
* @param computedHashes The pre-generated hashes for the elements in {@link #GIVEN_PASSWORDS}
|
||||||
* @param hash1 The pre-generated hash for the second {@link #GIVEN_PASSWORDS}
|
|
||||||
* @param hash2 The pre-generated hash for the third {@link #GIVEN_PASSWORDS}
|
|
||||||
* @param hash3 The pre-generated hash for the fourth {@link #GIVEN_PASSWORDS}
|
|
||||||
*/
|
*/
|
||||||
public AbstractEncryptionMethodTest(EncryptionMethod method, String hash0, String hash1,
|
public AbstractEncryptionMethodTest(EncryptionMethod method, String... computedHashes) {
|
||||||
String hash2, String hash3) {
|
if (method.hasSeparateSalt()) {
|
||||||
// TODO #358: Throw if method.hasSeparateSalt() is true
|
throw new UnsupportedOperationException("Test must be initialized with EncryptedPassword objects if "
|
||||||
|
+ "the salt is stored separately. Use the other constructor");
|
||||||
|
} else if (computedHashes.length != GIVEN_PASSWORDS.length) {
|
||||||
|
throw new UnsupportedOperationException("Expected " + GIVEN_PASSWORDS.length + " hashes");
|
||||||
|
}
|
||||||
this.method = method;
|
this.method = method;
|
||||||
|
|
||||||
hashes = new HashMap<>();
|
hashes = new HashMap<>();
|
||||||
hashes.put(GIVEN_PASSWORDS[0], hash0);
|
for (int i = 0; i < GIVEN_PASSWORDS.length; ++i) {
|
||||||
hashes.put(GIVEN_PASSWORDS[1], hash1);
|
hashes.put(GIVEN_PASSWORDS[i], new EncryptedPassword(computedHashes[i]));
|
||||||
hashes.put(GIVEN_PASSWORDS[2], hash2);
|
}
|
||||||
hashes.put(GIVEN_PASSWORDS[3], hash3);
|
|
||||||
salts = new HashMap<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractEncryptionMethodTest(EncryptionMethod method, HashResult result0, HashResult result1,
|
public AbstractEncryptionMethodTest(EncryptionMethod method, EncryptedPassword result0, EncryptedPassword result1,
|
||||||
HashResult result2, HashResult result3) {
|
EncryptedPassword result2, EncryptedPassword result3) {
|
||||||
// TODO #358: Throw if method.hasSeparateSalt() is false
|
if (!method.hasSeparateSalt()) {
|
||||||
|
throw new UnsupportedOperationException("Salt is not stored separately, so test should be initialized"
|
||||||
|
+ " with the password hashes only. Use the other constructor");
|
||||||
|
}
|
||||||
this.method = method;
|
this.method = method;
|
||||||
|
|
||||||
hashes = new HashMap<>();
|
hashes = new HashMap<>();
|
||||||
hashes.put(GIVEN_PASSWORDS[0], result0.getHash());
|
hashes.put(GIVEN_PASSWORDS[0], result0);
|
||||||
hashes.put(GIVEN_PASSWORDS[1], result1.getHash());
|
hashes.put(GIVEN_PASSWORDS[1], result1);
|
||||||
hashes.put(GIVEN_PASSWORDS[2], result2.getHash());
|
hashes.put(GIVEN_PASSWORDS[2], result2);
|
||||||
hashes.put(GIVEN_PASSWORDS[3], result3.getHash());
|
hashes.put(GIVEN_PASSWORDS[3], result3);
|
||||||
|
|
||||||
salts = new HashMap<>();
|
|
||||||
salts.put(GIVEN_PASSWORDS[0], result0.getSalt());
|
|
||||||
salts.put(GIVEN_PASSWORDS[1], result1.getSalt());
|
|
||||||
salts.put(GIVEN_PASSWORDS[2], result2.getSalt());
|
|
||||||
salts.put(GIVEN_PASSWORDS[3], result3.getSalt());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -108,6 +103,7 @@ public abstract class AbstractEncryptionMethodTest {
|
|||||||
for (String password : internalPasswords) {
|
for (String password : internalPasswords) {
|
||||||
final String salt = method.generateSalt();
|
final String salt = method.generateSalt();
|
||||||
final String hash = method.computeHash(password, salt, USERNAME);
|
final String hash = method.computeHash(password, salt, USERNAME);
|
||||||
|
EncryptedPassword encryptedPassword = new EncryptedPassword(hash, salt);
|
||||||
|
|
||||||
// Check that the computeHash(password, salt, name) method has the same output for the returned salt
|
// Check that the computeHash(password, salt, name) method has the same output for the returned salt
|
||||||
if (testHashEqualityForSameSalt()) {
|
if (testHashEqualityForSameSalt()) {
|
||||||
@ -116,22 +112,20 @@ public abstract class AbstractEncryptionMethodTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("Generated hash for '" + password + "' should match password (hash = '" + hash + "')",
|
assertTrue("Generated hash for '" + password + "' should match password (hash = '" + hash + "')",
|
||||||
method.comparePassword(hash, password, salt, USERNAME));
|
method.comparePassword(password, encryptedPassword, USERNAME));
|
||||||
if (!password.equals(password.toLowerCase())) {
|
if (!password.equals(password.toLowerCase())) {
|
||||||
assertFalse("Lower-case of '" + password + "' should not match generated hash '" + hash + "'",
|
assertFalse("Lower-case of '" + password + "' should not match generated hash '" + hash + "'",
|
||||||
method.comparePassword(hash, password.toLowerCase(), salt, USERNAME));
|
method.comparePassword(password.toLowerCase(), encryptedPassword, USERNAME));
|
||||||
}
|
}
|
||||||
if (!password.equals(password.toUpperCase())) {
|
if (!password.equals(password.toUpperCase())) {
|
||||||
assertFalse("Upper-case of '" + password + "' should not match generated hash '" + hash + "'",
|
assertFalse("Upper-case of '" + password + "' should not match generated hash '" + hash + "'",
|
||||||
method.comparePassword(hash, password.toUpperCase(), salt, USERNAME));
|
method.comparePassword(password.toUpperCase(), encryptedPassword, USERNAME));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doesGivenHashMatch(String password, EncryptionMethod method) {
|
private boolean doesGivenHashMatch(String password, EncryptionMethod method) {
|
||||||
String hash = hashes.get(password);
|
return method.comparePassword(password, hashes.get(password), USERNAME);
|
||||||
String salt = salts.get(password);
|
|
||||||
return method.comparePassword(hash, password, salt, USERNAME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @org.junit.Test public void a() { AbstractEncryptionMethodTest.generateTest(); }
|
// @org.junit.Test public void a() { AbstractEncryptionMethodTest.generateTest(); }
|
||||||
@ -150,9 +144,9 @@ public abstract class AbstractEncryptionMethodTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (method.hasSeparateSalt()) {
|
if (method.hasSeparateSalt()) {
|
||||||
HashResult hashResult = method.computeHash(password, USERNAME);
|
EncryptedPassword encryptedPassword = method.computeHash(password, USERNAME);
|
||||||
System.out.println(String.format("\t\tnew HashResult(\"%s\", \"%s\")%s// %s",
|
System.out.println(String.format("\t\tnew EncryptedPassword(\"%s\", \"%s\")%s// %s",
|
||||||
hashResult.getHash(), hashResult.getSalt(), delim, password));
|
encryptedPassword.getHash(), encryptedPassword.getSalt(), delim, password));
|
||||||
} else {
|
} else {
|
||||||
System.out.println("\t\t\"" + method.computeHash(password, USERNAME).getHash()
|
System.out.println("\t\t\"" + method.computeHash(password, USERNAME).getHash()
|
||||||
+ "\"" + delim + "// " + password);
|
+ "\"" + delim + "// " + password);
|
||||||
|
|||||||
@ -7,10 +7,10 @@ public class IPB3Test extends AbstractEncryptionMethodTest {
|
|||||||
|
|
||||||
public IPB3Test() {
|
public IPB3Test() {
|
||||||
super(new IPB3(),
|
super(new IPB3(),
|
||||||
new HashResult("f8ecea1ce42b5babef369ff7692dbe3f", "1715b"), //password
|
new EncryptedPassword("f8ecea1ce42b5babef369ff7692dbe3f", "1715b"), //password
|
||||||
new HashResult("40a93731a931352e0619cdf09b975040", "ba91c"), //PassWord1
|
new EncryptedPassword("40a93731a931352e0619cdf09b975040", "ba91c"), //PassWord1
|
||||||
new HashResult("a77ca982373946d5800430bd2947ba11", "a7725"), //&^%te$t?Pw@_
|
new EncryptedPassword("a77ca982373946d5800430bd2947ba11", "a7725"), //&^%te$t?Pw@_
|
||||||
new HashResult("383d7b9e2b707d6e894ec7b30e3032c3", "fa9fd")); //âË_3(íù*
|
new EncryptedPassword("383d7b9e2b707d6e894ec7b30e3032c3", "fa9fd")); //âË_3(íù*
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,10 +7,10 @@ public class MYBBTest extends AbstractEncryptionMethodTest {
|
|||||||
|
|
||||||
public MYBBTest() {
|
public MYBBTest() {
|
||||||
super(new MYBB(),
|
super(new MYBB(),
|
||||||
new HashResult("57c7a16d860833db5030738f5a465d2b", "acdc14e6"), //password
|
new EncryptedPassword("57c7a16d860833db5030738f5a465d2b", "acdc14e6"), //password
|
||||||
new HashResult("08fbdf721f2c42d9780b7d66df0ba830", "792fd7fb"), //PassWord1
|
new EncryptedPassword("08fbdf721f2c42d9780b7d66df0ba830", "792fd7fb"), //PassWord1
|
||||||
new HashResult("d602f38fb59ad9e185d5604f5d4ddb36", "4b5534a4"), //&^%te$t?Pw@_
|
new EncryptedPassword("d602f38fb59ad9e185d5604f5d4ddb36", "4b5534a4"), //&^%te$t?Pw@_
|
||||||
new HashResult("b3c39410d0ab8ae2a65c257820797fad", "e5a6cb14")); //âË_3(íù*
|
new EncryptedPassword("b3c39410d0ab8ae2a65c257820797fad", "e5a6cb14")); //âË_3(íù*
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,10 +7,10 @@ public class PHPFUSIONTest extends AbstractEncryptionMethodTest {
|
|||||||
|
|
||||||
public PHPFUSIONTest() {
|
public PHPFUSIONTest() {
|
||||||
super(new PHPFUSION(),
|
super(new PHPFUSION(),
|
||||||
new HashResult("f7a606c4eb3fcfbc382906476e05b06f21234a77d1a4eacc0f93f503deb69e70", "6cd1c97c55cb"), // password
|
new EncryptedPassword("f7a606c4eb3fcfbc382906476e05b06f21234a77d1a4eacc0f93f503deb69e70", "6cd1c97c55cb"), // password
|
||||||
new HashResult("8a9b7bb706a3347e5f684a7cb905bfb26b9a0d099358064139ab3ed1a66aeb2b", "d6012370b73f"), // PassWord1
|
new EncryptedPassword("8a9b7bb706a3347e5f684a7cb905bfb26b9a0d099358064139ab3ed1a66aeb2b", "d6012370b73f"), // PassWord1
|
||||||
new HashResult("43f2f23f44c8f89e2dbf06050bc8c77dbcdf71a7b5d28c87ec657d474e63d62d", "f75400a209a4"), // &^%te$t?Pw@_
|
new EncryptedPassword("43f2f23f44c8f89e2dbf06050bc8c77dbcdf71a7b5d28c87ec657d474e63d62d", "f75400a209a4"), // &^%te$t?Pw@_
|
||||||
new HashResult("4e7f4eb7e3653d7460f1cf590def4153c6fcdf8b8e16fb95538fdf9e54a95245", "d552e0f5b23a")); // âË_3(íù*
|
new EncryptedPassword("4e7f4eb7e3653d7460f1cf590def4153c6fcdf8b8e16fb95538fdf9e54a95245", "d552e0f5b23a")); // âË_3(íù*
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,10 +17,10 @@ public class SALTED2MD5Test extends AbstractEncryptionMethodTest {
|
|||||||
|
|
||||||
public SALTED2MD5Test() {
|
public SALTED2MD5Test() {
|
||||||
super(new SALTED2MD5(),
|
super(new SALTED2MD5(),
|
||||||
new HashResult("9f3d13dc01a6fe61fd669954174399f3", "9b5f5749"), // password
|
new EncryptedPassword("9f3d13dc01a6fe61fd669954174399f3", "9b5f5749"), // password
|
||||||
new HashResult("b28c32f624a4eb161d6adc9acb5bfc5b", "f750ba32"), // PassWord1
|
new EncryptedPassword("b28c32f624a4eb161d6adc9acb5bfc5b", "f750ba32"), // PassWord1
|
||||||
new HashResult("38dcb83cc68424afe3cda012700c2bb1", "eb2c3394"), // &^%te$t?Pw@_
|
new EncryptedPassword("38dcb83cc68424afe3cda012700c2bb1", "eb2c3394"), // &^%te$t?Pw@_
|
||||||
new HashResult("ad25606eae5b760c8a2469d65578ac39", "04eee598")); // âË_3(íù*)
|
new EncryptedPassword("ad25606eae5b760c8a2469d65578ac39", "04eee598")); // âË_3(íù*)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,10 +7,10 @@ public class SALTEDSHA512Test extends AbstractEncryptionMethodTest {
|
|||||||
|
|
||||||
public SALTEDSHA512Test() {
|
public SALTEDSHA512Test() {
|
||||||
super(new SALTEDSHA512(),
|
super(new SALTEDSHA512(),
|
||||||
new HashResult("dea7a37cecf5384ae8e347fd1411efb51364b6ba1b328695de3b354612c1d7010807e8b7051c40f740e498490e1f133e2c2408327d13fbdd68e1b1f6d548e624", "29f8a3c52147f987fee7ba3e0fb311bd"), // password
|
new EncryptedPassword("dea7a37cecf5384ae8e347fd1411efb51364b6ba1b328695de3b354612c1d7010807e8b7051c40f740e498490e1f133e2c2408327d13fbdd68e1b1f6d548e624", "29f8a3c52147f987fee7ba3e0fb311bd"), // password
|
||||||
new HashResult("7c06225aac574d2dc7c81a2ed306637adf025715f52083e05bdab014faaa234e24a97d0e69ea0108dfa77cc9228e58be319ee677e679b5d1ad168d40e50a42f6", "8ea37b85d020b98f60c0fe9b8ec9296c"), // PassWord1
|
new EncryptedPassword("7c06225aac574d2dc7c81a2ed306637adf025715f52083e05bdab014faaa234e24a97d0e69ea0108dfa77cc9228e58be319ee677e679b5d1ad168d40e50a42f6", "8ea37b85d020b98f60c0fe9b8ec9296c"), // PassWord1
|
||||||
new HashResult("55711adbe03c9616f3505f0d57077fdd528c32243eb6f9840c1a6ff9e553940d6b89790750ebd52ebda63ca793fbe9980d54057af40836820c648750fe22d49c", "9f58079631ef21d32b4710694f1f461b"), // &^%te$t?Pw@_
|
new EncryptedPassword("55711adbe03c9616f3505f0d57077fdd528c32243eb6f9840c1a6ff9e553940d6b89790750ebd52ebda63ca793fbe9980d54057af40836820c648750fe22d49c", "9f58079631ef21d32b4710694f1f461b"), // &^%te$t?Pw@_
|
||||||
new HashResult("29dc5be8702975ea4563ed3de5b145e2d2f1c37ae661bbe0d3e94d964402cf09d539d65f3b90ff6921ea3d40727f76fb38fb34d1e5c2d62238c4e0203efc372f", "048bb76168265d906f1fd1f81d0616a9")); // âË_3(íù*
|
new EncryptedPassword("29dc5be8702975ea4563ed3de5b145e2d2f1c37ae661bbe0d3e94d964402cf09d539d65f3b90ff6921ea3d40727f76fb38fb34d1e5c2d62238c4e0203efc372f", "048bb76168265d906f1fd1f81d0616a9")); // âË_3(íù*
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,10 +7,10 @@ public class WBB3Test extends AbstractEncryptionMethodTest {
|
|||||||
|
|
||||||
public WBB3Test() {
|
public WBB3Test() {
|
||||||
super(new WBB3(),
|
super(new WBB3(),
|
||||||
new HashResult("8df818ef7d56075ab2744f74b98ad68a375ccac4", "b7415b355492ea60314f259a35733a3092c03e3f"), // password
|
new EncryptedPassword("8df818ef7d56075ab2744f74b98ad68a375ccac4", "b7415b355492ea60314f259a35733a3092c03e3f"), // password
|
||||||
new HashResult("106da5cf5df92cb845e12cf62cbdb5235b6dc693", "6110f19b2b52910dccf592a19c59126873f42e69"), // PassWord1
|
new EncryptedPassword("106da5cf5df92cb845e12cf62cbdb5235b6dc693", "6110f19b2b52910dccf592a19c59126873f42e69"), // PassWord1
|
||||||
new HashResult("940a9fb7acec0178c6691e8b3c14bd7d789078b1", "f9dd501ff3d1bf74904f9e89649e378429af56e7"), // &^%te$t?Pw@_
|
new EncryptedPassword("940a9fb7acec0178c6691e8b3c14bd7d789078b1", "f9dd501ff3d1bf74904f9e89649e378429af56e7"), // &^%te$t?Pw@_
|
||||||
new HashResult("0fa12e8d96c9e95f73aa91f3b76f8cdc815ec8a5", "736be8669f6159ddb2d5b47a3e6428cdb8b324de")); // âË_3(íù*
|
new EncryptedPassword("0fa12e8d96c9e95f73aa91f3b76f8cdc815ec8a5", "736be8669f6159ddb2d5b47a3e6428cdb8b324de")); // âË_3(íù*
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user