mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-12-22 08:37:49 +01:00
Update 2.9.3
* Fix BungeeCord again * Remove useless part of api * Fix register api method * Always store cache with lowercase players name * Remove some useless asynchronous part * Fix some thread problems * Add PBKDF2 method * Fix SQLite problem (world duplicate column) * Fix cannot measure distance between two different world
This commit is contained in:
parent
2522357982
commit
7e7afcbfd6
2
pom.xml
2
pom.xml
@ -24,7 +24,7 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<version>2.9.2</version>
|
||||
<version>2.9.3</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
|
@ -134,7 +134,7 @@ public class Management {
|
||||
.getLimboPlayer(name);
|
||||
final PlayerAuth getAuth = database.getAuth(name);
|
||||
if (limbo != null) {
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -161,7 +161,7 @@ public class Management {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -189,7 +189,7 @@ public class Management {
|
||||
.contains(player.getWorld()
|
||||
.getName())) {
|
||||
final Location spawnL = spawnLoc;
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -222,7 +222,7 @@ public class Management {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -244,7 +244,7 @@ public class Management {
|
||||
});
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -256,7 +256,7 @@ public class Management {
|
||||
|
||||
if (Settings.protectInventoryBeforeLogInEnabled
|
||||
&& player.hasPlayedBefore()) {
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -312,7 +312,7 @@ public class Management {
|
||||
pllog.save();
|
||||
} catch (NullPointerException ex) {
|
||||
}
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -343,7 +343,7 @@ public class Management {
|
||||
"[AuthMe] " + player.getName()
|
||||
+ " logged in!"));
|
||||
}
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -359,7 +359,7 @@ public class Management {
|
||||
try {
|
||||
final int gm = AuthMePlayerListener.gameMode
|
||||
.get(name);
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -369,7 +369,7 @@ public class Management {
|
||||
});
|
||||
} catch (NullPointerException npe) {
|
||||
}
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -393,7 +393,7 @@ public class Management {
|
||||
.getLimboPlayer(name);
|
||||
if (limbo != null) {
|
||||
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -428,7 +428,7 @@ public class Management {
|
||||
database.getAuth(name)
|
||||
.getQuitLocZ() + 0.5D);
|
||||
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -448,7 +448,7 @@ public class Management {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -473,7 +473,7 @@ public class Management {
|
||||
&& Settings.getForcedWorlds.contains(player
|
||||
.getWorld().getName())) {
|
||||
final Location spawnL = spawnLoc;
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -510,7 +510,7 @@ public class Management {
|
||||
database.getAuth(name).getQuitLocX() + 0.5D,
|
||||
database.getAuth(name).getQuitLocY() + 0.5D,
|
||||
database.getAuth(name).getQuitLocZ() + 0.5D);
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -528,7 +528,7 @@ public class Management {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -547,7 +547,7 @@ public class Management {
|
||||
});
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -559,7 +559,7 @@ public class Management {
|
||||
|
||||
if (Settings.protectInventoryBeforeLogInEnabled
|
||||
&& player.hasPlayedBefore()) {
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -612,7 +612,7 @@ public class Management {
|
||||
pllog.save();
|
||||
} catch (NullPointerException ex) {
|
||||
}
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Bukkit.getServer()
|
||||
@ -638,7 +638,7 @@ public class Management {
|
||||
"[AuthMe] " + player.getName()
|
||||
+ " logged in!"));
|
||||
}
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
player.saveData();
|
||||
|
@ -11,7 +11,6 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import uk.org.whoami.authme.AuthMe;
|
||||
import uk.org.whoami.authme.ConsoleLogger;
|
||||
import uk.org.whoami.authme.Utils;
|
||||
import uk.org.whoami.authme.cache.auth.PlayerAuth;
|
||||
import uk.org.whoami.authme.cache.auth.PlayerCache;
|
||||
@ -73,65 +72,9 @@ public class API {
|
||||
return Utils.getInstance().isUnrestricted(player);
|
||||
}
|
||||
|
||||
public static boolean isChatAllowed() {
|
||||
return Settings.isChatAllowed;
|
||||
}
|
||||
|
||||
public static boolean isAllowRestrictedIp() {
|
||||
return Settings.isAllowRestrictedIp;
|
||||
}
|
||||
|
||||
public static boolean isBackupActivated() {
|
||||
return Settings.isBackupActivated;
|
||||
}
|
||||
|
||||
public static boolean isForceSpawnLocOnJoinEnabled() {
|
||||
return Settings.isForceSpawnLocOnJoinEnabled;
|
||||
}
|
||||
|
||||
public static DataSourceType getDataSource() {
|
||||
return Settings.getDataSource;
|
||||
}
|
||||
|
||||
public static int getMovementRadius() {
|
||||
return Settings.getMovementRadius;
|
||||
}
|
||||
|
||||
public static List<String> getJoinPermissions() {
|
||||
return Settings.getJoinPermissions;
|
||||
}
|
||||
|
||||
public static Boolean isPasspartuEnable() {
|
||||
return Settings.enablePasspartu;
|
||||
}
|
||||
|
||||
public static String getcUnrestrictedName() {
|
||||
return Settings.getcUnrestrictedName;
|
||||
}
|
||||
|
||||
public static Boolean getEnablePasswordVerifier() {
|
||||
return Settings.getEnablePasswordVerifier;
|
||||
}
|
||||
|
||||
public static int getMaxNickLength() {
|
||||
return Settings.getMaxNickLength;
|
||||
}
|
||||
|
||||
public static int getMinNickLength() {
|
||||
return Settings.getMinNickLength;
|
||||
}
|
||||
|
||||
public static Array getLastLocationColumns() {
|
||||
Array columns = null;
|
||||
Array.set(columns, 0, Settings.getMySQLlastlocX);
|
||||
Array.set(columns, 1, Settings.getMySQLlastlocY);
|
||||
Array.set(columns, 2, Settings.getMySQLlastlocZ);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Location getLastLocation(Player player) {
|
||||
try {
|
||||
PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName());
|
||||
PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName().toLowerCase());
|
||||
|
||||
if (auth != null) {
|
||||
Location loc = new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY() , auth.getQuitLocZ());
|
||||
@ -145,30 +88,6 @@ public class API {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getNickRegex() {
|
||||
return Settings.getNickRegex;
|
||||
}
|
||||
|
||||
public static int getPasswordMinLen() {
|
||||
return Settings.getPasswordMinLen;
|
||||
}
|
||||
|
||||
public static HashAlgorithm getPasswordHash() {
|
||||
return Settings.getPasswordHash;
|
||||
}
|
||||
|
||||
public static int getRegistrationTimeout() {
|
||||
return Settings.getRegistrationTimeout;
|
||||
}
|
||||
|
||||
public static int getSessionTimeout() {
|
||||
return Settings.getSessionTimeout;
|
||||
}
|
||||
|
||||
public static String getUnloggedinGroup() {
|
||||
return Settings.getUnloggedinGroup;
|
||||
}
|
||||
|
||||
public static void setPlayerInventory(Player player, ItemStack[] content, ItemStack[] armor) {
|
||||
try {
|
||||
player.getInventory().setContents(content);
|
||||
@ -214,7 +133,7 @@ public class API {
|
||||
try {
|
||||
String name = playerName.toLowerCase();
|
||||
String hash = PasswordSecurity.getHash(Settings.getPasswordHash, password, name);
|
||||
if (database.isAuthAvailable(name)) {
|
||||
if (isRegistered(name)) {
|
||||
return false;
|
||||
}
|
||||
PlayerAuth auth = new PlayerAuth(name, hash, "198.18.0.1", 0);
|
||||
|
@ -220,5 +220,13 @@ public class PlayerAuth {
|
||||
public String getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String s = "Player : " + nickname + " ! IP : " + ip + " ! LastLogin : " + lastLogin + " ! LastPosition : " + x + "," + y + "," + z + "," + world
|
||||
+ " ! Email : " + email + " ! Hash : " + hash + " ! Salt : " + salt;
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,24 +28,24 @@ public class PlayerCache {
|
||||
}
|
||||
|
||||
public void addPlayer(PlayerAuth auth) {
|
||||
cache.put(auth.getNickname(), auth);
|
||||
cache.put(auth.getNickname().toLowerCase(), auth);
|
||||
}
|
||||
|
||||
public void updatePlayer(PlayerAuth auth) {
|
||||
cache.remove(auth.getNickname());
|
||||
cache.put(auth.getNickname(), auth);
|
||||
cache.remove(auth.getNickname().toLowerCase());
|
||||
cache.put(auth.getNickname().toLowerCase(), auth);
|
||||
}
|
||||
|
||||
public void removePlayer(String user) {
|
||||
cache.remove(user);
|
||||
cache.remove(user.toLowerCase());
|
||||
}
|
||||
|
||||
public boolean isAuthenticated(String user) {
|
||||
return cache.containsKey(user);
|
||||
return cache.containsKey(user.toLowerCase());
|
||||
}
|
||||
|
||||
public PlayerAuth getAuth(String user) {
|
||||
return cache.get(user);
|
||||
return cache.get(user.toLowerCase());
|
||||
}
|
||||
|
||||
public static PlayerCache getInstance() {
|
||||
|
@ -176,7 +176,7 @@ public class AdminCommand implements CommandExecutor {
|
||||
if (!args[1].contains(".")) {
|
||||
final CommandSender fSender = sender;
|
||||
final String[] arguments = args;
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerAuth pAuth = null;
|
||||
@ -219,7 +219,7 @@ public class AdminCommand implements CommandExecutor {
|
||||
} else {
|
||||
final CommandSender fSender = sender;
|
||||
final String[] arguments = args;
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String message = "[AuthMe] ";
|
||||
@ -344,12 +344,16 @@ public class AdminCommand implements CommandExecutor {
|
||||
bannedPlayers.add(off.getName().toLowerCase());
|
||||
}
|
||||
final List<String> bP = bannedPlayers;
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
database.purgeBanned(bP);
|
||||
}
|
||||
});
|
||||
if (database instanceof Thread) {
|
||||
database.purgeBanned(bP);
|
||||
} else {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
database.purgeBanned(bP);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (args[0].equalsIgnoreCase("spawn")) {
|
||||
try {
|
||||
if (sender instanceof Player) {
|
||||
|
@ -172,13 +172,18 @@ public class EmailCommand implements CommandExecutor {
|
||||
}
|
||||
final String finalhashnew = hashnew;
|
||||
final PlayerAuth finalauth = auth;
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
finalauth.setHash(finalhashnew);
|
||||
data.updatePassword(finalauth);
|
||||
}
|
||||
});
|
||||
if (data instanceof Thread) {
|
||||
finalauth.setHash(hashnew);
|
||||
data.updatePassword(auth);
|
||||
} else {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
finalauth.setHash(finalhashnew);
|
||||
data.updatePassword(finalauth);
|
||||
}
|
||||
});
|
||||
}
|
||||
plugin.mail.main(auth, thePass);
|
||||
player.sendMessage(m._("email_send"));
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
|
@ -100,7 +100,7 @@ public class UnregisterCommand implements CommandExecutor {
|
||||
BukkitTask id = sched.runTaskLater(plugin, new TimeoutTask(plugin, name), delay);
|
||||
LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id.getTaskId());
|
||||
}
|
||||
sched.runTask(plugin, new MessageTask(plugin, name, m._("reg_msg"), interval));
|
||||
sched.scheduleSyncDelayedTask(plugin, new MessageTask(plugin, name, m._("reg_msg"), interval));
|
||||
if(!Settings.unRegisteredGroup.isEmpty()){
|
||||
Utils.getInstance().setGroup(player, Utils.groupType.UNREGISTERED);
|
||||
}
|
||||
|
@ -153,8 +153,8 @@ private synchronized Connection getConnection3() throws SQLException {
|
||||
else {
|
||||
pconn = dataSource.getPooledConnection();
|
||||
pconn.addConnectionEventListener(poolConnectionEventListener); }
|
||||
activeConnections++;
|
||||
Connection conn = pconn.getConnection();
|
||||
activeConnections++;
|
||||
assertInnerState();
|
||||
return conn; }
|
||||
|
||||
|
@ -283,7 +283,7 @@ public class MySQLDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSession(PlayerAuth auth) {
|
||||
public synchronized boolean updateSession(PlayerAuth auth) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
try {
|
||||
@ -307,7 +307,7 @@ public class MySQLDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int purgeDatabase(long until) {
|
||||
public synchronized int purgeDatabase(long until) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
try {
|
||||
@ -350,7 +350,7 @@ public class MySQLDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateQuitLoc(PlayerAuth auth) {
|
||||
public synchronized boolean updateQuitLoc(PlayerAuth auth) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
try {
|
||||
@ -376,7 +376,7 @@ public class MySQLDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIps(String ip) {
|
||||
public synchronized int getIps(String ip) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
ResultSet rs = null;
|
||||
@ -405,7 +405,7 @@ public class MySQLDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateEmail(PlayerAuth auth) {
|
||||
public synchronized boolean updateEmail(PlayerAuth auth) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
try {
|
||||
@ -428,7 +428,7 @@ public class MySQLDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSalt(PlayerAuth auth) {
|
||||
public synchronized boolean updateSalt(PlayerAuth auth) {
|
||||
if (columnSalt.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
@ -497,7 +497,7 @@ public class MySQLDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllAuthsByName(PlayerAuth auth) {
|
||||
public synchronized List<String> getAllAuthsByName(PlayerAuth auth) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
ResultSet rs = null;
|
||||
@ -526,7 +526,7 @@ public class MySQLDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllAuthsByIp(String ip) {
|
||||
public synchronized List<String> getAllAuthsByIp(String ip) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
ResultSet rs = null;
|
||||
@ -555,7 +555,7 @@ public class MySQLDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllAuthsByEmail(String email) {
|
||||
public synchronized List<String> getAllAuthsByEmail(String email) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
ResultSet rs = null;
|
||||
@ -584,7 +584,7 @@ public class MySQLDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeBanned(List<String> banned) {
|
||||
public synchronized void purgeBanned(List<String> banned) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
try {
|
||||
|
@ -1,7 +1,3 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package uk.org.whoami.authme.datasource;
|
||||
|
||||
import java.sql.*;
|
||||
@ -106,6 +102,7 @@ public class SqliteDataSource implements DataSource {
|
||||
+ "ALTER TABLE " + tableName + " ADD COLUMN " + lastlocZ + " smallint(6) NOT NULL DEFAULT '0';");
|
||||
}
|
||||
rs.close();
|
||||
rs = con.getMetaData().getColumns(null, null, tableName, lastlocWorld);
|
||||
if (!rs.next()) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + lastlocWorld + " VARCHAR(255) NOT NULL DEFAULT 'world' AFTER " + lastlocZ + ";");
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ public class AuthMePlayerListener implements Listener {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable()
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run() {
|
||||
@ -227,7 +227,7 @@ public class AuthMePlayerListener implements Listener {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable()
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run() {
|
||||
@ -285,7 +285,7 @@ public class AuthMePlayerListener implements Listener {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable()
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run() {
|
||||
@ -342,7 +342,7 @@ public class AuthMePlayerListener implements Listener {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable()
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run() {
|
||||
@ -399,7 +399,7 @@ public class AuthMePlayerListener implements Listener {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable()
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run() {
|
||||
@ -456,7 +456,7 @@ public class AuthMePlayerListener implements Listener {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable()
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run() {
|
||||
@ -827,16 +827,20 @@ public class AuthMePlayerListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlayerCache.getInstance().isAuthenticated(name) && !player.isDead()) {
|
||||
if (PlayerCache.getInstance().isAuthenticated(name) && !player.isDead()) {
|
||||
if(Settings.isSaveQuitLocationEnabled && data.isAuthAvailable(name)) {
|
||||
final PlayerAuth auth = new PlayerAuth(event.getPlayer().getName().toLowerCase(),loc.getBlockX(),loc.getBlockY(),loc.getBlockZ(),loc.getWorld().getName());
|
||||
try {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
data.updateQuitLoc(auth);
|
||||
}
|
||||
});
|
||||
if (data instanceof Thread) {
|
||||
data.updateQuitLoc(auth);
|
||||
} else {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){
|
||||
@Override
|
||||
public void run() {
|
||||
data.updateQuitLoc(auth);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (NullPointerException npe) { }
|
||||
}
|
||||
}
|
||||
@ -898,12 +902,18 @@ public class AuthMePlayerListener implements Listener {
|
||||
if ((PlayerCache.getInstance().isAuthenticated(name)) && (!player.isDead()) &&
|
||||
(Settings.isSaveQuitLocationEnabled.booleanValue()) && data.isAuthAvailable(name)) {
|
||||
final PlayerAuth auth = new PlayerAuth(event.getPlayer().getName().toLowerCase(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(),loc.getWorld().getName());
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
data.updateQuitLoc(auth);
|
||||
}
|
||||
});
|
||||
try {
|
||||
if (data instanceof Thread) {
|
||||
data.updateQuitLoc(auth);
|
||||
} else {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){
|
||||
@Override
|
||||
public void run() {
|
||||
data.updateQuitLoc(auth);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (NullPointerException npe) { }
|
||||
}
|
||||
|
||||
if (LimboCache.getInstance().hasLimboPlayer(name))
|
||||
@ -1181,12 +1191,18 @@ public class AuthMePlayerListener implements Listener {
|
||||
if (Spawn.getInstance().getLocation() != null && Spawn.getInstance().getLocation().getWorld().equals(player.getWorld()))
|
||||
spawn = Spawn.getInstance().getLocation();
|
||||
final PlayerAuth auth = new PlayerAuth(event.getPlayer().getName().toLowerCase(), spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ(),spawn.getWorld().getName());
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){
|
||||
@Override
|
||||
public void run() {
|
||||
data.updateQuitLoc(auth);
|
||||
}
|
||||
});
|
||||
try {
|
||||
if (data instanceof Thread) {
|
||||
data.updateQuitLoc(auth);
|
||||
} else {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){
|
||||
@Override
|
||||
public void run() {
|
||||
data.updateQuitLoc(auth);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (NullPointerException npe) { }
|
||||
event.setRespawnLocation(spawn);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
|
||||
import uk.org.whoami.authme.AuthMe;
|
||||
import uk.org.whoami.authme.ConsoleLogger;
|
||||
|
||||
public class BungeeCordMessage implements PluginMessageListener {
|
||||
|
||||
@ -24,7 +23,6 @@ public class BungeeCordMessage implements PluginMessageListener {
|
||||
try {
|
||||
final DataInputStream in = new DataInputStream(new ByteArrayInputStream(message));
|
||||
if (in.readUTF().equals("IP")) { //We need only the IP channel
|
||||
ConsoleLogger.info("PluginMessage send to " + player.getName() + " , the message was : " + message.toString());
|
||||
plugin.realIp.put(player.getName().toLowerCase(), in.readUTF()); //Put the IP (only the ip not the port) in the hashmap
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
|
@ -28,6 +28,8 @@ import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import uk.org.whoami.authme.AuthMe;
|
||||
import uk.org.whoami.authme.security.pbkdf2.PBKDF2Engine;
|
||||
import uk.org.whoami.authme.security.pbkdf2.PBKDF2Parameters;
|
||||
import uk.org.whoami.authme.settings.Settings;
|
||||
|
||||
public class PasswordSecurity {
|
||||
@ -105,6 +107,13 @@ public class PasswordSecurity {
|
||||
private static String getWBB3(String message, String salt) throws NoSuchAlgorithmException {
|
||||
return getSHA1(salt.concat(getSHA1(salt.concat(getSHA1(message)))));
|
||||
}
|
||||
|
||||
private static String getPBKDF2(String password, String salt) throws NoSuchAlgorithmException {
|
||||
String result = "pbkdf2_sha256$10000$"+salt+"$";
|
||||
PBKDF2Parameters params = new PBKDF2Parameters("SHA-256", "UTF-8", salt.getBytes(), 10000);
|
||||
PBKDF2Engine engine = new PBKDF2Engine(params);
|
||||
return result + engine.deriveKey(password,57).toString();
|
||||
}
|
||||
|
||||
private static String createSalt(int length) throws NoSuchAlgorithmException {
|
||||
byte[] msg = new byte[40];
|
||||
@ -226,6 +235,9 @@ public class PasswordSecurity {
|
||||
return getSHA512(password);
|
||||
case DOUBLEMD5:
|
||||
return getMD5(getMD5(password));
|
||||
case PBKDF2:
|
||||
String saltpbkdf2 = createSalt(12);
|
||||
return getPBKDF2(password, saltpbkdf2);
|
||||
default:
|
||||
throw new NoSuchAlgorithmException("Unknown hash algorithm");
|
||||
}
|
||||
@ -237,24 +249,24 @@ public class PasswordSecurity {
|
||||
return checkHash.phpbb_check_hash(password, hash);
|
||||
}
|
||||
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.WBB3) {
|
||||
String saltwbb3 = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||
return hash.equals(getWBB3(password, saltwbb3));
|
||||
String salt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||
return hash.equals(getWBB3(password, salt));
|
||||
}
|
||||
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.IPB3) {
|
||||
String saltipb = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||
return hash.equals(getSaltedIPB3(password, saltipb));
|
||||
String salt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||
return hash.equals(getSaltedIPB3(password, salt));
|
||||
}
|
||||
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.BCRYPT) {
|
||||
String saltbcrypt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||
return hash.equals(BCrypt.hashpw(password, saltbcrypt));
|
||||
String salt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||
return hash.equals(BCrypt.hashpw(password, salt));
|
||||
}
|
||||
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.PHPFUSION) {
|
||||
String saltfusion = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||
return hash.equals(getPhPFusion(password, saltfusion));
|
||||
String salt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||
return hash.equals(getPhPFusion(password, salt));
|
||||
}
|
||||
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.MYBB) {
|
||||
String saltmybb = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||
return hash.equals(getSaltedMyBB(password, saltmybb));
|
||||
String salt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||
return hash.equals(getSaltedMyBB(password, salt));
|
||||
}
|
||||
if(Settings.getPasswordHash == HashAlgorithm.SMF)
|
||||
return hash.equals(getSHA1(playername.toLowerCase() + password));
|
||||
@ -265,15 +277,23 @@ public class PasswordSecurity {
|
||||
if(Settings.getPasswordHash == HashAlgorithm.DOUBLEMD5)
|
||||
return hash.equals(getMD5(getMD5(password)));
|
||||
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.SALTED2MD5) {
|
||||
String salt2md5 = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||
return hash.equals(getMD5(getMD5(password) + salt2md5));
|
||||
String salt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||
return hash.equals(getMD5(getMD5(password) + salt));
|
||||
}
|
||||
if(Settings.getPasswordHash == HashAlgorithm.JOOMLA) {
|
||||
String saltj = hash.split(":")[1];
|
||||
return hash.equals(getMD5(password + saltj) + ":" + saltj);
|
||||
String salt = hash.split(":")[1];
|
||||
return hash.equals(getMD5(password + salt) + ":" + salt);
|
||||
}
|
||||
if(Settings.getPasswordHash == HashAlgorithm.SHA512)
|
||||
return hash.equals(getSHA512(password));
|
||||
if(Settings.getPasswordHash == HashAlgorithm.PBKDF2) {
|
||||
String[] line = hash.split("\\$");
|
||||
String salt = line[2];
|
||||
String derivedKey = line[3];
|
||||
PBKDF2Parameters params = new PBKDF2Parameters("SHA-256", "UTF-8", salt.getBytes(), 10000, derivedKey.getBytes());
|
||||
PBKDF2Engine engine = new PBKDF2Engine(params);
|
||||
return engine.verifyKey(password);
|
||||
}
|
||||
// PlainText Password
|
||||
if(hash.length() < 32 )
|
||||
return hash.equals(password);
|
||||
@ -336,7 +356,7 @@ public class PasswordSecurity {
|
||||
public enum HashAlgorithm {
|
||||
|
||||
MD5, SHA1, SHA256, WHIRLPOOL, XAUTH, MD5VB, PHPBB, PLAINTEXT, MYBB, IPB3, PHPFUSION, SMF, XFSHA1,
|
||||
XFSHA256, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512, DOUBLEMD5
|
||||
XFSHA256, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512, DOUBLEMD5, PBKDF2
|
||||
}
|
||||
|
||||
}
|
||||
|
137
src/main/java/uk/org/whoami/authme/security/pbkdf2/BinTools.java
Normal file
137
src/main/java/uk/org/whoami/authme/security/pbkdf2/BinTools.java
Normal file
@ -0,0 +1,137 @@
|
||||
package uk.org.whoami.authme.security.pbkdf2;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Free auxiliary functions. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public class BinTools
|
||||
{
|
||||
public static final String hex = "0123456789ABCDEF";
|
||||
|
||||
/**
|
||||
* Simple binary-to-hexadecimal conversion.
|
||||
*
|
||||
* @param b
|
||||
* Input bytes. May be <code>null</code>.
|
||||
* @return Hexadecimal representation of b. Uppercase A-F, two characters
|
||||
* per byte. Empty string on <code>null</code> input.
|
||||
*/
|
||||
public static String bin2hex(final byte[] b)
|
||||
{
|
||||
if (b == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
StringBuffer sb = new StringBuffer(2 * b.length);
|
||||
for (int i = 0; i < b.length; i++)
|
||||
{
|
||||
int v = (256 + b[i]) % 256;
|
||||
sb.append(hex.charAt((v / 16) & 15));
|
||||
sb.append(hex.charAt((v % 16) & 15));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert hex string to array of bytes.
|
||||
*
|
||||
* @param s
|
||||
* String containing hexadecimal digits. May be <code>null</code>.
|
||||
* On odd length leading zero will be assumed.
|
||||
* @return Array on bytes, non-<code>null</code>.
|
||||
* @throws IllegalArgumentException
|
||||
* when string contains non-hex character
|
||||
*/
|
||||
public static byte[] hex2bin(final String s)
|
||||
{
|
||||
String m = s;
|
||||
if (s == null)
|
||||
{
|
||||
// Allow empty input string.
|
||||
m = "";
|
||||
}
|
||||
else if (s.length() % 2 != 0)
|
||||
{
|
||||
// Assume leading zero for odd string length
|
||||
m = "0" + s;
|
||||
}
|
||||
byte r[] = new byte[m.length() / 2];
|
||||
for (int i = 0, n = 0; i < m.length(); n++)
|
||||
{
|
||||
char h = m.charAt(i++);
|
||||
char l = m.charAt(i++);
|
||||
r[n] = (byte) (hex2bin(h) * 16 + hex2bin(l));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert hex digit to numerical value.
|
||||
*
|
||||
* @param c
|
||||
* 0-9, a-f, A-F allowd.
|
||||
* @return 0-15
|
||||
* @throws IllegalArgumentException
|
||||
* on non-hex character
|
||||
*/
|
||||
public static int hex2bin(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
return (c - '0');
|
||||
}
|
||||
if (c >= 'A' && c <= 'F')
|
||||
{
|
||||
return (c - 'A' + 10);
|
||||
}
|
||||
if (c >= 'a' && c <= 'f')
|
||||
{
|
||||
return (c - 'a' + 10);
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
"Input string may only contain hex digits, but found '" + c
|
||||
+ "'");
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
byte b[] = new byte[256];
|
||||
byte bb = 0;
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
b[i] = bb++;
|
||||
}
|
||||
String s = bin2hex(b);
|
||||
byte c[] = hex2bin(s);
|
||||
String t = bin2hex(c);
|
||||
if (!s.equals(t))
|
||||
{
|
||||
throw new AssertionError("Mismatch");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
package uk.org.whoami.authme.security.pbkdf2;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
/**
|
||||
* Default PRF implementation based on standard javax.crypt.Mac mechanisms.
|
||||
*
|
||||
* <hr />
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public class MacBasedPRF implements PRF
|
||||
{
|
||||
protected Mac mac;
|
||||
|
||||
protected int hLen;
|
||||
|
||||
protected String macAlgorithm;
|
||||
|
||||
/**
|
||||
* Create Mac-based Pseudo Random Function.
|
||||
*
|
||||
* @param macAlgorithm
|
||||
* Mac algorithm to use, i.e. HMacSHA1 or HMacMD5.
|
||||
*/
|
||||
public MacBasedPRF(String macAlgorithm)
|
||||
{
|
||||
this.macAlgorithm = macAlgorithm;
|
||||
try
|
||||
{
|
||||
mac = Mac.getInstance(macAlgorithm);
|
||||
hLen = mac.getMacLength();
|
||||
}
|
||||
catch (NoSuchAlgorithmException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public MacBasedPRF(String macAlgorithm, String provider)
|
||||
{
|
||||
this.macAlgorithm = macAlgorithm;
|
||||
try
|
||||
{
|
||||
mac = Mac.getInstance(macAlgorithm, provider);
|
||||
hLen = mac.getMacLength();
|
||||
}
|
||||
catch (NoSuchAlgorithmException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (NoSuchProviderException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] doFinal(byte[] M)
|
||||
{
|
||||
byte[] r = mac.doFinal(M);
|
||||
return r;
|
||||
}
|
||||
|
||||
public int getHLen()
|
||||
{
|
||||
return hLen;
|
||||
}
|
||||
|
||||
public void init(byte[] P)
|
||||
{
|
||||
try
|
||||
{
|
||||
mac.init(new SecretKeySpec(P, macAlgorithm));
|
||||
}
|
||||
catch (InvalidKeyException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package uk.org.whoami.authme.security.pbkdf2;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface PBKDF2
|
||||
{
|
||||
/**
|
||||
* Convert String-based input to internal byte array, then invoke PBKDF2.
|
||||
* Desired key length defaults to Pseudo Random Function block size.
|
||||
*
|
||||
* @param inputPassword
|
||||
* Candidate password to compute the derived key for.
|
||||
* @return internal byte array
|
||||
*/
|
||||
public abstract byte[] deriveKey(String inputPassword);
|
||||
|
||||
/**
|
||||
* Convert String-based input to internal byte array, then invoke PBKDF2.
|
||||
*
|
||||
* @param inputPassword
|
||||
* Candidate password to compute the derived key for.
|
||||
* @param dkLen
|
||||
* Specify desired key length
|
||||
* @return internal byte array
|
||||
*/
|
||||
public abstract byte[] deriveKey(String inputPassword, int dkLen);
|
||||
|
||||
/**
|
||||
* Convert String-based input to internal byte arrays, then invoke PBKDF2
|
||||
* and verify result against the reference data that is supplied in the
|
||||
* PBKDF2Parameters.
|
||||
*
|
||||
* @param inputPassword
|
||||
* Candidate password to compute the derived key for.
|
||||
* @return <code>true</code> password match; <code>false</code>
|
||||
* incorrect password
|
||||
*/
|
||||
public abstract boolean verifyKey(String inputPassword);
|
||||
|
||||
/**
|
||||
* Allow reading of configured parameters.
|
||||
*
|
||||
* @return Currently set parameters.
|
||||
*/
|
||||
public abstract PBKDF2Parameters getParameters();
|
||||
|
||||
/**
|
||||
* Allow setting of configured parameters.
|
||||
*
|
||||
* @param parameters
|
||||
*/
|
||||
public abstract void setParameters(PBKDF2Parameters parameters);
|
||||
|
||||
/**
|
||||
* Get currently set Pseudo Random Function.
|
||||
*
|
||||
* @return Currently set Pseudo Random Function
|
||||
*/
|
||||
public abstract PRF getPseudoRandomFunction();
|
||||
|
||||
/**
|
||||
* Set the Pseudo Random Function to use. Note that deriveKeys/getPRF does
|
||||
* init this object using the supplied candidate password. If this is
|
||||
* undesired, one has to override getPRF.
|
||||
*
|
||||
* @param prf
|
||||
* Pseudo Random Function to set.
|
||||
*/
|
||||
public abstract void setPseudoRandomFunction(PRF prf);
|
||||
}
|
@ -0,0 +1,401 @@
|
||||
package uk.org.whoami.authme.security.pbkdf2;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Request for Comments: 2898 PKCS #5: Password-Based Cryptography Specification
|
||||
* <p>
|
||||
* Version 2.0
|
||||
*
|
||||
* <p>
|
||||
* PBKDF2 (P, S, c, dkLen)
|
||||
*
|
||||
* <p>
|
||||
* Options:
|
||||
* <ul>
|
||||
* <li>PRF underlying pseudorandom function (hLen denotes the length in octets
|
||||
* of the pseudorandom function output). PRF is pluggable.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* Input:
|
||||
* <ul>
|
||||
* <li>P password, an octet string</li>
|
||||
* <li>S salt, an octet string</li>
|
||||
* <li>c iteration count, a positive integer</li>
|
||||
* <li>dkLen intended length in octets of the derived key, a positive integer,
|
||||
* at most (2^32 - 1) * hLen</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* Output:
|
||||
* <ul>
|
||||
* <li>DK derived key, a dkLen-octet string</li>
|
||||
* </ul>
|
||||
*
|
||||
* <hr />
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898</a>
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public class PBKDF2Engine implements PBKDF2
|
||||
{
|
||||
protected PBKDF2Parameters parameters;
|
||||
|
||||
protected PRF prf;
|
||||
|
||||
/**
|
||||
* Constructor for PBKDF2 implementation object. PBKDF2 parameters must be
|
||||
* passed later.
|
||||
*/
|
||||
public PBKDF2Engine()
|
||||
{
|
||||
this.parameters = null;
|
||||
prf = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for PBKDF2 implementation object. PBKDF2 parameters are
|
||||
* passed so that this implementation knows iteration count, method to use
|
||||
* and String encoding.
|
||||
*
|
||||
* @param parameters
|
||||
* Data holder for iteration count, method to use et cetera.
|
||||
*/
|
||||
public PBKDF2Engine(PBKDF2Parameters parameters)
|
||||
{
|
||||
this.parameters = parameters;
|
||||
prf = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for PBKDF2 implementation object. PBKDF2 parameters are
|
||||
* passed so that this implementation knows iteration count, method to use
|
||||
* and String encoding.
|
||||
*
|
||||
* @param parameters
|
||||
* Data holder for iteration count, method to use et cetera.
|
||||
* @param prf
|
||||
* Supply customer Pseudo Random Function.
|
||||
*/
|
||||
public PBKDF2Engine(PBKDF2Parameters parameters, PRF prf)
|
||||
{
|
||||
this.parameters = parameters;
|
||||
this.prf = prf;
|
||||
}
|
||||
|
||||
public byte[] deriveKey(String inputPassword)
|
||||
{
|
||||
return deriveKey(inputPassword, 0);
|
||||
}
|
||||
|
||||
public byte[] deriveKey(String inputPassword, int dkLen)
|
||||
{
|
||||
byte[] r = null;
|
||||
byte P[] = null;
|
||||
String charset = parameters.getHashCharset();
|
||||
if (inputPassword == null)
|
||||
{
|
||||
inputPassword = "";
|
||||
}
|
||||
try
|
||||
{
|
||||
if (charset == null)
|
||||
{
|
||||
P = inputPassword.getBytes();
|
||||
}
|
||||
else
|
||||
{
|
||||
P = inputPassword.getBytes(charset);
|
||||
}
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
assertPRF(P);
|
||||
if (dkLen == 0)
|
||||
{
|
||||
dkLen = prf.getHLen();
|
||||
}
|
||||
r = PBKDF2(prf, parameters.getSalt(), parameters.getIterationCount(),
|
||||
dkLen);
|
||||
return r;
|
||||
}
|
||||
|
||||
public boolean verifyKey(String inputPassword)
|
||||
{
|
||||
byte[] referenceKey = getParameters().getDerivedKey();
|
||||
if (referenceKey == null || referenceKey.length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
byte[] inputKey = deriveKey(inputPassword, referenceKey.length);
|
||||
|
||||
if (inputKey == null || inputKey.length != referenceKey.length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < inputKey.length; i++)
|
||||
{
|
||||
if (inputKey[i] != referenceKey[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method. Default implementation is (H)MAC-based. To be overridden
|
||||
* in derived classes.
|
||||
*
|
||||
* @param P
|
||||
* User-supplied candidate password as array of bytes.
|
||||
*/
|
||||
protected void assertPRF(byte[] P)
|
||||
{
|
||||
if (prf == null)
|
||||
{
|
||||
prf = new MacBasedPRF(parameters.getHashAlgorithm());
|
||||
}
|
||||
prf.init(P);
|
||||
}
|
||||
|
||||
public PRF getPseudoRandomFunction()
|
||||
{
|
||||
return prf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Core Password Based Key Derivation Function 2.
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2</a>
|
||||
* @param prf
|
||||
* Pseudo Random Function (i.e. HmacSHA1)
|
||||
* @param S
|
||||
* Salt as array of bytes. <code>null</code> means no salt.
|
||||
* @param c
|
||||
* Iteration count (see RFC 2898 4.2)
|
||||
* @param dkLen
|
||||
* desired length of derived key.
|
||||
* @return internal byte array
|
||||
*/
|
||||
protected byte[] PBKDF2(PRF prf, byte[] S, int c, int dkLen)
|
||||
{
|
||||
if (S == null)
|
||||
{
|
||||
S = new byte[0];
|
||||
}
|
||||
int hLen = prf.getHLen();
|
||||
int l = ceil(dkLen, hLen);
|
||||
int r = dkLen - (l - 1) * hLen;
|
||||
byte T[] = new byte[l * hLen];
|
||||
int ti_offset = 0;
|
||||
for (int i = 1; i <= l; i++)
|
||||
{
|
||||
_F(T, ti_offset, prf, S, c, i);
|
||||
ti_offset += hLen;
|
||||
}
|
||||
if (r < hLen)
|
||||
{
|
||||
// Incomplete last block
|
||||
byte DK[] = new byte[dkLen];
|
||||
System.arraycopy(T, 0, DK, 0, dkLen);
|
||||
return DK;
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Integer division with ceiling function.
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step 2.</a>
|
||||
* @param a
|
||||
* @param b
|
||||
* @return ceil(a/b)
|
||||
*/
|
||||
protected int ceil(int a, int b)
|
||||
{
|
||||
int m = 0;
|
||||
if (a % b > 0)
|
||||
{
|
||||
m = 1;
|
||||
}
|
||||
return a / b + m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function F.
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step 3.</a>
|
||||
* @param dest
|
||||
* Destination byte buffer
|
||||
* @param offset
|
||||
* Offset into destination byte buffer
|
||||
* @param prf
|
||||
* Pseudo Random Function
|
||||
* @param S
|
||||
* Salt as array of bytes
|
||||
* @param c
|
||||
* Iteration count
|
||||
* @param blockIndex
|
||||
*/
|
||||
protected void _F(byte[] dest, int offset, PRF prf, byte[] S, int c,
|
||||
int blockIndex)
|
||||
{
|
||||
int hLen = prf.getHLen();
|
||||
byte U_r[] = new byte[hLen];
|
||||
|
||||
// U0 = S || INT (i);
|
||||
byte U_i[] = new byte[S.length + 4];
|
||||
System.arraycopy(S, 0, U_i, 0, S.length);
|
||||
INT(U_i, S.length, blockIndex);
|
||||
|
||||
for (int i = 0; i < c; i++)
|
||||
{
|
||||
U_i = prf.doFinal(U_i);
|
||||
xor(U_r, U_i);
|
||||
}
|
||||
System.arraycopy(U_r, 0, dest, offset, hLen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Block-Xor. Xor source bytes into destination byte buffer. Destination
|
||||
* buffer must be same length or less than source buffer.
|
||||
*
|
||||
* @param dest
|
||||
* @param src
|
||||
*/
|
||||
protected void xor(byte[] dest, byte[] src)
|
||||
{
|
||||
for (int i = 0; i < dest.length; i++)
|
||||
{
|
||||
dest[i] ^= src[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Four-octet encoding of the integer i, most significant octet first.
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step 3.</a>
|
||||
* @param dest
|
||||
* @param offset
|
||||
* @param i
|
||||
*/
|
||||
protected void INT(byte[] dest, int offset, int i)
|
||||
{
|
||||
dest[offset + 0] = (byte) (i / (256 * 256 * 256));
|
||||
dest[offset + 1] = (byte) (i / (256 * 256));
|
||||
dest[offset + 2] = (byte) (i / (256));
|
||||
dest[offset + 3] = (byte) (i);
|
||||
}
|
||||
|
||||
public PBKDF2Parameters getParameters()
|
||||
{
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setParameters(PBKDF2Parameters parameters)
|
||||
{
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public void setPseudoRandomFunction(PRF prf)
|
||||
{
|
||||
this.prf = prf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience client function. Convert supplied password with random 8-byte
|
||||
* salt and 1000 iterations using HMacSHA1. Assume that password is in
|
||||
* ISO-8559-1 encoding. Output result as
|
||||
* "Salt:iteration-count:PBKDF2" with binary data in hexadecimal
|
||||
* encoding.
|
||||
*
|
||||
* Example: Password "password" (without the quotes) leads to
|
||||
* 48290A0B96C426C3:1000:973899B1D4AFEB3ED371060D0797E0EE0142BD04
|
||||
*
|
||||
* @param args
|
||||
* Supply the password as argument.
|
||||
* @throws IOException
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
public static void main(String[] args) throws IOException,
|
||||
NoSuchAlgorithmException
|
||||
{
|
||||
String password = "password";
|
||||
String candidate = null;
|
||||
PBKDF2Formatter formatter = new PBKDF2HexFormatter();
|
||||
|
||||
if (args.length >= 1)
|
||||
{
|
||||
password = args[0];
|
||||
}
|
||||
if (args.length >= 2)
|
||||
{
|
||||
candidate = args[1];
|
||||
}
|
||||
if (candidate == null)
|
||||
{
|
||||
// Creation mode
|
||||
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
|
||||
byte[] salt = new byte[8];
|
||||
sr.nextBytes(salt);
|
||||
int iterations = 1000;
|
||||
PBKDF2Parameters p = new PBKDF2Parameters("HmacSHA1", "ISO-8859-1",
|
||||
salt, iterations);
|
||||
PBKDF2Engine e = new PBKDF2Engine(p);
|
||||
p.setDerivedKey(e.deriveKey(password));
|
||||
candidate = formatter.toString(p);
|
||||
System.out.println(candidate);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Verification mode
|
||||
PBKDF2Parameters p = new PBKDF2Parameters();
|
||||
p.setHashAlgorithm("HmacSHA1");
|
||||
p.setHashCharset("ISO-8859-1");
|
||||
if (formatter.fromString(p, candidate))
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"Candidate data does not have correct format (\""
|
||||
+ candidate + "\")");
|
||||
}
|
||||
PBKDF2Engine e = new PBKDF2Engine(p);
|
||||
boolean verifyOK = e.verifyKey(password);
|
||||
System.out.println(verifyOK ? "OK" : "FAIL");
|
||||
System.exit(verifyOK ? 0 : 1);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package uk.org.whoami.authme.security.pbkdf2;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface PBKDF2Formatter
|
||||
{
|
||||
/**
|
||||
* Convert parameters to String.
|
||||
*
|
||||
* @param p
|
||||
* Parameters object to output.
|
||||
* @return String representation
|
||||
*/
|
||||
public abstract String toString(PBKDF2Parameters p);
|
||||
|
||||
/**
|
||||
* Convert String to parameters. Depending on actual implementation, it may
|
||||
* be required to set further fields externally.
|
||||
*
|
||||
* @param s
|
||||
* String representation of parameters to decode.
|
||||
* @return <code>false</code> syntax OK, <code>true</code> some syntax
|
||||
* issue.
|
||||
*/
|
||||
public abstract boolean fromString(PBKDF2Parameters p, String s);
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package uk.org.whoami.authme.security.pbkdf2;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public class PBKDF2HexFormatter implements PBKDF2Formatter
|
||||
{
|
||||
public boolean fromString(PBKDF2Parameters p, String s)
|
||||
{
|
||||
if (p == null || s == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
String[] p123 = s.split(":");
|
||||
if (p123 == null || p123.length != 3)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
byte salt[] = BinTools.hex2bin(p123[0]);
|
||||
int iterationCount = Integer.parseInt(p123[1]);
|
||||
byte bDK[] = BinTools.hex2bin(p123[2]);
|
||||
|
||||
p.setSalt(salt);
|
||||
p.setIterationCount(iterationCount);
|
||||
p.setDerivedKey(bDK);
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString(PBKDF2Parameters p)
|
||||
{
|
||||
String s = BinTools.bin2hex(p.getSalt()) + ":"
|
||||
+ String.valueOf(p.getIterationCount()) + ":"
|
||||
+ BinTools.bin2hex(p.getDerivedKey());
|
||||
return s;
|
||||
}
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
package uk.org.whoami.authme.security.pbkdf2;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parameter data holder for PBKDF2 configuration.
|
||||
* </p>
|
||||
*
|
||||
* <hr />
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public class PBKDF2Parameters
|
||||
{
|
||||
protected byte[] salt;
|
||||
|
||||
protected int iterationCount;
|
||||
|
||||
protected String hashAlgorithm;
|
||||
|
||||
protected String hashCharset;
|
||||
|
||||
/**
|
||||
* The derived key is actually only a convenience to store a reference
|
||||
* derived key. It is not used during computation.
|
||||
*/
|
||||
protected byte[] derivedKey;
|
||||
|
||||
/**
|
||||
* Constructor. Defaults to <code>null</code> for byte arrays, UTF-8 as
|
||||
* character set and 1000 for iteration count.
|
||||
*
|
||||
*/
|
||||
public PBKDF2Parameters()
|
||||
{
|
||||
this.hashAlgorithm = null;
|
||||
this.hashCharset = "UTF-8";
|
||||
this.salt = null;
|
||||
this.iterationCount = 1000;
|
||||
this.derivedKey = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param hashAlgorithm
|
||||
* for example HMacSHA1 or HMacMD5
|
||||
* @param hashCharset
|
||||
* for example UTF-8
|
||||
* @param salt
|
||||
* Salt as byte array, may be <code>null</code> (not
|
||||
* recommended)
|
||||
* @param iterationCount
|
||||
* Number of iterations to execute. Recommended value 1000.
|
||||
*/
|
||||
public PBKDF2Parameters(String hashAlgorithm, String hashCharset,
|
||||
byte[] salt, int iterationCount)
|
||||
{
|
||||
this.hashAlgorithm = hashAlgorithm;
|
||||
this.hashCharset = hashCharset;
|
||||
this.salt = salt;
|
||||
this.iterationCount = iterationCount;
|
||||
this.derivedKey = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param hashAlgorithm
|
||||
* for example HMacSHA1 or HMacMD5
|
||||
* @param hashCharset
|
||||
* for example UTF-8
|
||||
* @param salt
|
||||
* Salt as byte array, may be <code>null</code> (not
|
||||
* recommended)
|
||||
* @param iterationCount
|
||||
* Number of iterations to execute. Recommended value 1000.
|
||||
* @param derivedKey
|
||||
* Convenience data holder, not used during computation.
|
||||
*/
|
||||
public PBKDF2Parameters(String hashAlgorithm, String hashCharset,
|
||||
byte[] salt, int iterationCount, byte[] derivedKey)
|
||||
{
|
||||
this.hashAlgorithm = hashAlgorithm;
|
||||
this.hashCharset = hashCharset;
|
||||
this.salt = salt;
|
||||
this.iterationCount = iterationCount;
|
||||
this.derivedKey = derivedKey;
|
||||
}
|
||||
|
||||
public int getIterationCount()
|
||||
{
|
||||
return iterationCount;
|
||||
}
|
||||
|
||||
public void setIterationCount(int iterationCount)
|
||||
{
|
||||
this.iterationCount = iterationCount;
|
||||
}
|
||||
|
||||
public byte[] getSalt()
|
||||
{
|
||||
return salt;
|
||||
}
|
||||
|
||||
public void setSalt(byte[] salt)
|
||||
{
|
||||
this.salt = salt;
|
||||
}
|
||||
|
||||
public byte[] getDerivedKey()
|
||||
{
|
||||
return derivedKey;
|
||||
}
|
||||
|
||||
public void setDerivedKey(byte[] derivedKey)
|
||||
{
|
||||
this.derivedKey = derivedKey;
|
||||
}
|
||||
|
||||
public String getHashAlgorithm()
|
||||
{
|
||||
return hashAlgorithm;
|
||||
}
|
||||
|
||||
public void setHashAlgorithm(String hashAlgorithm)
|
||||
{
|
||||
this.hashAlgorithm = hashAlgorithm;
|
||||
}
|
||||
|
||||
public String getHashCharset()
|
||||
{
|
||||
return hashCharset;
|
||||
}
|
||||
|
||||
public void setHashCharset(String hashCharset)
|
||||
{
|
||||
this.hashCharset = hashCharset;
|
||||
}
|
||||
}
|
60
src/main/java/uk/org/whoami/authme/security/pbkdf2/PRF.java
Normal file
60
src/main/java/uk/org/whoami/authme/security/pbkdf2/PRF.java
Normal file
@ -0,0 +1,60 @@
|
||||
package uk.org.whoami.authme.security.pbkdf2;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* </p>
|
||||
* <p>
|
||||
* For Details, see <a
|
||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthias Gärtner
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface PRF
|
||||
{
|
||||
/**
|
||||
* Initialize this instance with the user-supplied password.
|
||||
*
|
||||
* @param P
|
||||
* The password supplied as array of bytes. It is the caller's
|
||||
* task to convert String passwords to bytes as appropriate.
|
||||
*/
|
||||
public void init(byte[] P);
|
||||
|
||||
/**
|
||||
* Pseudo Random Function
|
||||
*
|
||||
* @param M
|
||||
* Input data/message etc. Together with any data supplied during
|
||||
* initilization.
|
||||
* @return Random bytes of hLen length.
|
||||
*/
|
||||
public byte[] doFinal(byte[] M);
|
||||
|
||||
/**
|
||||
* Query block size of underlying algorithm/mechanism.
|
||||
*
|
||||
* @return block size
|
||||
*/
|
||||
public int getHLen();
|
||||
}
|
@ -299,7 +299,7 @@ public class MySQLThread extends Thread implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSession(PlayerAuth auth) {
|
||||
public synchronized boolean updateSession(PlayerAuth auth) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
try {
|
||||
@ -323,7 +323,7 @@ public class MySQLThread extends Thread implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int purgeDatabase(long until) {
|
||||
public synchronized int purgeDatabase(long until) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
try {
|
||||
@ -366,7 +366,7 @@ public class MySQLThread extends Thread implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateQuitLoc(PlayerAuth auth) {
|
||||
public synchronized boolean updateQuitLoc(PlayerAuth auth) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
try {
|
||||
@ -392,7 +392,7 @@ public class MySQLThread extends Thread implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIps(String ip) {
|
||||
public synchronized int getIps(String ip) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
ResultSet rs = null;
|
||||
@ -421,7 +421,7 @@ public class MySQLThread extends Thread implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateEmail(PlayerAuth auth) {
|
||||
public synchronized boolean updateEmail(PlayerAuth auth) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
try {
|
||||
@ -444,7 +444,7 @@ public class MySQLThread extends Thread implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSalt(PlayerAuth auth) {
|
||||
public synchronized boolean updateSalt(PlayerAuth auth) {
|
||||
if (columnSalt.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
@ -513,7 +513,7 @@ public class MySQLThread extends Thread implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllAuthsByName(PlayerAuth auth) {
|
||||
public synchronized List<String> getAllAuthsByName(PlayerAuth auth) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
ResultSet rs = null;
|
||||
@ -542,7 +542,7 @@ public class MySQLThread extends Thread implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllAuthsByIp(String ip) {
|
||||
public synchronized List<String> getAllAuthsByIp(String ip) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
ResultSet rs = null;
|
||||
@ -571,7 +571,7 @@ public class MySQLThread extends Thread implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllAuthsByEmail(String email) {
|
||||
public synchronized List<String> getAllAuthsByEmail(String email) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
ResultSet rs = null;
|
||||
@ -600,7 +600,7 @@ public class MySQLThread extends Thread implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeBanned(List<String> banned) {
|
||||
public synchronized void purgeBanned(List<String> banned) {
|
||||
Connection con = null;
|
||||
PreparedStatement pst = null;
|
||||
try {
|
||||
@ -617,4 +617,35 @@ public class MySQLThread extends Thread implements DataSource {
|
||||
close(con);
|
||||
}
|
||||
}
|
||||
|
||||
/* public synchronized boolean makeSureConnectionIsReady() {
|
||||
try {
|
||||
conPool.getValidConnection();
|
||||
return true;
|
||||
} catch (TimeoutException te) {
|
||||
try {
|
||||
reconnect();
|
||||
} catch (TimeoutException e) {
|
||||
return false;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
} catch (SQLException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void reconnect() throws ClassNotFoundException, SQLException, TimeoutException {
|
||||
conPool.dispose();
|
||||
Class.forName("com.mysql.jdbc.Driver");
|
||||
MysqlConnectionPoolDataSource dataSource = new MysqlConnectionPoolDataSource();
|
||||
dataSource.setDatabaseName(database);
|
||||
dataSource.setServerName(host);
|
||||
dataSource.setPort(Integer.parseInt(port));
|
||||
dataSource.setUser(username);
|
||||
dataSource.setPassword(password);
|
||||
conPool = new MiniConnectionPoolManager(dataSource, 10);
|
||||
ConsoleLogger.info("Connection pool reconnected");
|
||||
} */
|
||||
}
|
||||
|
@ -123,6 +123,7 @@ public class SQLiteThread extends Thread implements DataSource {
|
||||
+ "ALTER TABLE " + tableName + " ADD COLUMN " + lastlocZ + " smallint(6) NOT NULL DEFAULT '0';");
|
||||
}
|
||||
rs.close();
|
||||
rs = con.getMetaData().getColumns(null, null, tableName, lastlocWorld);
|
||||
if (!rs.next()) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + lastlocWorld + " VARCHAR(255) NOT NULL DEFAULT 'world' AFTER " + lastlocZ + ";");
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ no_perm: '&cSem permissao!'
|
||||
error: '&fOcorreu um erro de sistema, por favor reporte ao ADM.'
|
||||
login_msg: '&cPara entrar digite: "/login password"'
|
||||
reg_msg: '&cPara registrar um nick digite: "/register senha senha"'
|
||||
reg_email_msg: '&cPlease register with "/register <email> <confirmEmail>"'
|
||||
reg_email_msg: '&cPara registrar um nick digite: "/register <e-mail> <e-mail>"'
|
||||
usage_unreg: '&cPara desregistrar digite: /unregister senha'
|
||||
pwd_changed: '&cSenha modificada!'
|
||||
user_unknown: '&cNome de usuario nao existe. Verifique.'
|
||||
@ -29,23 +29,23 @@ registered: '&cRegistrado com sucesso!'
|
||||
pass_len: '&fSenha muito curta.'
|
||||
reload: '&fAuthMe Recarregado.'
|
||||
timeout: '&fDemorou....'
|
||||
name_len: '&cYour nickname is too Short or too long'
|
||||
regex: '&cYour nickname contains illegal characters. Allowed chars: REG_EX'
|
||||
add_email: '&cPlease add your email with : /email add yourEmail confirmEmail'
|
||||
bad_database_email: '[AuthMe] This /email command only available with MySQL and SQLite, contact an Admin'
|
||||
recovery_email: '&cForgot your password? Please use /email recovery <yourEmail>'
|
||||
usage_captcha: '&cUsage: /captcha <theCaptcha>'
|
||||
wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA'
|
||||
valid_captcha: '&cYour captcha is valid !'
|
||||
kick_forvip: '&cA VIP Player join the full server!'
|
||||
name_len: '&cSeu nome de usuário é muito longo'
|
||||
regex: '&cSeu nome de usuário tem caracteres ilegais. Permitido: REG_EX'
|
||||
add_email: '&cAdicione seu e-mail, digite: /email add e-mail e-mail'
|
||||
bad_database_email: '[AuthMe] Comando /email disponibilizado apenas com MySQL e SQLite, contate um Admin'
|
||||
recovery_email: '&cEsqueceu sua senha? Digite /email recovery <e-mail>'
|
||||
usage_captcha: '&cDigite: /captcha <theCaptcha>'
|
||||
wrong_captcha: '&Captcha errado, digite: /captcha THE_CAPTCHA'
|
||||
valid_captcha: '&cSeu captcha é válido!'
|
||||
kick_forvip: '&cUsuário VIP entrou no servidor cheio!'
|
||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
email_invalid: '[AuthMe] Invalid Email'
|
||||
email_added: '[AuthMe] Email Added !'
|
||||
email_confirm: '[AuthMe] Confirm your Email !'
|
||||
email_changed: '[AuthMe] Email Change !'
|
||||
email_send: '[AuthMe] Recovery Email Send !'
|
||||
usage_email_add: '&fDigite: /email add <e-mail> <e-mail> '
|
||||
usage_email_change: '&fDigite: /email change <e-mailAnterior> <novoE-mail> '
|
||||
usage_email_recovery: '&fDigite: /email recovery <e-mail>'
|
||||
new_email_invalid: '[AuthMe] Novo e-mail inválido!'
|
||||
old_email_invalid: '[AuthMe] E-mail anterior, inválido!'
|
||||
email_invalid: '[AuthMe] E-mail iválido'
|
||||
email_added: '[AuthMe] E-mail adicionado com sucesso!'
|
||||
email_confirm: '[AuthMe] Confirme seu e-mail!'
|
||||
email_changed: '[AuthMe] E-mail alterado!'
|
||||
email_send: '[AuthMe] E-mail com nova senha enviado!'
|
||||
|
@ -41,8 +41,8 @@ wrong_captcha: '&cSpatne opsana Captcha, pouzij prosim: /captcha CAPTCHA_TEXT'
|
||||
valid_captcha: '&cZadana captcha je OK !'
|
||||
kick_forvip: '&cA VIP Hrac se pripojil na plny server!'
|
||||
kick_fullserver: '&cServer je plne obsazen, zkus to pozdeji prosim !'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||
usage_email_change: '&fUsage: /email change <oldEmail> newEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
|
@ -41,8 +41,8 @@ wrong_captcha: '&cFalsches Captcha, bitte nutze: /captcha <dasCaptcha>'
|
||||
valid_captcha: '&cDas Captcha ist korrekt!'
|
||||
kick_forvip: '&cEin VIP Spieler hat den vollen Server betreten!'
|
||||
kick_fullserver: '&cDer Server ist momentan voll, Sorry!'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
|
@ -41,8 +41,8 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA'
|
||||
valid_captcha: '&cYour captcha is valid !'
|
||||
kick_forvip: '&cA VIP Player join the full server!'
|
||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_add: '&fUsage: /email add <email> <confirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change oldEmail> <newEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
|
@ -42,8 +42,8 @@ wrong_captcha: '&cCaptcha incorrecto, please use : /captcha EL_CAPTCHA'
|
||||
valid_captcha: '&c¡ Captcha ingresado correctamente !'
|
||||
kick_forvip: '&cA VIP Player join the full server!'
|
||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
|
@ -41,8 +41,8 @@ wrong_captcha: '&cVäärä varmistus, käytä : /captcha THE_CAPTCHA'
|
||||
valid_captcha: '&cSinun varmistus epäonnistui.!'
|
||||
kick_forvip: '&cA VIP Player join the full server!'
|
||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
|
@ -41,8 +41,8 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA'
|
||||
valid_captcha: '&cYour captcha is valid !'
|
||||
kick_forvip: '&cA VIP Player join the full server!'
|
||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
|
@ -41,13 +41,13 @@ wrong_captcha: '&cCaptcha sbagliato, perfavore fai: /captcha THE_CAPTCHA'
|
||||
valid_captcha: "&cIl tuo captcha è valido!"
|
||||
kick_forvip: "&cUn player VIP è entrato mentre il server era pieno!"
|
||||
kick_fullserver: "&cIl server è attualmente pieno, ci dispiace!"
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
email_invalid: '[AuthMe] Invalid Email'
|
||||
email_added: '[AuthMe] Email Added !'
|
||||
email_confirm: '[AuthMe] Confirm your Email !'
|
||||
email_changed: '[AuthMe] Email Change !'
|
||||
email_send: '[AuthMe] Recovery Email Send !'
|
||||
usage_email_add: '&fUtilizzo: /email add <email> <confermaEmail>'
|
||||
usage_email_change: '&fUtilizzo: /email change <vecchiaEmail> <nuovaEmail>'
|
||||
usage_email_recovery: '&fUtilizzo: /email recovery <email>'
|
||||
new_email_invalid: '[AuthMe] La nuova email non è valida!'
|
||||
old_email_invalid: '[AuthMe] La vecchia email non è valida!'
|
||||
email_invalid: "[AuthMe] L'email non è valida"
|
||||
email_added: '[AuthMe] Email Aggiunta!'
|
||||
email_confirm: '[AuthMe] Conferma la tua Email!'
|
||||
email_changed: '[AuthMe] Email cambiata!'
|
||||
email_send: '[AuthMe] Email di recupero inviata!'
|
||||
|
@ -1,53 +1,53 @@
|
||||
unknown_user: 사용자는 데이터베이스에 없습니다
|
||||
unsafe_spawn: 당신이 나갔던 위치는 안전하지 않았습니다, 당신을 윌드 스폰으로 텔레포트시킵니다
|
||||
not_logged_in: '&c로그인하지 않았습니다!'
|
||||
reg_voluntarily: 당신이 서버에 게정을 등록하고 싶다면 "/register 비밀번호 비밀번호재입력"을 치세요
|
||||
usage_log: '&c사용법: /login 비밀번호'
|
||||
wrong_pwd: '&c잘못된 비밀번호입니다'
|
||||
unregistered: '&c성공적으로 회원탈퇴되었습니다!'
|
||||
reg_disabled: '&c회원가입이 성공적으로 비활성화되었습니다'
|
||||
valid_session: '&c세션 로그인'
|
||||
login: '&c성공적으로 로그인 되었습니다!'
|
||||
vb_nonActiv: 당신의 계정은 활성화되어 있지 않습니다 당신의 이메일을 체크해주세요!
|
||||
user_regged: '&c사용자 이름은 이미 등록되어 있습니다'
|
||||
usage_reg: '&c사용법: /register 비밀번호 비밀번호재입력'
|
||||
max_reg: 당신은 가입할 수 있는 계정의 최대 한도 수를 넘었습니다
|
||||
no_perm: '&c권한이 없습니다'
|
||||
error: 오류가 발생했습니다; 관리자한테 문의하세요
|
||||
login_msg: '&c로그인 하실려면 "/login 비밀번호"를 치세요'
|
||||
reg_msg: '&c가입하실려면 "/register 비밀번호 비밀번호재입력"을 치세요'
|
||||
reg_email_msg: '&c가입하실려면 "/register <이메일> <이메일재입력>을 치세요"'
|
||||
usage_unreg: '&c사용법: /unregister 비밀번호'
|
||||
pwd_changed: '&c비밀번호가 변경되었습니다!'
|
||||
user_unknown: '&c사용자 이름은 등록되지 않았습니다'
|
||||
password_error: 비밀번호가 일치하지 않습니다
|
||||
unvalid_session: Session Dataes doesnt corrispond 세션이 끝날때 까지 기달려주세요
|
||||
reg_only: 회원가입은 플레이어만 할 수 있습니다! http://example.com 에 가입해주세요
|
||||
logged_in: '&c이미 로그인되어 있습니다!'
|
||||
logout: '&c성공적으로 로그아웃되었습니다'
|
||||
same_nick: 같은 닉네임이 이미 게임중입니다
|
||||
registered: '&c성공적으로 회원가입되었습니다!'
|
||||
pass_len: 당신의 비밀번호는 최소 글자나 최대글자를 초과하였습니다 적당한 비밀번호 글자로 해주세요
|
||||
reload: 설정과 데이터베이스가 리로드되었습니다
|
||||
timeout: 로그인 시간 초과
|
||||
usage_changepassword: '사용법: /changepassword 기존비밀번호 새비밀번호'
|
||||
name_len: '&c당신의 닉네임은 너무 길거나 짧습니다'
|
||||
regex: '&c당신의 닉네임에 잘못된 문자가 포함되어 있습니다. 허용된 글자: REG_EX'
|
||||
add_email: '&c당신의 이메일을 : /email add yourEmail confirmEmail 명령어로 추가해주세요'
|
||||
bad_database_email: '[AuthMe] /email 명령어는 오직 MySQL 와 SQLite에서만 가능합니다, 관리자에게 문의해보세요'
|
||||
recovery_email: '&c비밀번호를 잊어버리셨다고요? /email recovery <자신의이메일>을 사용해서 복구해보세요'
|
||||
usage_captcha: '&c사용법: /captcha <캡차>'
|
||||
wrong_captcha: '&c잘못된 캡차입니다, 올바른 사용법 : /captcha THE_CAPTCHA'
|
||||
valid_captcha: '&c당신의 캡차는 올바릅니다 !'
|
||||
kick_forvip: '&c한 VIP 플레이어가 만원인 서버에 입장했습니다!!'
|
||||
kick_fullserver: '&c그 서버는 실제로 만원입니다, 미안!'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
email_invalid: '[AuthMe] Invalid Email'
|
||||
email_added: '[AuthMe] Email Added !'
|
||||
email_confirm: '[AuthMe] Confirm your Email !'
|
||||
email_changed: '[AuthMe] Email Change !'
|
||||
email_send: '[AuthMe] Recovery Email Send !'
|
||||
unknown_user: 사용자는 데이터베이스에 없습니다
|
||||
unsafe_spawn: 당신이 나갔던 위치는 안전하지 않았습니다, 당신을 윌드 스폰으로 텔레포트시킵니다
|
||||
not_logged_in: '&c로그인하지 않았습니다!'
|
||||
reg_voluntarily: 당신이 서버에 게정을 등록하고 싶다면 "/register 비밀번호 비밀번호재입력"을 치세요
|
||||
usage_log: '&c사용법: /login 비밀번호'
|
||||
wrong_pwd: '&c잘못된 비밀번호입니다'
|
||||
unregistered: '&c성공적으로 회원탈퇴되었습니다!'
|
||||
reg_disabled: '&c회원가입이 성공적으로 비활성화되었습니다'
|
||||
valid_session: '&c세션 로그인'
|
||||
login: '&c성공적으로 로그인 되었습니다!'
|
||||
vb_nonActiv: 당신의 계정은 활성화되어 있지 않습니다 당신의 이메일을 체크해주세요!
|
||||
user_regged: '&c사용자 이름은 이미 등록되어 있습니다'
|
||||
usage_reg: '&c사용법: /register 비밀번호 비밀번호재입력'
|
||||
max_reg: 당신은 가입할 수 있는 계정의 최대 한도 수를 넘었습니다
|
||||
no_perm: '&c권한이 없습니다'
|
||||
error: 오류가 발생했습니다; 관리자한테 문의하세요
|
||||
login_msg: '&c로그인 하실려면 "/login 비밀번호"를 치세요'
|
||||
reg_msg: '&c가입하실려면 "/register 비밀번호 비밀번호재입력"을 치세요'
|
||||
reg_email_msg: '&c가입하실려면 "/register <이메일> <이메일재입력>을 치세요"'
|
||||
usage_unreg: '&c사용법: /unregister 비밀번호'
|
||||
pwd_changed: '&c비밀번호가 변경되었습니다!'
|
||||
user_unknown: '&c사용자 이름은 등록되지 않았습니다'
|
||||
password_error: 비밀번호가 일치하지 않습니다
|
||||
unvalid_session: 세션 데이터베이스가 일치하지 않습니다 세션이 끝날때 까지 기달려주세요
|
||||
reg_only: 회원가입은 플레이어만 할 수 있습니다! http://example.com 에 가입해주세요
|
||||
logged_in: '&c이미 로그인되어 있습니다!'
|
||||
logout: '&c성공적으로 로그아웃되었습니다'
|
||||
same_nick: 같은 닉네임이 이미 게임중입니다
|
||||
registered: '&c성공적으로 회원가입되었습니다!'
|
||||
pass_len: 당신의 비밀번호는 최소 글자나 최대글자를 초과하였습니다 적당한 비밀번호 글자로 해주세요
|
||||
reload: 설정과 데이터베이스가 리로드되었습니다
|
||||
timeout: 로그인 시간 초과
|
||||
usage_changepassword: '사용법: /changepassword 기존비밀번호 새비밀번호'
|
||||
name_len: '&c당신의 닉네임은 너무 길거나 짧습니다'
|
||||
regex: '&c당신의 닉네임에 잘못된 문자가 포함되어 있습니다. 허용된 글자: REG_EX'
|
||||
add_email: '&c당신의 이메일을 : /email add yourEmail confirmEmail 명령어로 추가해주세요'
|
||||
bad_database_email: '[AuthMe] /email 명령어는 오직 MySQL 와 SQLite에서만 가능합니다, 관리자에게 문의해보세요'
|
||||
recovery_email: '&c비밀번호를 잊어버리셨다고요? /email recovery <자신의이메일>을 사용해서 복구해보세요'
|
||||
usage_captcha: '&c사용법: /captcha <캡차>'
|
||||
wrong_captcha: '&c잘못된 캡차입니다, 올바른 사용법 : /captcha THE_CAPTCHA'
|
||||
valid_captcha: '&c당신의 캡차는 올바릅니다 !'
|
||||
kick_forvip: '&c한 VIP 플레이어가 만원인 서버에 입장했습니다!!'
|
||||
kick_fullserver: '&c그 서버는 실제로 만원입니다, 미안!'
|
||||
usage_email_add: '&f사용법: /email add <이메일> <이메일재입력> '
|
||||
usage_email_change: '&f사용법: /email change <oldEmail> <newEmail> '
|
||||
usage_email_recovery: '&f사용법: /email recovery <이메일>'
|
||||
new_email_invalid: '[AuthMe] 새 이메일이 잘못되었습니다!'
|
||||
old_email_invalid: '[AuthMe] 기존 이메일이 잘못되었습니다!'
|
||||
email_invalid: '[AuthMe] 이메일이 잘못되었습니다'
|
||||
email_added: '[AuthMe] 이메일 추가됨 !'
|
||||
email_confirm: '[AuthMe] 이메일을 확인해주세요 !'
|
||||
email_changed: '[AuthMe] 이메일 변경됨 !'
|
||||
email_send: '[AuthMe] 복구 이메일 발송됨 !'
|
||||
|
@ -41,9 +41,9 @@ wrong_captcha: '&cNeteisinga Captcha, naudokite : /captcha THE_CAPTCHA'
|
||||
valid_captcha: '&cJusu captcha Teisinga!'
|
||||
kick_forvip: '&cA VIP prisijunge i pilna serveri!'
|
||||
kick_fullserver: '&cServeris yra pilnas, Atsiprasome.'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
email_invalid: '[AuthMe] Invalid Email'
|
||||
|
@ -41,9 +41,9 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA'
|
||||
valid_captcha: '&cYour captcha is valid !'
|
||||
kick_forvip: '&cA VIP Player join the full server!'
|
||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
email_invalid: '[AuthMe] Invalid Email'
|
||||
|
@ -15,7 +15,7 @@ max_reg: '&cAtingiu o numero máximo de registos permitidos'
|
||||
no_perm: '&cSem Permissões'
|
||||
error: '&fOcorreu um erro; Por favor contacte um admin'
|
||||
login_msg: '&cIdentifique-se com "/login password"'
|
||||
reg_msg: '&cPor favor registe-se com "/register password ConfirmePassword"'
|
||||
reg_msg: '&cPor favor registe-se com "/register password confirmePassword"'
|
||||
reg_email_msg: '&ePor favor registe-se com "/register <email> <confirmarEmail>"'
|
||||
usage_unreg: '&cUse: /unregister password'
|
||||
pwd_changed: '&cPassword alterada!'
|
||||
@ -37,14 +37,14 @@ add_email: '&cPor favor adicione o seu email com : /email add seuEmail confirmar
|
||||
bad_database_email: '[AuthMe] O comando /email não está disponível contacte o staff via ticket'
|
||||
recovery_email: '&cPerdeu a sua password? Para a recuperar escreva /email recovery <seuEmail>'
|
||||
usage_captcha: '&cUse: /captcha <theCaptcha>'
|
||||
wrong_captcha: '&cCaptcha errado, por favor use : /captcha THE_CAPTCHA'
|
||||
wrong_captcha: '&cCaptcha errado, por favor use: /captcha THE_CAPTCHA'
|
||||
valid_captcha: '&cO seu captcha é válido!'
|
||||
kick_forvip: '&cUm jogador VIP entrou no servidor cheio!'
|
||||
kick_fullserver: '&cO servidor está actualmente cheio, lamentamos!'
|
||||
usage_email_add: '&fUse: /email add <Email> <confirmeEmail> '
|
||||
usage_email_add: '&fUse: /email add <email> <confirmeEmail> '
|
||||
usage_email_change: '&fUse: /email change <emailAntigo> <emailNovo> '
|
||||
usage_email_recovery: '&fUse: /email recovery <Email>'
|
||||
email_add: '/email add <Email> <confirmEmail>'
|
||||
usage_email_recovery: '&fUse: /email recovery <email>'
|
||||
email_add: '/email add <email> <confirmeEmail>'
|
||||
new_email_invalid: 'Novo email inválido!'
|
||||
old_email_invalid: 'Email antigo inválido!'
|
||||
email_invalid: 'Email inválido!'
|
||||
|
@ -46,9 +46,9 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA'
|
||||
valid_captcha: '&cYour captcha is valid !'
|
||||
kick_forvip: '&cA VIP Player join the full server!'
|
||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
email_invalid: '[AuthMe] Invalid Email'
|
||||
|
@ -10,7 +10,7 @@ usage_reg: '&cPríkaz: /register heslo zopakujHeslo'
|
||||
usage_log: '&cPríkaz: /login heslo'
|
||||
user_unknown: '&cZadané meno nie je zaregistrované!'
|
||||
pwd_changed: '&cHeslo zmenené!'
|
||||
reg_only: '&fVstup iba pre registrovanych! Navstiv http://www.cs-gaming.eu pre registráciu'
|
||||
reg_only: '&fVstup iba pre registrovanych! Navstiv http://example.com pre registráciu'
|
||||
valid_session: '&cZapamätané prihlásenie'
|
||||
login_msg: '&cPrihlás sa príkazom "/login heslo"'
|
||||
reg_msg: '&cZaregistruj sa príkazom "/register heslo zopakujHeslo"'
|
||||
@ -45,9 +45,9 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA'
|
||||
valid_captcha: '&cYour captcha is valid !'
|
||||
kick_forvip: '&cA VIP Player join the full server!'
|
||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
email_invalid: '[AuthMe] Invalid Email'
|
||||
|
@ -41,9 +41,9 @@ wrong_captcha: '&c错误的验证码,请输入:“/captcha <验证码>”'
|
||||
valid_captcha: '&c你的验证码是有效的!'
|
||||
kick_forvip: '&cA VIP Player join the full server!'
|
||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
email_invalid: '[AuthMe] Invalid Email'
|
||||
|
@ -22,7 +22,7 @@ pwd_changed: '&c你成功的更換了你的密碼 !'
|
||||
user_unknown: '&c此用戶名沒有已登記資料 。'
|
||||
password_error: '&f密碼不符合 。'
|
||||
unvalid_session: '&f登入階段資料已損壞 , 請等待登入階段結束 。'
|
||||
reg_only: '&f限已註冊會員 , 請先到 http://member.usociety.org 註冊 。'
|
||||
reg_only: '&f限已註冊會員 , 請先到 http://example.com 註冊 。'
|
||||
logged_in: '&c你已經登入過了 。'
|
||||
logout: '&b你成功的登出了 。'
|
||||
same_nick: '&f同名玩家已在遊玩 。'
|
||||
@ -41,9 +41,9 @@ wrong_captcha: '&c你輸入了錯誤的驗證碼,請使用 《 /captcha <驗
|
||||
valid_captcha: '&c你的驗證碼是無效的 !'
|
||||
kick_forvip: '&cA VIP Player join the full server!'
|
||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||
usage_email_recovery: '&fUsage: /email recovery <email>'
|
||||
new_email_invalid: '[AuthMe] New email invalid!'
|
||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||
email_invalid: '[AuthMe] Invalid Email'
|
||||
|
@ -3,7 +3,7 @@ author: Xephi59
|
||||
website: http://www.multiplayer-italia.com/
|
||||
description: AuthMe prevents people, which aren't logged in, from doing stuff like placing blocks, moving, typing commands or seeing the inventory of the current player.
|
||||
main: uk.org.whoami.authme.AuthMe
|
||||
version: 2.9.2
|
||||
version: 2.9.3
|
||||
softdepend: [Vault, ChestShop, Spout, Multiverse-Core, Notifications, Citizens, CombatTag, Essentials, EssentialsSpawn]
|
||||
commands:
|
||||
register:
|
||||
|
Loading…
Reference in New Issue
Block a user