Skip to content

Commit 140a02e

Browse files
committed
Add BCrypt implementation opt-in
1 parent ab20b6f commit 140a02e

29 files changed

+101
-960
lines changed

Diff for: Kepler-Server/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ dependencies {
5959

6060
implementation 'com.goterl.lazycode:lazysodium-java:3.3.0'
6161
implementation 'com.github.bhlangonijr:chesslib:1.1.1'
62+
63+
// https://mvnrepository.com/artifact/at.favre.lib/bcrypt
64+
compile group: 'at.favre.lib', name: 'bcrypt', version: '0.9.0'
6265
}
6366

6467
// Create fat jar with libraries inside of it.

Diff for: Kepler-Server/src/main/java/org/alexdev/kepler/Kepler.java

+20
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package org.alexdev.kepler;
22

3+
import at.favre.lib.crypto.bcrypt.BCrypt;
4+
import com.goterl.lazycode.lazysodium.LazySodiumJava;
5+
import com.goterl.lazycode.lazysodium.SodiumJava;
36
import io.netty.util.ResourceLeakDetector;
47
import org.alexdev.kepler.dao.Storage;
8+
import org.alexdev.kepler.dao.mysql.PlayerDao;
59
import org.alexdev.kepler.dao.mysql.SettingsDao;
610
import org.alexdev.kepler.game.GameScheduler;
711
import org.alexdev.kepler.game.bot.BotManager;
@@ -16,13 +20,15 @@
1620
import org.alexdev.kepler.game.item.ItemManager;
1721
import org.alexdev.kepler.game.moderation.ChatManager;
1822
import org.alexdev.kepler.game.navigator.NavigatorManager;
23+
import org.alexdev.kepler.game.player.PlayerDetails;
1924
import org.alexdev.kepler.game.player.PlayerManager;
2025
import org.alexdev.kepler.game.recycler.RecyclerManager;
2126
import org.alexdev.kepler.game.room.RoomManager;
2227
import org.alexdev.kepler.game.room.models.RoomModelManager;
2328
import org.alexdev.kepler.game.room.public_rooms.walkways.WalkwaysManager;
2429
import org.alexdev.kepler.game.texts.TextsManager;
2530
import org.alexdev.kepler.messages.MessageHandler;
31+
import org.alexdev.kepler.messages.incoming.register.REGISTER;
2632
import org.alexdev.kepler.server.mus.MusServer;
2733
import org.alexdev.kepler.server.netty.NettyServer;
2834
import org.alexdev.kepler.server.rcon.RconServer;
@@ -35,6 +41,7 @@
3541
import org.slf4j.Logger;
3642
import org.slf4j.LoggerFactory;
3743

44+
import java.io.Console;
3845
import java.io.IOException;
3946
import java.net.UnknownHostException;
4047

