From c27a9714e0104c0bcb9c5d8603053314a4a2c295 Mon Sep 17 00:00:00 2001 From: Simplxs <44570052+Simplxss@users.noreply.github.com> Date: Mon, 4 Sep 2023 20:38:38 +0800 Subject: [PATCH 1/5] enableRandomEncryptSeed --- .../grasscutter/config/ConfigContainer.java | 2 + .../grasscutter/net/packet/BasePacket.java | 8 +-- .../grasscutter/server/game/GameSession.java | 16 +++++- .../packet/recv/HandlerGetPlayerTokenReq.java | 5 +- .../packet/send/PacketGetPlayerTokenRsp.java | 6 ++- .../java/emu/grasscutter/utils/Crypto.java | 38 ++++++++++--- .../utils/algorithm/MersenneTwister64.java | 54 +++++++++++++++++++ 7 files changed, 108 insertions(+), 21 deletions(-) create mode 100644 src/main/java/emu/grasscutter/utils/algorithm/MersenneTwister64.java diff --git a/src/main/java/emu/grasscutter/config/ConfigContainer.java b/src/main/java/emu/grasscutter/config/ConfigContainer.java index d68936cec10..e4f4dc8e17b 100644 --- a/src/main/java/emu/grasscutter/config/ConfigContainer.java +++ b/src/main/java/emu/grasscutter/config/ConfigContainer.java @@ -169,6 +169,8 @@ public static class Game { /* This is the port used in the default region. */ public int accessPort = 0; + public boolean enableRandomEncryptSeed = true; + /* Entities within a certain range will be loaded for the player */ public int loadEntitiesForPlayerRange = 300; /* Start in 'unstable-quests', Lua scripts will be enabled by default. */ diff --git a/src/main/java/emu/grasscutter/net/packet/BasePacket.java b/src/main/java/emu/grasscutter/net/packet/BasePacket.java index ce605f63725..5918d93aab1 100644 --- a/src/main/java/emu/grasscutter/net/packet/BasePacket.java +++ b/src/main/java/emu/grasscutter/net/packet/BasePacket.java @@ -108,13 +108,7 @@ public byte[] build() { this.writeBytes(baos, data); this.writeUint16(baos, const2); - byte[] packet = baos.toByteArray(); - - if (this.shouldEncrypt) { - Crypto.xor(packet, this.useDispatchKey() ? Crypto.DISPATCH_KEY : Crypto.ENCRYPT_KEY); - } - - return packet; + return baos.toByteArray(); } public void writeUint16(ByteArrayOutputStream baos, int i) { diff --git a/src/main/java/emu/grasscutter/server/game/GameSession.java b/src/main/java/emu/grasscutter/server/game/GameSession.java index 0cff31cd125..1f15552d526 100644 --- a/src/main/java/emu/grasscutter/server/game/GameSession.java +++ b/src/main/java/emu/grasscutter/server/game/GameSession.java @@ -23,6 +23,9 @@ public class GameSession implements GameSessionManager.KcpChannel { @Getter @Setter private Account account; @Getter private Player player; + @Getter private long encryptSeed; + private final byte[] encryptKey = new byte[4096]; + @Setter private boolean useSecretKey; @Getter @Setter private SessionState state; @@ -34,6 +37,10 @@ public GameSession(GameServer server) { this.server = server; this.state = SessionState.WAITING_FOR_TOKEN; this.lastPingTime = System.currentTimeMillis(); + + if (GAME_INFO.enableRandomEncryptSeed) { + encryptSeed = Crypto.generateEncryptKeyAndSeed(encryptKey); + } } public GameServer getServer() { @@ -133,7 +140,12 @@ public void send(BasePacket packet) { event.call(); if (!event.isCanceled()) { // If event is not cancelled, continue. try { - tunnel.writeData(event.getPacket().build()); + packet = event.getPacket(); + var bytes = packet.build(); + if (packet.shouldEncrypt) { + Crypto.xor(bytes, packet.useDispatchKey() ? Crypto.DISPATCH_KEY : GAME_INFO.enableRandomEncryptSeed ? encryptKey : Crypto.ENCRYPT_KEY); + } + tunnel.writeData(bytes); } catch (Exception ignored) { Grasscutter.getLogger().debug("Unable to send packet to client."); } @@ -149,7 +161,7 @@ public void onConnected(GameSessionManager.KcpTunnel tunnel) { @Override public void handleReceive(byte[] bytes) { // Decrypt and turn back into a packet - Crypto.xor(bytes, useSecretKey() ? Crypto.ENCRYPT_KEY : Crypto.DISPATCH_KEY); + Crypto.xor(bytes, useSecretKey() ? GAME_INFO.enableRandomEncryptSeed ? encryptKey : Crypto.ENCRYPT_KEY : Crypto.DISPATCH_KEY); ByteBuf packet = Unpooled.wrappedBuffer(bytes); // Log diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java index 5f25512fcd8..0869a93013c 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java @@ -1,6 +1,7 @@ package emu.grasscutter.server.packet.recv; import static emu.grasscutter.config.Configuration.ACCOUNT; +import static emu.grasscutter.config.Configuration.GAME_INFO; import emu.grasscutter.*; import emu.grasscutter.database.DatabaseHelper; @@ -119,7 +120,7 @@ public void handle(GameSession session, byte[] header, byte[] payload) throws Ex var client_seed = ByteBuffer.wrap(cipher.doFinal(client_seed_encrypted)).getLong(); var seed_bytes = - ByteBuffer.wrap(new byte[8]).putLong(Crypto.ENCRYPT_SEED ^ client_seed).array(); + ByteBuffer.wrap(new byte[8]).putLong((GAME_INFO.enableRandomEncryptSeed ? session.getEncryptSeed() : Crypto.ENCRYPT_SEED) ^ client_seed).array(); cipher.init(Cipher.ENCRYPT_MODE, Crypto.EncryptionKeys.get(req.getKeyId())); var seed_encrypted = cipher.doFinal(seed_bytes); @@ -136,7 +137,7 @@ public void handle(GameSession session, byte[] header, byte[] payload) throws Ex } catch (Exception ignored) { // Only UA Patch users will have exception var clientBytes = Utils.base64Decode(req.getClientRandKey()); - var seed = ByteHelper.longToBytes(Crypto.ENCRYPT_SEED); + var seed = ByteHelper.longToBytes(GAME_INFO.enableRandomEncryptSeed ? session.getEncryptSeed() : Crypto.ENCRYPT_SEED); Crypto.xor(clientBytes, seed); var base64str = Utils.base64Encode(clientBytes); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java index 29d85565152..9d7c18a21bd 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java @@ -6,6 +6,8 @@ import emu.grasscutter.server.game.GameSession; import emu.grasscutter.utils.Crypto; +import static emu.grasscutter.config.Configuration.GAME_INFO; + public class PacketGetPlayerTokenRsp extends BasePacket { public PacketGetPlayerTokenRsp(GameSession session) { @@ -20,7 +22,7 @@ public PacketGetPlayerTokenRsp(GameSession session) { .setAccountType(1) .setIsProficientPlayer( session.getPlayer().getAvatars().getAvatarCount() > 0) // Not sure where this goes - .setSecretKeySeed(Crypto.ENCRYPT_SEED) + .setSecretKeySeed(GAME_INFO.enableRandomEncryptSeed ? session.getEncryptSeed() : Crypto.ENCRYPT_SEED) .setSecurityCmdBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER)) .setPlatformType(3) .setChannelId(1) @@ -66,7 +68,7 @@ public PacketGetPlayerTokenRsp( .setAccountType(1) .setIsProficientPlayer( session.getPlayer().getAvatars().getAvatarCount() > 0) // Not sure where this goes - .setSecretKeySeed(Crypto.ENCRYPT_SEED) + .setSecretKeySeed(GAME_INFO.enableRandomEncryptSeed ? session.getEncryptSeed() : Crypto.ENCRYPT_SEED) .setSecurityCmdBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER)) .setPlatformType(3) .setChannelId(1) diff --git a/src/main/java/emu/grasscutter/utils/Crypto.java b/src/main/java/emu/grasscutter/utils/Crypto.java index d9f4a8403b4..685d4f2a114 100644 --- a/src/main/java/emu/grasscutter/utils/Crypto.java +++ b/src/main/java/emu/grasscutter/utils/Crypto.java @@ -2,6 +2,8 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.server.http.objects.QueryCurRegionRspJson; +import emu.grasscutter.utils.algorithm.MersenneTwister64; + import java.io.ByteArrayOutputStream; import java.nio.file.Path; import java.security.*; @@ -34,9 +36,9 @@ public static void loadKeys() { try { CUR_SIGNING_KEY = - KeyFactory.getInstance("RSA") - .generatePrivate( - new PKCS8EncodedKeySpec(FileUtils.readResource("/keys/SigningKey.der"))); + KeyFactory.getInstance("RSA") + .generatePrivate( + new PKCS8EncodedKeySpec(FileUtils.readResource("/keys/SigningKey.der"))); Pattern pattern = Pattern.compile("([0-9]*)_Pub\\.der"); for (Path path : FileUtils.getPathsFromResource("/keys/game_keys")) { @@ -46,8 +48,8 @@ public static void loadKeys() { if (m.matches()) { var key = - KeyFactory.getInstance("RSA") - .generatePublic(new X509EncodedKeySpec(FileUtils.read(path))); + KeyFactory.getInstance("RSA") + .generatePublic(new X509EncodedKeySpec(FileUtils.read(path))); EncryptionKeys.put(Integer.valueOf(m.group(1)), key); } @@ -74,8 +76,28 @@ public static byte[] createSessionKey(int length) { return bytes; } + public static long generateEncryptKeyAndSeed(byte[] encryptKey) { + var encryptSeed = secureRandom.nextLong(); + var mt = new MersenneTwister64(); + mt.setSeed(encryptSeed); + mt.setSeed(mt.nextLong()); + mt.nextLong(); + for (int i = 0; i < 4096 >> 3; i++) { + var rand = mt.nextLong(); + encryptKey[i << 3] = (byte) (rand >> 56); + encryptKey[(i << 3) + 1] = (byte) (rand >> 48); + encryptKey[(i << 3) + 2] = (byte) (rand >> 40); + encryptKey[(i << 3) + 3] = (byte) (rand >> 32); + encryptKey[(i << 3) + 4] = (byte) (rand >> 24); + encryptKey[(i << 3) + 5] = (byte) (rand >> 16); + encryptKey[(i << 3) + 6] = (byte) (rand >> 8); + encryptKey[(i << 3) + 7] = (byte) rand; + } + return encryptSeed; + } + public static QueryCurRegionRspJson encryptAndSignRegionData(byte[] regionInfo, String key_id) - throws Exception { + throws Exception { if (key_id == null) { throw new Exception("Key ID was not set"); } @@ -93,8 +115,8 @@ public static QueryCurRegionRspJson encryptAndSignRegionData(byte[] regionInfo, for (int i = 0; i < numChunks; i++) { byte[] chunk = - Arrays.copyOfRange( - regionInfo, i * chunkSize, Math.min((i + 1) * chunkSize, regionInfoLength)); + Arrays.copyOfRange( + regionInfo, i * chunkSize, Math.min((i + 1) * chunkSize, regionInfoLength)); byte[] encryptedChunk = cipher.doFinal(chunk); encryptedRegionInfoStream.write(encryptedChunk); } diff --git a/src/main/java/emu/grasscutter/utils/algorithm/MersenneTwister64.java b/src/main/java/emu/grasscutter/utils/algorithm/MersenneTwister64.java new file mode 100644 index 00000000000..8916322fa76 --- /dev/null +++ b/src/main/java/emu/grasscutter/utils/algorithm/MersenneTwister64.java @@ -0,0 +1,54 @@ +package emu.grasscutter.utils.algorithm; + +public class MersenneTwister64 { + // Period parameters + private static final int N = 312; + private static final int M = 156; + private static final long MATRIX_A = 0xB5026F5AA96619E9L; // private static final * constant vector a + private static final long UPPER_MASK = 0xFFFFFFFF80000000L; // most significant w-r bits + private static final int LOWER_MASK = 0x7FFFFFFF; // least significant r bits + + private final long[] mt = new long[N]; // the array for the state vector + private int mti; // mti==N+1 means mt[N] is not initialized + + synchronized public void setSeed(long seed) { + mt[0] = seed; + for (mti = 1; mti < N; mti++) { + mt[mti] = (0x5851F42D4C957F2DL * (mt[mti - 1] ^ (mt[mti - 1] >>> 62)) + mti); + } + } + + public synchronized long nextLong() { + int i; + long x; + final long[] mag01 = {0x0L, MATRIX_A}; + + if (mti >= N) // generate N words at one time + { + if (mti == N + 1) { + setSeed(5489L); + } + + for (i = 0; i < N - M; i++) { + x = (mt[i] & UPPER_MASK) | (mt[i + 1] & LOWER_MASK); + mt[i] = mt[i + M] ^ (x >>> 1) ^ mag01[(int) (x & 0x1)]; + } + for (; i < N - 1; i++) { + x = (mt[i] & UPPER_MASK) | (mt[i + 1] & LOWER_MASK); + mt[i] = mt[i + (M - N)] ^ (x >>> 1) ^ mag01[(int) (x & 0x1)]; + } + x = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK); + mt[N - 1] = mt[M - 1] ^ (x >>> 1) ^ mag01[(int) (x & 0x1)]; + + mti = 0; + } + + x = mt[mti++]; + x ^= (x >>> 29) & 0x5555555555555555L; + x ^= (x << 17) & 0x71D67FFFEDA60000L; + x ^= (x << 37) & 0xFFF7EEE000000000L; + x ^= (x >>> 43); + + return x; + } +} From 3d5091e82ea8986c6757b7e2365f311b2db2f387 Mon Sep 17 00:00:00 2001 From: Simplxs <44570052+Simplxss@users.noreply.github.com> Date: Mon, 4 Sep 2023 20:49:50 +0800 Subject: [PATCH 2/5] update config version --- src/main/java/emu/grasscutter/config/ConfigContainer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/emu/grasscutter/config/ConfigContainer.java b/src/main/java/emu/grasscutter/config/ConfigContainer.java index e4f4dc8e17b..32d6c4d82c8 100644 --- a/src/main/java/emu/grasscutter/config/ConfigContainer.java +++ b/src/main/java/emu/grasscutter/config/ConfigContainer.java @@ -33,9 +33,11 @@ public class ConfigContainer { * Lua script require system if performance is a concern. * Version 12 - 'http.startImmediately' was added to control whether the * HTTP server should start immediately. + * Version 13 - 'game.enableRandomEncryptSeed' was added to control whether the + * encryption use random seed and key. */ private static int version() { - return 12; + return 13; } /** From 5d2f9db3cd3f1b7010a61c7a461b5184b36dfe8e Mon Sep 17 00:00:00 2001 From: Simplxs Date: Mon, 11 Sep 2023 12:30:59 +0800 Subject: [PATCH 3/5] make the codes more beautiful --- .../emu/grasscutter/config/ConfigContainer.java | 7 ++++--- .../emu/grasscutter/server/game/GameSession.java | 13 +++++++------ .../packet/recv/HandlerGetPlayerTokenReq.java | 6 +++--- .../server/packet/send/PacketGetPlayerTokenRsp.java | 6 ++---- .../utils/algorithm/MersenneTwister64.java | 11 +++++------ 5 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/main/java/emu/grasscutter/config/ConfigContainer.java b/src/main/java/emu/grasscutter/config/ConfigContainer.java index 32d6c4d82c8..fd264e26bb8 100644 --- a/src/main/java/emu/grasscutter/config/ConfigContainer.java +++ b/src/main/java/emu/grasscutter/config/ConfigContainer.java @@ -33,8 +33,8 @@ public class ConfigContainer { * Lua script require system if performance is a concern. * Version 12 - 'http.startImmediately' was added to control whether the * HTTP server should start immediately. - * Version 13 - 'game.enableRandomEncryptSeed' was added to control whether the - * encryption use random seed and key. + * Version 13 - 'game.useUniquePacketKey' was added to control whether the + * encryption key used for packets is a constant or randomly generated. */ private static int version() { return 13; @@ -171,7 +171,8 @@ public static class Game { /* This is the port used in the default region. */ public int accessPort = 0; - public boolean enableRandomEncryptSeed = true; + /* Enabling this will generate a unique packet encryption key for each player. */ + public boolean useUniquePacketKey = true; /* Entities within a certain range will be loaded for the player */ public int loadEntitiesForPlayerRange = 300; diff --git a/src/main/java/emu/grasscutter/server/game/GameSession.java b/src/main/java/emu/grasscutter/server/game/GameSession.java index 1f15552d526..fa0d1a35799 100644 --- a/src/main/java/emu/grasscutter/server/game/GameSession.java +++ b/src/main/java/emu/grasscutter/server/game/GameSession.java @@ -23,8 +23,8 @@ public class GameSession implements GameSessionManager.KcpChannel { @Getter @Setter private Account account; @Getter private Player player; - @Getter private long encryptSeed; - private final byte[] encryptKey = new byte[4096]; + @Getter private long encryptSeed = Crypto.ENCRYPT_SEED; + private byte[] encryptKey = Crypto.ENCRYPT_KEY; @Setter private boolean useSecretKey; @Getter @Setter private SessionState state; @@ -38,8 +38,9 @@ public GameSession(GameServer server) { this.state = SessionState.WAITING_FOR_TOKEN; this.lastPingTime = System.currentTimeMillis(); - if (GAME_INFO.enableRandomEncryptSeed) { - encryptSeed = Crypto.generateEncryptKeyAndSeed(encryptKey); + if (GAME_INFO.useUniquePacketKey) { + this.encryptKey = new byte[4096]; + this.encryptSeed = Crypto.generateEncryptKeyAndSeed(this.encryptKey); } } @@ -143,7 +144,7 @@ public void send(BasePacket packet) { packet = event.getPacket(); var bytes = packet.build(); if (packet.shouldEncrypt) { - Crypto.xor(bytes, packet.useDispatchKey() ? Crypto.DISPATCH_KEY : GAME_INFO.enableRandomEncryptSeed ? encryptKey : Crypto.ENCRYPT_KEY); + Crypto.xor(bytes, packet.useDispatchKey() ? Crypto.DISPATCH_KEY : this.encryptKey); } tunnel.writeData(bytes); } catch (Exception ignored) { @@ -161,7 +162,7 @@ public void onConnected(GameSessionManager.KcpTunnel tunnel) { @Override public void handleReceive(byte[] bytes) { // Decrypt and turn back into a packet - Crypto.xor(bytes, useSecretKey() ? GAME_INFO.enableRandomEncryptSeed ? encryptKey : Crypto.ENCRYPT_KEY : Crypto.DISPATCH_KEY); + Crypto.xor(bytes, useSecretKey() ? this.encryptKey : Crypto.DISPATCH_KEY); ByteBuf packet = Unpooled.wrappedBuffer(bytes); // Log diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java index 0869a93013c..703f39df5b8 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java @@ -1,7 +1,6 @@ package emu.grasscutter.server.packet.recv; import static emu.grasscutter.config.Configuration.ACCOUNT; -import static emu.grasscutter.config.Configuration.GAME_INFO; import emu.grasscutter.*; import emu.grasscutter.database.DatabaseHelper; @@ -112,6 +111,7 @@ public void handle(GameSession session, byte[] header, byte[] payload) throws Ex // Only >= 2.7.50 has this if (req.getKeyId() > 0) { + var encrypt_seed = session.getEncryptSeed(); try { var cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, Crypto.CUR_SIGNING_KEY); @@ -120,7 +120,7 @@ public void handle(GameSession session, byte[] header, byte[] payload) throws Ex var client_seed = ByteBuffer.wrap(cipher.doFinal(client_seed_encrypted)).getLong(); var seed_bytes = - ByteBuffer.wrap(new byte[8]).putLong((GAME_INFO.enableRandomEncryptSeed ? session.getEncryptSeed() : Crypto.ENCRYPT_SEED) ^ client_seed).array(); + ByteBuffer.wrap(new byte[8]).putLong(encrypt_seed ^ client_seed).array(); cipher.init(Cipher.ENCRYPT_MODE, Crypto.EncryptionKeys.get(req.getKeyId())); var seed_encrypted = cipher.doFinal(seed_bytes); @@ -137,7 +137,7 @@ public void handle(GameSession session, byte[] header, byte[] payload) throws Ex } catch (Exception ignored) { // Only UA Patch users will have exception var clientBytes = Utils.base64Decode(req.getClientRandKey()); - var seed = ByteHelper.longToBytes(GAME_INFO.enableRandomEncryptSeed ? session.getEncryptSeed() : Crypto.ENCRYPT_SEED); + var seed = ByteHelper.longToBytes(encrypt_seed); Crypto.xor(clientBytes, seed); var base64str = Utils.base64Encode(clientBytes); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java index 9d7c18a21bd..6a1ab63f0ba 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java @@ -6,8 +6,6 @@ import emu.grasscutter.server.game.GameSession; import emu.grasscutter.utils.Crypto; -import static emu.grasscutter.config.Configuration.GAME_INFO; - public class PacketGetPlayerTokenRsp extends BasePacket { public PacketGetPlayerTokenRsp(GameSession session) { @@ -22,7 +20,7 @@ public PacketGetPlayerTokenRsp(GameSession session) { .setAccountType(1) .setIsProficientPlayer( session.getPlayer().getAvatars().getAvatarCount() > 0) // Not sure where this goes - .setSecretKeySeed(GAME_INFO.enableRandomEncryptSeed ? session.getEncryptSeed() : Crypto.ENCRYPT_SEED) + .setSecretKeySeed(session.getEncryptSeed()) .setSecurityCmdBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER)) .setPlatformType(3) .setChannelId(1) @@ -68,7 +66,7 @@ public PacketGetPlayerTokenRsp( .setAccountType(1) .setIsProficientPlayer( session.getPlayer().getAvatars().getAvatarCount() > 0) // Not sure where this goes - .setSecretKeySeed(GAME_INFO.enableRandomEncryptSeed ? session.getEncryptSeed() : Crypto.ENCRYPT_SEED) + .setSecretKeySeed(session.getEncryptSeed()) .setSecurityCmdBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER)) .setPlatformType(3) .setChannelId(1) diff --git a/src/main/java/emu/grasscutter/utils/algorithm/MersenneTwister64.java b/src/main/java/emu/grasscutter/utils/algorithm/MersenneTwister64.java index 8916322fa76..29ebf14198c 100644 --- a/src/main/java/emu/grasscutter/utils/algorithm/MersenneTwister64.java +++ b/src/main/java/emu/grasscutter/utils/algorithm/MersenneTwister64.java @@ -1,17 +1,17 @@ package emu.grasscutter.utils.algorithm; -public class MersenneTwister64 { +public final class MersenneTwister64 { // Period parameters private static final int N = 312; private static final int M = 156; - private static final long MATRIX_A = 0xB5026F5AA96619E9L; // private static final * constant vector a + private static final long MATRIX_A = 0xB5026F5AA96619E9L; // private static final * constant vector a private static final long UPPER_MASK = 0xFFFFFFFF80000000L; // most significant w-r bits private static final int LOWER_MASK = 0x7FFFFFFF; // least significant r bits private final long[] mt = new long[N]; // the array for the state vector - private int mti; // mti==N+1 means mt[N] is not initialized + private int mti; // mti == N+1 means mt[N] is not initialized - synchronized public void setSeed(long seed) { + public synchronized void setSeed(long seed) { mt[0] = seed; for (mti = 1; mti < N; mti++) { mt[mti] = (0x5851F42D4C957F2DL * (mt[mti - 1] ^ (mt[mti - 1] >>> 62)) + mti); @@ -23,8 +23,7 @@ public synchronized long nextLong() { long x; final long[] mag01 = {0x0L, MATRIX_A}; - if (mti >= N) // generate N words at one time - { + if (mti >= N) { // generate N words at one time if (mti == N + 1) { setSeed(5489L); } From 60ae097d47276116780c8916054cd0709d64b3c0 Mon Sep 17 00:00:00 2001 From: Simplxs Date: Tue, 12 Sep 2023 11:23:49 +0800 Subject: [PATCH 4/5] move KahnsSort to algorithms --- src/main/java/emu/grasscutter/game/world/Scene.java | 2 +- src/main/java/emu/grasscutter/utils/Crypto.java | 2 +- .../grasscutter/utils/{objects => algorithms}/KahnsSort.java | 2 +- .../utils/{algorithm => algorithms}/MersenneTwister64.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/main/java/emu/grasscutter/utils/{objects => algorithms}/KahnsSort.java (97%) rename src/main/java/emu/grasscutter/utils/{algorithm => algorithms}/MersenneTwister64.java (97%) diff --git a/src/main/java/emu/grasscutter/game/world/Scene.java b/src/main/java/emu/grasscutter/game/world/Scene.java index f9c6290316e..481bcbe8fef 100644 --- a/src/main/java/emu/grasscutter/game/world/Scene.java +++ b/src/main/java/emu/grasscutter/game/world/Scene.java @@ -39,7 +39,7 @@ import emu.grasscutter.server.event.player.PlayerTeleportEvent; import emu.grasscutter.server.packet.send.*; import emu.grasscutter.server.scheduler.ServerTaskScheduler; -import emu.grasscutter.utils.objects.KahnsSort; +import emu.grasscutter.utils.algorithms.KahnsSort; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import java.util.*; import java.util.concurrent.ConcurrentHashMap; diff --git a/src/main/java/emu/grasscutter/utils/Crypto.java b/src/main/java/emu/grasscutter/utils/Crypto.java index 685d4f2a114..03f2644ace8 100644 --- a/src/main/java/emu/grasscutter/utils/Crypto.java +++ b/src/main/java/emu/grasscutter/utils/Crypto.java @@ -2,7 +2,7 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.server.http.objects.QueryCurRegionRspJson; -import emu.grasscutter.utils.algorithm.MersenneTwister64; +import emu.grasscutter.utils.algorithms.MersenneTwister64; import java.io.ByteArrayOutputStream; import java.nio.file.Path; diff --git a/src/main/java/emu/grasscutter/utils/objects/KahnsSort.java b/src/main/java/emu/grasscutter/utils/algorithms/KahnsSort.java similarity index 97% rename from src/main/java/emu/grasscutter/utils/objects/KahnsSort.java rename to src/main/java/emu/grasscutter/utils/algorithms/KahnsSort.java index 57c22d7b00b..38dee3c5982 100644 --- a/src/main/java/emu/grasscutter/utils/objects/KahnsSort.java +++ b/src/main/java/emu/grasscutter/utils/algorithms/KahnsSort.java @@ -1,4 +1,4 @@ -package emu.grasscutter.utils.objects; +package emu.grasscutter.utils.algorithms; import java.util.*; diff --git a/src/main/java/emu/grasscutter/utils/algorithm/MersenneTwister64.java b/src/main/java/emu/grasscutter/utils/algorithms/MersenneTwister64.java similarity index 97% rename from src/main/java/emu/grasscutter/utils/algorithm/MersenneTwister64.java rename to src/main/java/emu/grasscutter/utils/algorithms/MersenneTwister64.java index 29ebf14198c..8709a2276b1 100644 --- a/src/main/java/emu/grasscutter/utils/algorithm/MersenneTwister64.java +++ b/src/main/java/emu/grasscutter/utils/algorithms/MersenneTwister64.java @@ -1,4 +1,4 @@ -package emu.grasscutter.utils.algorithm; +package emu.grasscutter.utils.algorithms; public final class MersenneTwister64 { // Period parameters From 24d0dacfec781c929e8f327a2a724dc4f8b882e3 Mon Sep 17 00:00:00 2001 From: Simplxs Date: Tue, 12 Sep 2023 11:31:30 +0800 Subject: [PATCH 5/5] rename variables --- .../packet/recv/HandlerGetPlayerTokenReq.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java index 703f39df5b8..edcc18a0079 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java @@ -111,33 +111,33 @@ public void handle(GameSession session, byte[] header, byte[] payload) throws Ex // Only >= 2.7.50 has this if (req.getKeyId() > 0) { - var encrypt_seed = session.getEncryptSeed(); + var encryptSeed = session.getEncryptSeed(); try { var cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, Crypto.CUR_SIGNING_KEY); - var client_seed_encrypted = Utils.base64Decode(req.getClientRandKey()); - var client_seed = ByteBuffer.wrap(cipher.doFinal(client_seed_encrypted)).getLong(); + var clientSeedEncrypted = Utils.base64Decode(req.getClientRandKey()); + var clientSeed = ByteBuffer.wrap(cipher.doFinal(clientSeedEncrypted)).getLong(); - var seed_bytes = - ByteBuffer.wrap(new byte[8]).putLong(encrypt_seed ^ client_seed).array(); + var seedBytes = + ByteBuffer.wrap(new byte[8]).putLong(encryptSeed ^ clientSeed).array(); cipher.init(Cipher.ENCRYPT_MODE, Crypto.EncryptionKeys.get(req.getKeyId())); - var seed_encrypted = cipher.doFinal(seed_bytes); + var seedEncrypted = cipher.doFinal(seedBytes); var privateSignature = Signature.getInstance("SHA256withRSA"); privateSignature.initSign(Crypto.CUR_SIGNING_KEY); - privateSignature.update(seed_bytes); + privateSignature.update(seedBytes); session.send( new PacketGetPlayerTokenRsp( session, - Utils.base64Encode(seed_encrypted), + Utils.base64Encode(seedEncrypted), Utils.base64Encode(privateSignature.sign()))); } catch (Exception ignored) { // Only UA Patch users will have exception var clientBytes = Utils.base64Decode(req.getClientRandKey()); - var seed = ByteHelper.longToBytes(encrypt_seed); + var seed = ByteHelper.longToBytes(encryptSeed); Crypto.xor(clientBytes, seed); var base64str = Utils.base64Encode(clientBytes);