Add Dispatch Password authentication

This commit is contained in:
AnimeGitB
2022-07-13 12:03:57 +09:30
committed by Luke H-W
parent 42e3af4e39
commit bc2c5deb48
12 changed files with 503 additions and 124 deletions

View File

@@ -1,6 +1,7 @@
package emu.grasscutter.server.packet.recv;
import static emu.grasscutter.Configuration.ACCOUNT;
import static emu.grasscutter.Configuration.GAME_OPTIONS;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.database.DatabaseHelper;
@@ -14,6 +15,14 @@ import emu.grasscutter.server.event.game.PlayerCreationEvent;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.game.GameSession.SessionState;
import emu.grasscutter.server.packet.send.PacketGetPlayerTokenRsp;
import emu.grasscutter.utils.ByteHelper;
import emu.grasscutter.utils.Crypto;
import emu.grasscutter.utils.Utils;
import javax.crypto.Cipher;
import java.nio.ByteBuffer;
import java.security.Signature;
@Opcodes(PacketOpcodes.GetPlayerTokenReq)
public class HandlerGetPlayerTokenReq extends PacketHandler {
@@ -90,8 +99,45 @@ public class HandlerGetPlayerTokenReq extends PacketHandler {
session.setUseSecretKey(true);
session.setState(SessionState.WAITING_FOR_LOGIN);
// Send packet
session.send(new PacketGetPlayerTokenRsp(session));
}
// Only >= 2.7.50 has this
if (req.getKeyId() > 0) {
if (GAME_OPTIONS.uaPatchCompatible) {
// More love for ua patch plz 😭
byte[] clientBytes = Utils.base64Decode(req.getClientSeed());
byte[] seed = ByteHelper.longToBytes(Crypto.ENCRYPT_SEED);
Crypto.xor(clientBytes, seed);
String base64str = Utils.base64Encode(clientBytes);
session.send(new PacketGetPlayerTokenRsp(session, base64str, "bm90aGluZyBoZXJl"));
return;
}
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, Crypto.CUR_SIGNING_KEY);
var client_seed_encrypted = Utils.base64Decode(req.getClientSeed());
var client_seed = ByteBuffer.wrap(cipher.doFinal(client_seed_encrypted))
.getLong();
byte[] seed_bytes = ByteBuffer.wrap(new byte[8])
.putLong(Crypto.ENCRYPT_SEED ^ client_seed)
.array();
//Kind of a hack, but whatever
cipher.init(Cipher.ENCRYPT_MODE, req.getKeyId() == 3 ? Crypto.CUR_OS_ENCRYPT_KEY : Crypto.CUR_CN_ENCRYPT_KEY);
var seed_encrypted = cipher.doFinal(seed_bytes);
Signature privateSignature = Signature.getInstance("SHA256withRSA");
privateSignature.initSign(Crypto.CUR_SIGNING_KEY);
privateSignature.update(seed_bytes);
session.send(new PacketGetPlayerTokenRsp(session, Utils.base64Encode(seed_encrypted), Utils.base64Encode(privateSignature.sign())));
}
else {
// Send packet
session.send(new PacketGetPlayerTokenRsp(session));
}
}
}

View File

@@ -10,45 +10,70 @@ import emu.grasscutter.utils.Crypto;
public class PacketGetPlayerTokenRsp extends BasePacket {
public PacketGetPlayerTokenRsp(GameSession session) {
super(PacketOpcodes.GetPlayerTokenRsp, true);
this.setUseDispatchKey(true);
public PacketGetPlayerTokenRsp(GameSession session) {
super(PacketOpcodes.GetPlayerTokenRsp, true);
GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder()
.setUid(session.getPlayer().getUid())
.setToken(session.getAccount().getToken())
.setAccountType(1)
.setIsProficientPlayer(session.getPlayer().getAvatars().getAvatarCount() > 0) // Not sure where this goes
.setSecretKeySeed(Crypto.ENCRYPT_SEED)
.setSecurityCmdBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER))
.setPlatformType(3)
.setChannelId(1)
.setCountryCode("US")
.setClientVersionRandomKey("c25-314dd05b0b5f")
.setRegPlatform(3)
.setClientIpStr(session.getAddress().getAddress().getHostAddress())
.build();
this.setData(p.toByteArray());
}
public PacketGetPlayerTokenRsp(GameSession session, int retcode, String msg, int blackEndTime) {
super(PacketOpcodes.GetPlayerTokenRsp, true);
this.setUseDispatchKey(true);
GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder()
.setUid(session.getPlayer().getUid())
.setIsProficientPlayer(session.getPlayer().getAvatars().getAvatarCount() > 0)
.setRetcode(retcode)
.setMsg(msg)
.setBlackUidEndTime(blackEndTime)
.setRegPlatform(3)
.setCountryCode("US")
.setClientIpStr(session.getAddress().getAddress().getHostAddress())
.build();
this.setData(p.toByteArray());
}
this.setUseDispatchKey(true);
GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder()
.setUid(session.getPlayer().getUid())
.setToken(session.getAccount().getToken())
.setAccountType(1)
.setIsProficientPlayer(session.getPlayer().getAvatars().getAvatarCount() > 0) // Not sure where this goes
.setSecretKeySeed(Crypto.ENCRYPT_SEED)
.setSecurityCmdBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER))
.setPlatformType(3)
.setChannelId(1)
.setCountryCode("US")
.setClientVersionRandomKey("c25-314dd05b0b5f")
.setRegPlatform(3)
.setClientIpStr(session.getAddress().getAddress().getHostAddress())
.build();
this.setData(p.toByteArray());
}
public PacketGetPlayerTokenRsp(GameSession session, int retcode, String msg, int blackEndTime) {
super(PacketOpcodes.GetPlayerTokenRsp, true);
this.setUseDispatchKey(true);
GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder()
.setUid(session.getPlayer().getUid())
.setIsProficientPlayer(session.getPlayer().getAvatars().getAvatarCount() > 0)
.setRetcode(retcode)
.setMsg(msg)
.setBlackUidEndTime(blackEndTime)
.setRegPlatform(3)
.setCountryCode("US")
.setClientIpStr(session.getAddress().getAddress().getHostAddress())
.build();
this.setData(p.toByteArray());
}
public PacketGetPlayerTokenRsp(GameSession session, String encryptedSeed, String encryptedSeedSign) {
super(PacketOpcodes.GetPlayerTokenRsp, true);
this.setUseDispatchKey(true);
GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder()
.setUid(session.getPlayer().getUid())
.setToken(session.getAccount().getToken())
.setAccountType(1)
.setIsProficientPlayer(session.getPlayer().getAvatars().getAvatarCount() > 0) // Not sure where this goes
.setSecretKeySeed(Crypto.ENCRYPT_SEED)
.setSecurityCmdBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER))
.setPlatformType(3)
.setChannelId(1)
.setCountryCode("US")
.setClientVersionRandomKey("c25-314dd05b0b5f")
.setRegPlatform(3)
.setClientIpStr(session.getAddress().getAddress().getHostAddress())
.setEncryptedSeed(encryptedSeed)
.setSeedSignature(encryptedSeedSign)
.build();
this.setData(p.toByteArray());
}
}