@@ -58,6 +65,8 @@ public class Kepler {
5865
private static RconServer rconServer;
5966
private static Logger log;
6067

68+
private static LazySodiumJava LIB_SODIUM;
69+
6170
/**
6271
* Main call of Java application
6372
* @param args System arguments
@@ -115,6 +124,13 @@ public static void main(String[] args) {
115124
// Update players online back to 0
116125
SettingsDao.updateSetting("players.online", "0");
117126

127+
if (ServerConfiguration.getStringOrDefault("password.hashing.library", "argon2").equalsIgnoreCase("argon2")) {
128+
log.info("Using Argon2 password hashing algorithim");
129+
LIB_SODIUM = new LazySodiumJava(new SodiumJava());
130+
} else {
131+
log.info("Using BCrypt password hashing algorithim");
132+
}
133+
118134
setupMus();
119135
setupRcon();
120136
setupServer();
@@ -298,4 +314,8 @@ public static long getStartupTime() {
298314
public static boolean isShuttingdown() {
299315
return isShutdown;
300316
}
317+
318+
public static LazySodiumJava getLibSodium() {
319+
return LIB_SODIUM;
320+
}
301321
}

Diff for: Kepler-Server/src/main/java/org/alexdev/kepler/dao/mysql/PlayerDao.java

+24-9
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
package org.alexdev.kepler.dao.mysql;
22

3+
import at.favre.lib.crypto.bcrypt.BCrypt;
34
import com.goterl.lazycode.lazysodium.LazySodiumJava;
45
import com.goterl.lazycode.lazysodium.SodiumJava;
56
import com.goterl.lazycode.lazysodium.interfaces.PwHash;
7+
import org.alexdev.kepler.Kepler;
68
import org.alexdev.kepler.dao.Storage;
79
import org.alexdev.kepler.game.player.Player;
810
import org.alexdev.kepler.game.player.PlayerDetails;
911
import org.alexdev.kepler.util.DateUtil;
1012

13+
import java.lang.constant.Constable;
1114
import java.nio.charset.StandardCharsets;
1215
import java.sql.*;
1316

1417
public class PlayerDao {
15-
public static final LazySodiumJava LIB_SODIUM = new LazySodiumJava(new SodiumJava());
16-
1718
/**
1819
* Logs the IP address for a given user
1920
*
@@ -188,7 +189,7 @@ public static boolean loginTicket(Player player, String ssoTicket) {
188189
* @param password password
189190
* @return true, if successful
190191
*/
191-
public static boolean login(PlayerDetails player, String username, String password) {
192+
public static boolean login(PlayerDetails player, String username, String password, boolean useLibSodium, boolean useBcrypt) {
192193
boolean success = false;
193194

194195
Connection sqlConnection = null;
@@ -202,14 +203,28 @@ public static boolean login(PlayerDetails player, String username, String passwo
202203
resultSet = preparedStatement.executeQuery();
203204

204205
if (resultSet.next()) {
205-
byte[] hashedPassword = (resultSet.getString("password") + '\0').getBytes(StandardCharsets.UTF_8);
206-
byte[] pass = password.getBytes(StandardCharsets.UTF_8);
206+
if (useLibSodium) {
207+
byte[] hashedPassword = (resultSet.getString("password") + '\0').getBytes(StandardCharsets.UTF_8);
208+
byte[] pass = password.getBytes(StandardCharsets.UTF_8);
209+
210+
PwHash.Native pwHash = (PwHash.Native) Kepler.getLibSodium();
211+
success = pwHash.cryptoPwHashStrVerify(hashedPassword, pass, pass.length);
212+
213+
if (success) {
214+
fill(player, resultSet);
215+
}
216+
}
217+
218+
if (useBcrypt) {
219+
var hashedPassword = resultSet.getString("password");
220+
221+
BCrypt.Result result = BCrypt.verifyer().verify(password.toCharArray(), hashedPassword);
222+
success = result.verified;
207223

208-
PwHash.Native pwHash = (PwHash.Native) LIB_SODIUM;
209-
success = pwHash.cryptoPwHashStrVerify(hashedPassword, pass, pass.length);
224+
if (success) {
225+
fill(player, resultSet);
210226

211-
if (success) {
212-
fill(player, resultSet);
227+
}
213228
}
214229
}
215230

Diff for: Kepler-Server/src/main/java/org/alexdev/kepler/messages/incoming/handshake/TRY_LOGIN.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.alexdev.kepler.messages.types.MessageEvent;
77
import org.alexdev.kepler.server.netty.streams.NettyRequest;
88
import org.alexdev.kepler.util.StringUtil;
9+
import org.alexdev.kepler.util.config.ServerConfiguration;
910

1011
public class TRY_LOGIN implements MessageEvent {
1112

@@ -18,7 +19,10 @@ public void handle(Player player, NettyRequest reader) {
1819
String username = StringUtil.filterInput(reader.readString(), true);
1920
String password = StringUtil.filterInput(reader.readString(), true);
2021

21-
if (!PlayerDao.login(player.getDetails(), username, password)) {
22+
if (!PlayerDao.login(player.getDetails(), username, password,
23+
ServerConfiguration.getStringOrDefault("password.hashing.library", "argon2").equalsIgnoreCase("argon2"),
24+
ServerConfiguration.getStringOrDefault("password.hashing.library", "argon2").equalsIgnoreCase("bcrypt")
25+
)) {
2226
player.send(new LOCALISED_ERROR("Login incorrect"));
2327
} else {
2428
player.login();

Diff for: Kepler-Server/src/main/java/org/alexdev/kepler/messages/incoming/register/REGISTER.java

+31-17
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package org.alexdev.kepler.messages.incoming.register;
22

3+
import at.favre.lib.crypto.bcrypt.BCrypt;
34
import com.goterl.lazycode.lazysodium.interfaces.PwHash;
5+
import org.alexdev.kepler.Kepler;
46
import org.alexdev.kepler.dao.mysql.PlayerDao;
57
import org.alexdev.kepler.game.player.Player;
68
import org.alexdev.kepler.messages.types.MessageEvent;
79
import org.alexdev.kepler.server.netty.NettyPlayerNetwork;
810
import org.alexdev.kepler.server.netty.streams.NettyRequest;
11+
import org.alexdev.kepler.util.config.ServerConfiguration;
912

1013
public class REGISTER implements MessageEvent {
1114
@Override
@@ -67,28 +70,39 @@ public void handle(Player player, NettyRequest reader) throws Exception {
6770
return;
6871
}
6972

70-
PlayerDao.register(username, createPassword(password), figure, gender);
73+
var hashedPassword = createPassword(password);
74+
75+
if (hashedPassword == null)
76+
return;
77+
78+
PlayerDao.register(username, hashedPassword, figure, gender);
7179
//System.out.println(name + " / " + figure + " / " + gender + " / " + email + " / " + birthday + " / " + password);
7280
}
7381

7482
public static String createPassword(String password) throws Exception {
75-
byte[] pw = password.getBytes();
76-
byte[] outputHash = new byte[PwHash.STR_BYTES];
77-
PwHash.Native pwHash = (PwHash.Native) PlayerDao.LIB_SODIUM;
78-
boolean success = pwHash.cryptoPwHashStr(
79-
outputHash,
80-
pw,
81-
pw.length,
82-
PwHash.OPSLIMIT_INTERACTIVE,
83-
PwHash.MEMLIMIT_INTERACTIVE
84-
);
85-
86-
if (!success) {
87-
throw new Exception("Password creation was a failure!");
83+
if (ServerConfiguration.getStringOrDefault("password.hashing.library", "argon2").equalsIgnoreCase("argon2")) {
84+
byte[] pw = password.getBytes();
85+
byte[] outputHash = new byte[PwHash.STR_BYTES];
86+
PwHash.Native pwHash = (PwHash.Native) Kepler.getLibSodium();
87+
boolean success = pwHash.cryptoPwHashStr(
88+
outputHash,
89+
pw,
90+
pw.length,
91+
PwHash.OPSLIMIT_INTERACTIVE,
92+
PwHash.MEMLIMIT_INTERACTIVE
93+
);
94+
95+
if (!success) {
96+
throw new Exception("Password creation was a failure!");
97+
}
98+
99+
return new String(outputHash).replace((char) 0 + "", "");
88100
}
89101

90-
return new String(outputHash).replace((char)0 + "", "");
91-
}
92-
102+
if (ServerConfiguration.getStringOrDefault("password.hashing.library", "argon2").equalsIgnoreCase("bcrypt")) {
103+
return BCrypt.withDefaults().hashToString(12, password.toCharArray());
104+
}
93105

106+
return null;
107+
}
94108
}

Diff for: Kepler-Server/src/main/java/org/alexdev/kepler/server/mus/MusConnectionHandler.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.alexdev.kepler.server.netty.NettyPlayerNetwork;
3131
import org.alexdev.kepler.util.DateUtil;
3232
import org.alexdev.kepler.util.StringUtil;
33+
import org.alexdev.kepler.util.config.ServerConfiguration;
3334
import org.apache.commons.lang3.StringUtils;
3435
import org.slf4j.Logger;
3536
import org.slf4j.LoggerFactory;
@@ -109,7 +110,10 @@ public void channelRead0(ChannelHandlerContext ctx, MusMessage message) {
109110

110111
PlayerDetails playerDetails = new PlayerDetails();
111112

112-
if (PlayerDao.login(playerDetails, username, password)) {
113+
if (PlayerDao.login(playerDetails, username, password,
114+
ServerConfiguration.getStringOrDefault("password.hashing.library", "argon2").equalsIgnoreCase("argon2"),
115+
ServerConfiguration.getStringOrDefault("password.hashing.library", "argon2").equalsIgnoreCase("bcrypt")
116+
)) {
113117
player = PlayerManager.getInstance().getPlayerById(playerDetails.getId());
114118
userId = playerDetails.getId();
115119
} else {

Diff for: Kepler-Server/src/main/java/org/alexdev/kepler/util/config/ServerConfiguration.java

+10
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ public static String getString(String key) {
5858
return config.getOrDefault(key, key);
5959
}
6060

61+
/**
62+
* Get value from configuration
63+
*
64+
* @param key the key to use
65+
* @return value
66+
*/
67+
public static String getStringOrDefault(String key, String value) {
68+
return config.getOrDefault(key, value);
69+
}
70+
6171
/**
6272
* Get value from configuration and cast to an Integer
6373
*

Diff for: Kepler-Server/src/main/java/org/alexdev/kepler/util/config/writer/DefaultConfigWriter.java

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public Map<String, String> setConfigurationDefaults() {
3535
config.put("v21.version.port", "0");
3636
config.put("v26.version.port", "0");
3737

38+
config.put("password.hashing.library", "argon2");
3839
config.put("debug", "false");
3940
return config;
4041
}
@@ -68,6 +69,8 @@ public void setConfigurationData(Map<String, String> config, PrintWriter writer)
6869
writer.println("mysql.password=" + config.get("mysql.password"));
6970
writer.println("mysql.database=" + config.get("mysql.database"));
7071
writer.println("");
72+
writer.println("password.hashing.library=" + config.get("password.hashing.library"));
73+
writer.println("");
7174
writer.println("[Logging]");
7275
writer.println("log.received.packets=" + config.get("log.received.packets"));
7376
writer.println("log.sent.packets=" + config.get("log.sent.packets"));

Diff for: Kepler-Web/.gitignore

-18
This file was deleted.

Diff for: Kepler-Web/build.gradle

-62
This file was deleted.

Diff for: Kepler-Web/libs/RetroRCON-1.1.jar

-148 KB
Binary file not shown.

Diff for: Kepler-Web/libs/duckHTTPD-all.jar

-5.05 MB
Binary file not shown.

0 commit comments

Comments
 (0)