Skip to content

Commit

Permalink
Complete BCrypt migration
Browse files Browse the repository at this point in the history
  • Loading branch information
MarloDelatorre committed Aug 25, 2024
1 parent 5db3d11 commit edceb81
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 68 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
/out
*.onetoc2
.gradle/
bin/

# Eclipse m2e generated files
# Eclipse Core
Expand Down
1 change: 0 additions & 1 deletion config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ server:
UPDATE_INTERVAL: 777 #Dictates the frequency on which the "centralized server time" is updated.

AUTOMATIC_REGISTER: true #Automatically register players when they login with a nonexistent username.
BCRYPT_MIGRATION: true #Performs a migration from old SHA-1 and SHA-512 password to bcrypt.
COLLECTIVE_CHARSLOT: false #Available character slots are contabilized globally rather than per world server.
DETERRED_MULTICLIENT: false #Enables detection of multi-client and suspicious remote IP on the login system.
#Besides blocking logging in with several client sessions on the same machine, this also blocks suspicious login attempts for players that tries to login on an account using several diferent remote addresses.
Expand Down
68 changes: 30 additions & 38 deletions src/main/java/client/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,34 @@
*/
package client;

import static java.util.concurrent.TimeUnit.SECONDS;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.script.ScriptEngine;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import client.inventory.InventoryType;
import config.YamlConfig;
import constants.game.GameConstants;
Expand All @@ -38,7 +66,6 @@
import net.packet.logging.MonitoredChrLogger;
import net.server.Server;
import net.server.channel.Channel;
import net.server.coordinator.login.LoginBypassCoordinator;
import net.server.coordinator.session.Hwid;
import net.server.coordinator.session.SessionCoordinator;
import net.server.coordinator.session.SessionCoordinator.AntiMulticlientResult;
Expand All @@ -50,8 +77,6 @@
import net.server.world.PartyCharacter;
import net.server.world.PartyOperation;
import net.server.world.World;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import scripting.AbstractPlayerInteraction;
import scripting.event.EventInstanceManager;
import scripting.event.EventManager;
Expand All @@ -66,39 +91,9 @@
import server.maps.FieldLimit;
import server.maps.MapleMap;
import server.maps.MiniDungeonInfo;
import tools.BCrypt;
import tools.HexTool;
import tools.PacketCreator;

import javax.script.ScriptEngine;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import static java.util.concurrent.TimeUnit.SECONDS;
import utils.Crypto;

public class Client extends ChannelInboundHandlerAdapter {
private static final Logger log = LoggerFactory.getLogger(Client.class);
Expand Down Expand Up @@ -509,11 +504,8 @@ public int login(String login, String pwd, Hwid hwid) {
if (getLoginState() > LOGIN_NOTLOGGEDIN) { // already loggedin
loggedIn = false;
loginok = 7;
} else if (passhash.charAt(0) == '$' && passhash.charAt(1) == '2' && BCrypt.checkpw(pwd, passhash)) {
} else if (Crypto.checkpw(pwd, passhash)) {
loginok = (tos == 0) ? 23 : 0;
} else if (pwd.equals(passhash) || checkHash(passhash, "SHA-1", pwd) || checkHash(passhash, "SHA-512", pwd)) {
// thanks GabrielSin for detecting some no-bcrypt inconsistencies here
loginok = (tos == 0) ? (!YamlConfig.config.server.BCRYPT_MIGRATION ? 23 : -23) : (!YamlConfig.config.server.BCRYPT_MIGRATION ? 0 : -10); // migrate to bcrypt
} else {
loggedIn = false;
loginok = 4;
Expand Down
40 changes: 16 additions & 24 deletions src/main/java/net/server/handlers/login/LoginPasswordHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,7 @@
*/
package net.server.handlers.login;

import client.Client;
import client.DefaultDates;
import config.YamlConfig;
import database.DatabaseConnection;
import net.PacketHandler;
import net.packet.InPacket;
import net.server.Server;
import net.server.coordinator.session.Hwid;
import tools.BCrypt;
import tools.HexTool;
import tools.PacketCreator;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.Date;
Expand All @@ -46,19 +32,25 @@
import java.sql.Timestamp;
import java.util.Calendar;

import client.Client;
import client.DefaultDates;
import config.YamlConfig;
import database.DatabaseConnection;
import net.PacketHandler;
import net.packet.InPacket;
import net.server.Server;
import net.server.coordinator.session.Hwid;
import tools.HexTool;
import tools.PacketCreator;
import utils.Crypto;

public final class LoginPasswordHandler implements PacketHandler {

@Override
public boolean validateState(Client c) {
return !c.isLoggedIn();
}

private static String hashpwSHA512(String pwd) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest digester = MessageDigest.getInstance("SHA-512");
digester.update(pwd.getBytes(StandardCharsets.UTF_8), 0, pwd.length());
return HexTool.toHexString(digester.digest()).replace(" ", "").toLowerCase();
}

@Override
public final void handlePacket(InPacket p, Client c) {
String remoteHost = c.getRemoteAddress();
Expand All @@ -79,9 +71,9 @@ public final void handlePacket(InPacket p, Client c) {

if (YamlConfig.config.server.AUTOMATIC_REGISTER && loginok == 5) {
try (Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("INSERT INTO accounts (name, password, birthday, tempban) VALUES (?, ?, ?, ?);", Statement.RETURN_GENERATED_KEYS)) { //Jayd: Added birthday, tempban
ps.setString(1, login);
ps.setString(2, YamlConfig.config.server.BCRYPT_MIGRATION ? BCrypt.hashpw(pwd, BCrypt.gensalt(12)) : hashpwSHA512(pwd));
PreparedStatement ps = con.prepareStatement("INSERT INTO accounts (name, password, birthday, tempban) VALUES (?, ?, ?, ?);", Statement.RETURN_GENERATED_KEYS)) {
ps.setString(1, login);
ps.setString(2, Crypto.hashpw(pwd, Crypto.gensalt(12)));
ps.setDate(3, Date.valueOf(DefaultDates.getBirthday()));
ps.setTimestamp(4, Timestamp.valueOf(DefaultDates.getTempban()));
ps.executeUpdate();
Expand All @@ -101,7 +93,7 @@ public final void handlePacket(InPacket p, Client c) {
if (YamlConfig.config.server.BCRYPT_MIGRATION && (loginok <= -10)) { // -10 means migration to bcrypt, -23 means TOS wasn't accepted
try (Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE accounts SET password = ? WHERE name = ?;")) {
ps.setString(1, BCrypt.hashpw(pwd, BCrypt.gensalt(12)));
ps.setString(1, Crypto.hashpw(pwd, Crypto.gensalt(12)));
ps.setString(2, login);
ps.executeUpdate();
} catch (SQLException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package tools;
package utils;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
Expand Down Expand Up @@ -60,7 +60,7 @@
* @author Damien Miller
* @version 0.4
*/
public class BCrypt {
public class Crypto {
// BCrypt parameters

private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10;
Expand Down Expand Up @@ -770,7 +770,7 @@ public static String hashpw(String password, String salt) {
* @return the hashed password
*/
public static String hashpw(byte[] passwordb, String salt) {
BCrypt B;
Crypto B;
String real_salt;
byte[] saltb, hashed;
char minor = (char) 0;
Expand Down Expand Up @@ -806,7 +806,7 @@ public static String hashpw(byte[] passwordb, String salt) {
passwordb = Arrays.copyOf(passwordb, passwordb.length + 1);
}

B = new BCrypt();
B = new Crypto();
hashed = B.crypt_raw(passwordb, saltb, rounds,
minor == 'x', // true for sign extension bug ('2x')
minor == 'a' ? 0x10000 : 0, // safety factor for '2a'
Expand Down Expand Up @@ -968,4 +968,4 @@ public static boolean checkpw(byte[] plaintext, String hashed) {
}
return ret == 0;
}
}
}

0 comments on commit edceb81

Please sign in to comment.