diff --git a/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java b/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java index af7dcfdc7..9d9074da2 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java @@ -4,7 +4,6 @@ import lombok.Getter; import net.mamoe.mirai.event.MiraiEventManager; import net.mamoe.mirai.event.events.server.ServerDisableEvent; import net.mamoe.mirai.event.events.server.ServerEnableEvent; -import net.mamoe.mirai.network.RobotNetworkHandler; import net.mamoe.mirai.network.packet.login.LoginState; import net.mamoe.mirai.task.MiraiTaskManager; import net.mamoe.mirai.utils.LoggerTextFormat; @@ -36,7 +35,7 @@ public class MiraiServer { @Getter //is running under UNIX private boolean unix; - @Getter//file path + @Getter//file pathq public File parentFolder; @Getter @@ -121,8 +120,7 @@ public class MiraiServer { this.qqs.keySet().stream().map(key -> this.qqs.getSection(key)).forEach(section -> { try { Robot robot = new Robot(section); - RobotNetworkHandler robotNetworkHandler = robot.getNetworkHandler(); - robotNetworkHandler.tryLogin$mirai_core(state -> { + robot.network.tryLogin$mirai_core(state -> { if (state == LoginState.SUCCEED) { Robot.instances.add(robot); } else { diff --git a/mirai-core/src/main/java/net/mamoe/mirai/Robot.java b/mirai-core/src/main/java/net/mamoe/mirai/Robot.java index fbc066118..0c3a1c169 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/Robot.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/Robot.java @@ -5,21 +5,58 @@ import net.mamoe.mirai.contact.Group; import net.mamoe.mirai.contact.QQ; import net.mamoe.mirai.network.RobotNetworkHandler; import net.mamoe.mirai.utils.ContactList; +import net.mamoe.mirai.utils.RobotAccount; import net.mamoe.mirai.utils.config.MiraiConfigSection; +import org.jetbrains.annotations.NotNull; import java.io.Closeable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; +import java.util.*; -public class Robot implements Closeable { +/** + * Robot that is the base of the whole program. + * It contains a {@link ContactSystem}, which manage contacts such as {@link QQ} and {@link Group}. + */ +public final class Robot implements Closeable { public static final List<Robot> instances = Collections.synchronizedList(new LinkedList<>()); - private final long qqNumber; - private final String password; - @Getter - private final RobotNetworkHandler networkHandler; + public final RobotAccount account; + + public final ContactSystem contacts = new ContactSystem(); + + public final RobotNetworkHandler network; + + /** + * Robot 联系人管理. + * + * @see Robot#contacts + */ + public final class ContactSystem { + private final ContactList<Group> groups = new ContactList<>(); + private final ContactList<QQ> qqs = new ContactList<>(); + + private ContactSystem() { + + } + + public QQ getQQ(long qqNumber) { + if (!this.qqs.containsKey(qqNumber)) { + this.qqs.put(qqNumber, new QQ(Robot.this, qqNumber)); + } + return this.qqs.get(qqNumber); + } + + public Group getGroupByNumber(long groupNumber) { + if (!this.groups.containsKey(groupNumber)) { + this.groups.put(groupNumber, new Group(Robot.this, groupNumber)); + } + return groups.get(groupNumber); + } + + public Group getGroupById(long groupId) { + return getGroupByNumber(Group.Companion.groupIdToNumber(groupId)); + } + } + /** * Ref list @@ -27,57 +64,36 @@ public class Robot implements Closeable { @Getter private final List<String> owners; - private final ContactList<Group> groups = new ContactList<>(); - private final ContactList<QQ> qqs = new ContactList<>(); - - public void close() { - this.networkHandler.close(); - this.owners.clear(); - this.groups.values().forEach(Group::close); - this.groups.clear(); - this.qqs.clear(); - } - public boolean isOwnBy(String ownerName) { return owners.contains(ownerName); } - public long getQQNumber() { - return qqNumber; - } - public Robot(MiraiConfigSection<Object> data) throws Throwable { this( - data.getLongOrThrow("account", () -> new IllegalArgumentException("account")), - data.getStringOrThrow("password", () -> new IllegalArgumentException("password")), + new RobotAccount( + data.getLongOrThrow("account", () -> new IllegalArgumentException("account")), + data.getStringOrThrow("password", () -> new IllegalArgumentException("password")) + ), data.getAsOrDefault("owners", ArrayList::new) ); - } - public Robot(long qqNumber, String password, List<String> owners) { - this.qqNumber = qqNumber; - this.password = password; + public Robot(@NotNull RobotAccount account, @NotNull List<String> owners) { + Objects.requireNonNull(account); + Objects.requireNonNull(owners); + this.account = account; this.owners = Collections.unmodifiableList(owners); - this.networkHandler = new RobotNetworkHandler(this, this.qqNumber, this.password); + this.network = new RobotNetworkHandler(this); } - public QQ getQQ(long qqNumber) { - if (!this.qqs.containsKey(qqNumber)) { - this.qqs.put(qqNumber, new QQ(qqNumber)); - } - return this.qqs.get(qqNumber); + + public void close() { + this.network.close(); + this.owners.clear(); + this.contacts.groups.values().forEach(Group::close); + this.contacts.groups.clear(); + this.contacts.qqs.clear(); } - public Group getGroup(long groupNumber) { - if (!this.groups.containsKey(groupNumber)) { - this.groups.put(groupNumber, new Group(groupNumber)); - } - return groups.get(groupNumber); - } - - public Group getGroupByGroupId(long groupId) { - return getGroup(Group.Companion.groupIdToNumber(groupId)); - } } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt b/mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt index fa1a475c1..ab33c4d10 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt @@ -1,14 +1,16 @@ package net.mamoe.mirai.contact +import net.mamoe.mirai.Robot import net.mamoe.mirai.message.Message import net.mamoe.mirai.message.defaults.PlainText /** * A contact is a [QQ] or a [Group] for one particular [Robot] instance only. * + * @param robot Owner [Robot] * @author Him188moe */ -abstract class Contact(val number: Long) { +abstract class Contact(val robot: Robot, val number: Long) { /** * Async diff --git a/mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt b/mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt index 3d23d53b7..3c14af642 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt @@ -1,15 +1,16 @@ package net.mamoe.mirai.contact +import net.mamoe.mirai.Robot import net.mamoe.mirai.message.Message import net.mamoe.mirai.utils.ContactList import java.io.Closeable -class Group(number: Long) : Contact(number), Closeable { +class Group(robot: Robot, number: Long) : Contact(robot, number), Closeable { val groupId = groupNumberToId(number) val members = ContactList<QQ>() override fun sendMessage(message: Message) { - + robot.network.packetSystem.sendGroupMessage(this, message) } override fun sendXMLMessage(message: String) { diff --git a/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt b/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt index e7a0cf537..efab8f4a6 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt @@ -1,15 +1,18 @@ package net.mamoe.mirai.contact +import net.mamoe.mirai.Robot import net.mamoe.mirai.message.Message import net.mamoe.mirai.message.defaults.At /** + * A QQ instance helps you to receive message from or send message to. + * Notice that one QQ instance belong to one [Robot], that is, QQ instances from different [Robot] are NOT the same. + * * @author Him188moe */ -class QQ(number: Long) : Contact(number) { - +class QQ(robot: Robot, number: Long) : Contact(robot, number) { override fun sendMessage(message: Message) { - + robot.network.packetSystem.sendFriendMessage(this, message) } override fun sendXMLMessage(message: String) { diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt index 258aff770..f5c4bbfb3 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt @@ -28,26 +28,44 @@ interface Protocol { const val head = "02" - const val ver = "37 13 " - const val fixVer = "03 00 00 00 01 2E 01 00 00 68 52 00 00 00 00 " - const val tail = " 03" - const val _fixVer = "02 00 00 00 01 01 01 00 00 68 20 " - const val _0825data0 = "00 18 00 16 00 01 " - const val _0825data2 = "00 00 04 53 00 00 00 01 00 00 15 85 " - const val _0825key = "A4 F1 91 88 C9 82 14 99 0C 9E 56 55 91 23 C8 3D" + const val ver = "37 13" + const val fixVer = "03 00 00 00 01 2E 01 00 00 68 52 00 00 00 00" + const val tail = "03" + /** + * _fixVer + */ + const val fixVer2 = "02 00 00 00 01 01 01 00 00 68 20" + /** + * 0825data1 + */ + const val constantData0 = "00 18 00 16 00 01 " + /** + * 0825data2 + */ + const val constantData1 = "00 00 04 53 00 00 00 01 00 00 15 85 " + const val key0825 = "A4 F1 91 88 C9 82 14 99 0C 9E 56 55 91 23 C8 3D" const val redirectionKey = "A8 F2 14 5F 58 12 60 AF 07 63 97 D6 76 B2 1A 3B" const val publicKey = "02 6D 28 41 D2 A5 6F D2 FC 3E 2A 1F 03 75 DE 6E 28 8F A8 19 3E 5F 16 49 D3" const val shareKey = "1A E9 7F 7D C9 73 75 98 AC 02 E0 80 5F A9 C6 AF" - const val _0836fix = "06 A9 12 97 B7 F8 76 25 AF AF D3 EA B4 C8 BC E7 " + const val fix0836 = "06 A9 12 97 B7 F8 76 25 AF AF D3 EA B4 C8 BC E7 " - const val _00BaKey = "C1 9C B8 C8 7B 8C 81 BA 9E 9E 7A 89 E1 7A EC 94" - const val _00BaFixKey = "69 20 D1 14 74 F5 B3 93 E4 D5 02 B3 71 1A CD 2A" + const val key00BA = "C1 9C B8 C8 7B 8C 81 BA 9E 9E 7A 89 E1 7A EC 94" + const val key00BAFix = "69 20 D1 14 74 F5 B3 93 E4 D5 02 B3 71 1A CD 2A" const val encryptKey = "“BA 42 FF 01 CF B4 FF D2 12 F0 6E A7 1B 7C B3 08”" - const val _0836_622_fix2 = "00 15 00 30 00 01 01 27 9B C7 F5 00 10 65 03 FD 8B 00 00 00 00 00 00 00 00 00 00 00 00 02 90 49 55 33 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B"; - const val _0836_622_fix1 = "03 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 01 01 03 00 19"; - const val _0836key1 = "EF 4A 36 6A 16 A8 E6 3D 2E EA BD 1F 98 C1 3C DA" + /** + * 0836_622_fix2 + */ + const val passwordSubmissionKey2 = "00 15 00 30 00 01 01 27 9B C7 F5 00 10 65 03 FD 8B 00 00 00 00 00 00 00 00 00 00 00 00 02 90 49 55 33 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B"; + /** + * 0836_622_fix1 + */ + const val passwordSubmissionKey1 = "03 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 01 01 03 00 19"; + /** + * fix_0836_1 + */ + const val key0836 = "EF 4A 36 6A 16 A8 E6 3D 2E EA BD 1F 98 C1 3C DA" private val hexToByteArrayCacheMap: MutableMap<Int, ByteArray> = mutableMapOf() diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt index e62c95502..0a8fb4c67 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt @@ -2,33 +2,36 @@ package net.mamoe.mirai.network import net.mamoe.mirai.Robot import net.mamoe.mirai.contact.Group +import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.event.events.qq.FriendMessageEvent import net.mamoe.mirai.event.events.robot.RobotLoginSucceedEvent +import net.mamoe.mirai.message.Message import net.mamoe.mirai.network.packet.* import net.mamoe.mirai.network.packet.login.* -import net.mamoe.mirai.network.packet.message.ClientSendGroupMessagePacket import net.mamoe.mirai.network.packet.message.ServerSendFriendMessageResponsePacket import net.mamoe.mirai.network.packet.message.ServerSendGroupMessageResponsePacket import net.mamoe.mirai.task.MiraiThreadPool -import net.mamoe.mirai.utils.* +import net.mamoe.mirai.utils.ClientLoginStatus +import net.mamoe.mirai.utils.MiraiLogger +import net.mamoe.mirai.utils.getGTK +import net.mamoe.mirai.utils.lazyEncode import java.io.Closeable import java.net.DatagramPacket import java.net.DatagramSocket import java.net.InetSocketAddress import java.util.concurrent.TimeUnit - /** * A RobotNetworkHandler is used to connect with Tencent servers. * * @author Him188moe */ -@ExperimentalUnsignedTypes -internal class RobotNetworkHandler(val robot: Robot, val number: Long, private val password: String) : Closeable { +@Suppress("EXPERIMENTAL_API_USAGE")//to simplify code +internal class RobotNetworkHandler(private val robot: Robot) : Closeable { - var socket: DatagramSocket = DatagramSocket((15314 + Math.random() * 100).toInt()) + private var socket: DatagramSocket = DatagramSocket((15314 + Math.random() * 100).toInt()) - var serverIP: String = "" + private var serverIP: String = "" set(value) { serverAddress = InetSocketAddress(value, 8000) field = value @@ -45,7 +48,7 @@ internal class RobotNetworkHandler(val robot: Robot, val number: Long, private v private lateinit var loginIP: String private var tgtgtKey: ByteArray? = null private var tlv0105: ByteArray - private lateinit var _0828_rec_decr_key: ByteArray + private lateinit var sessionResponseDecryptionKey: ByteArray private var verificationCodeSequence: Int = 0//这两个验证码使用 private var verificationCodeCache: ByteArray? = null//每次包只发一部分验证码来 @@ -82,10 +85,6 @@ internal class RobotNetworkHandler(val robot: Robot, val number: Long, private v } } - - @ExperimentalUnsignedTypes - private var md5_32: ByteArray = getRandomKey(32) - /** * Try to login to server */ @@ -110,7 +109,7 @@ internal class RobotNetworkHandler(val robot: Robot, val number: Long, private v if (loginHook != null) { this.loginHook = loginHook } - this.sendPacket(ClientTouchPacket(this.number, this.serverIP)) + this.sendPacket(ClientTouchPacket(this.robot.account.qqNumber, this.serverIP)) } private fun restartSocket() { @@ -151,20 +150,20 @@ internal class RobotNetworkHandler(val robot: Robot, val number: Long, private v packet.decode() MiraiLogger info "Packet received: $packet" if (packet is ServerEventPacket) { - sendPacket(ClientMessageResponsePacket(this.number, packet.packetId, this.sessionKey, packet.eventIdentity)) + sendPacket(ClientMessageResponsePacket(this.robot.account.qqNumber, packet.packetId, this.sessionKey, packet.eventIdentity)) } when (packet) { is ServerTouchResponsePacket -> { if (packet.serverIP != null) {//redirection serverIP = packet.serverIP!! //connect(packet.serverIP!!) - sendPacket(ClientServerRedirectionPacket(packet.serverIP!!, number)) + sendPacket(ClientServerRedirectionPacket(packet.serverIP!!, this.robot.account.qqNumber)) } else {//password submission this.loginIP = packet.loginIP this.loginTime = packet.loginTime this.token0825 = packet.token0825 this.tgtgtKey = packet.tgtgtKey - sendPacket(ClientPasswordSubmissionPacket(this.number, this.password, packet.loginTime, packet.loginIP, packet.tgtgtKey, packet.token0825)) + sendPacket(ClientPasswordSubmissionPacket(this.robot.account.qqNumber, this.robot.account.password, packet.loginTime, packet.loginIP, packet.tgtgtKey, packet.token0825)) } } @@ -182,7 +181,7 @@ internal class RobotNetworkHandler(val robot: Robot, val number: Long, private v if (packet.unknownBoolean != null && packet.unknownBoolean!!) { this.verificationCodeSequence = 1 - sendPacket(ClientVerificationCodeTransmissionRequestPacket(1, this.number, this.token0825, this.verificationCodeSequence, this.token00BA)) + sendPacket(ClientVerificationCodeTransmissionRequestPacket(1, this.robot.account.qqNumber, this.token0825, this.verificationCodeSequence, this.token00BA)) } } @@ -190,7 +189,7 @@ internal class RobotNetworkHandler(val robot: Robot, val number: Long, private v is ServerVerificationCodeRepeatPacket -> {//todo 这个名字正确么 this.tgtgtKey = packet.tgtgtKeyUpdate this.token00BA = packet.token00BA - sendPacket(ClientLoginResendPacket3105(this.number, this.password, this.loginTime, this.loginIP, this.tgtgtKey!!, this.token0825, this.token00BA)) + sendPacket(ClientLoginResendPacket3105(this.robot.account.qqNumber, this.robot.account.password, this.loginTime, this.loginIP, this.tgtgtKey!!, this.token0825, this.token00BA)) } is ServerVerificationCodeTransmissionPacket -> { @@ -210,26 +209,26 @@ internal class RobotNetworkHandler(val robot: Robot, val number: Long, private v this.verificationCodeCache TODO("验证码好了") } else { - sendPacket(ClientVerificationCodeTransmissionRequestPacket(this.verificationCodeCacheCount, this.number, this.token0825, this.verificationCodeSequence, this.token00BA)) + sendPacket(ClientVerificationCodeTransmissionRequestPacket(this.verificationCodeCacheCount, this.robot.account.qqNumber, this.token0825, this.verificationCodeSequence, this.token00BA)) } } is ServerLoginResponseSuccessPacket -> { - this._0828_rec_decr_key = packet._0828_rec_decr_key - sendPacket(ClientSessionRequestPacket(this.number, this.serverIP, this.loginIP, this.md5_32, packet.token38, packet.token88, packet.encryptionKey, this.tlv0105)) + this.sessionResponseDecryptionKey = packet._0828_rec_decr_key + sendPacket(ClientSessionRequestPacket(this.robot.account.qqNumber, this.serverIP, packet.token38, packet.token88, packet.encryptionKey, this.tlv0105)) } //是ClientPasswordSubmissionPacket之后服务器回复的 is ServerLoginResponseResendPacket -> { - if (packet.tokenUnknown != null) { - //this.token00BA = packet.token00BA!! - //println("token00BA changed!!! to " + token00BA.toUByteArray()) - } + //if (packet.tokenUnknown != null) { + //this.token00BA = packet.token00BA!! + //println("token00BA changed!!! to " + token00BA.toUByteArray()) + //} if (packet.flag == ServerLoginResponseResendPacket.Flag.`08 36 31 03`) { this.tgtgtKey = packet.tgtgtKey sendPacket(ClientLoginResendPacket3104( - this.number, - this.password, + this.robot.account.qqNumber, + this.robot.account.password, this.loginTime, this.loginIP, this.tgtgtKey!!, @@ -242,8 +241,8 @@ internal class RobotNetworkHandler(val robot: Robot, val number: Long, private v )) } else { sendPacket(ClientLoginResendPacket3106( - this.number, - this.password, + this.robot.account.qqNumber, + this.robot.account.password, this.loginTime, this.loginIP, this.tgtgtKey!!, @@ -261,7 +260,7 @@ internal class RobotNetworkHandler(val robot: Robot, val number: Long, private v is ServerSessionKeyResponsePacket -> { this.sessionKey = packet.sessionKey MiraiThreadPool.getInstance().scheduleWithFixedDelay({ - sendPacket(ClientHeartbeatPacket(this.number, this.sessionKey)) + sendPacket(ClientHeartbeatPacket(this.robot.account.qqNumber, this.sessionKey)) }, 90000, 90000, TimeUnit.MILLISECONDS) RobotLoginSucceedEvent(robot).broadcast() @@ -270,24 +269,24 @@ internal class RobotNetworkHandler(val robot: Robot, val number: Long, private v }, 2, TimeUnit.SECONDS) this.tlv0105 = packet.tlv0105 - sendPacket(ClientLoginStatusPacket(this.number, this.sessionKey, ClientLoginStatus.ONLINE)) + sendPacket(ClientChangeOnlineStatusPacket(this.robot.account.qqNumber, this.sessionKey, ClientLoginStatus.ONLINE)) } is ServerLoginSuccessPacket -> { loginState = LoginState.SUCCEED - sendPacket(ClientSKeyRequestPacket(this.number, this.sessionKey)) + sendPacket(ClientSKeyRequestPacket(this.robot.account.qqNumber, this.sessionKey)) } is ServerSKeyResponsePacket -> { this.sKey = packet.sKey - this.cookies = "uin=o" + this.number + ";skey=" + this.sKey + ";" + this.cookies = "uin=o" + this.robot.account.qqNumber + ";skey=" + this.sKey + ";" MiraiThreadPool.getInstance().scheduleWithFixedDelay({ - sendPacket(ClientSKeyRefreshmentRequestPacket(this.number, this.sessionKey)) + sendPacket(ClientSKeyRefreshmentRequestPacket(this.robot.account.qqNumber, this.sessionKey)) }, 1800000, 1800000, TimeUnit.MILLISECONDS) this.gtk = getGTK(sKey) - sendPacket(ClientAccountInfoRequestPacket(this.number, this.sessionKey)) + sendPacket(ClientAccountInfoRequestPacket(this.robot.account.qqNumber, this.sessionKey)) } is ServerHeartbeatResponsePacket -> { @@ -304,17 +303,12 @@ internal class RobotNetworkHandler(val robot: Robot, val number: Long, private v return } - FriendMessageEvent(this.robot, this.robot.getQQ(packet.qq), packet.message) + FriendMessageEvent(this.robot, this.robot.contacts.getQQ(packet.qq), packet.message) } is ServerGroupMessageEventPacket -> { - //group message - if (packet.message == "牛逼") { - sendPacket(ClientSendGroupMessagePacket(Group.groupNumberToId(packet.groupNumber), this.number, this.sessionKey, "牛逼!")) - } - - //todo - //GroupMessageEvent(this.robot, this.robot.getGroup(packet.groupNumber), this.robot.getQQ(packet.qq), packet.message) + //todo message chain + //GroupMessageEvent(this.robot, this.robot.contacts.getGroupByNumber(packet.groupNumber), this.robot.contacts.getQQ(packet.qq), packet.message) } is UnknownServerEventPacket -> { @@ -329,17 +323,17 @@ internal class RobotNetworkHandler(val robot: Robot, val number: Long, private v } - is ServerMessageEventPacketRaw -> onPacketReceived(packet.analyze()) + is ServerEventPacket.Raw -> onPacketReceived(packet.distribute()) - is ServerVerificationCodePacketEncrypted -> onPacketReceived(packet.decrypt()) - is ServerLoginResponseVerificationCodePacketEncrypted -> onPacketReceived(packet.decrypt()) - is ServerLoginResponseResendPacketEncrypted -> onPacketReceived(packet.decrypt(this.tgtgtKey!!)) - is ServerLoginResponseSuccessPacketEncrypted -> onPacketReceived(packet.decrypt(this.tgtgtKey!!)) - is ServerSessionKeyResponsePacketEncrypted -> onPacketReceived(packet.decrypt(this._0828_rec_decr_key)) - is ServerTouchResponsePacketEncrypted -> onPacketReceived(packet.decrypt()) - is ServerSKeyResponsePacketEncrypted -> onPacketReceived(packet.decrypt(this.sessionKey)) - is ServerAccountInfoResponsePacketEncrypted -> onPacketReceived(packet.decrypt(this.sessionKey)) - is ServerMessageEventPacketRawEncoded -> onPacketReceived(packet.decrypt(this.sessionKey)) + is ServerVerificationCodePacket.Encrypted -> onPacketReceived(packet.decrypt()) + is ServerLoginResponseVerificationCodeInitPacket.Encrypted -> onPacketReceived(packet.decrypt()) + is ServerLoginResponseResendPacket.Encrypted -> onPacketReceived(packet.decrypt(this.tgtgtKey!!)) + is ServerLoginResponseSuccessPacket.Encrypted -> onPacketReceived(packet.decrypt(this.tgtgtKey!!)) + is ServerSessionKeyResponsePacket.Encrypted -> onPacketReceived(packet.decrypt(this.sessionResponseDecryptionKey)) + is ServerTouchResponsePacket.Encrypted -> onPacketReceived(packet.decrypt()) + is ServerSKeyResponsePacket.Encrypted -> onPacketReceived(packet.decrypt(this.sessionKey)) + is ServerAccountInfoResponsePacket.Encrypted -> onPacketReceived(packet.decrypt(this.sessionKey)) + is ServerEventPacket.Raw.Encrypted -> onPacketReceived(packet.decrypt(this.sessionKey)) is ServerSendFriendMessageResponsePacket, @@ -352,6 +346,21 @@ internal class RobotNetworkHandler(val robot: Robot, val number: Long, private v } + internal val packetSystem: PacketSystem = PacketSystem() + + inner class PacketSystem { + fun sendFriendMessage(qq: QQ, message: Message) { + TODO() + //sendPacket(ClientSendFriendMessagePacket(robot.account.qqNumber, qq.number, sessionKey, message)) + } + + fun sendGroupMessage(group: Group, message: Message): Unit { + TODO() + //sendPacket(ClientSendGroupMessagePacket(group.groupId, robot.account.qqNumber, sessionKey, message)) + } + + } + @ExperimentalUnsignedTypes fun sendPacket(packet: ClientPacket) { MiraiThreadPool.getInstance().submit { diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt index 90d50c89e..67d5d3113 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt @@ -1,7 +1,7 @@ package net.mamoe.mirai.network.packet import net.mamoe.mirai.network.Protocol -import net.mamoe.mirai.utils.TEACryptor +import net.mamoe.mirai.utils.TEA import java.io.DataInputStream /** @@ -18,7 +18,7 @@ class ClientAccountInfoRequestPacket( override fun encode() { this.writeRandom(2)//part of packet id this.writeQQ(qq) - this.writeHex(Protocol._fixVer) + this.writeHex(Protocol.fixVer2) this.encryptAndWrite(sessionKey) { it.writeByte(0x88) it.writeQQ(qq) @@ -27,6 +27,7 @@ class ClientAccountInfoRequestPacket( } } +@PacketId("00 5C") class ServerAccountInfoResponsePacket(input: DataInputStream) : ServerPacket(input) { //等级 //升级剩余活跃天数 @@ -34,16 +35,13 @@ class ServerAccountInfoResponsePacket(input: DataInputStream) : ServerPacket(inp override fun decode() { } -} -class ServerAccountInfoResponsePacketEncrypted(inputStream: DataInputStream) : ServerPacket(inputStream) { - override fun decode() { - - } - - fun decrypt(sessionKey: ByteArray): ServerAccountInfoResponsePacket { - this.input goto 14 - val data = this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) } - return ServerAccountInfoResponsePacket(TEACryptor.decrypt(data, sessionKey).dataInputStream()); + @PacketId("00 5C") + class Encrypted(inputStream: DataInputStream) : ServerPacket(inputStream) { + fun decrypt(sessionKey: ByteArray): ServerAccountInfoResponsePacket { + this.input goto 14 + val data = this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) } + return ServerAccountInfoResponsePacket(TEA.decrypt(data, sessionKey).dataInputStream()); + } } } \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ClientPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ClientPacket.kt index 7ea56c462..2435134d0 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ClientPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ClientPacket.kt @@ -108,15 +108,15 @@ fun DataOutputStream.writeVarInt(dec: UInt) { } fun DataOutputStream.encryptAndWrite(byteArray: ByteArray, key: ByteArray) { - this.write(TEACryptor.encrypt(byteArray, key)) + this.write(TEA.encrypt(byteArray, key)) } -fun DataOutputStream.encryptAndWrite(byteArray: ByteArray, cryptor: TEACryptor) { +fun DataOutputStream.encryptAndWrite(byteArray: ByteArray, cryptor: TEA) { this.write(cryptor.encrypt(byteArray)) } fun DataOutputStream.encryptAndWrite(key: ByteArray, encoder: (ByteArrayDataOutputStream) -> Unit) { - this.write(TEACryptor.encrypt(ByteArrayDataOutputStream().let { encoder(it); it.toByteArray() }, key)) + this.write(TEA.encrypt(ByteArrayDataOutputStream().let { encoder(it); it.toByteArray() }, key)) } @ExperimentalUnsignedTypes @@ -124,7 +124,7 @@ fun DataOutputStream.encryptAndWrite(keyHex: String, encoder: (ByteArrayDataOutp this.encryptAndWrite(keyHex.hexToBytes(), encoder) } -fun DataOutputStream.encryptAndWrite(cryptor: TEACryptor, encoder: (ByteArrayDataOutputStream) -> Unit) { +fun DataOutputStream.encryptAndWrite(cryptor: TEA, encoder: (ByteArrayDataOutputStream) -> Unit) { this.write(cryptor.encrypt(ByteArrayDataOutputStream().let { encoder(it); it.toByteArray() })) } @@ -132,24 +132,24 @@ fun DataOutputStream.encryptAndWrite(cryptor: TEACryptor, encoder: (ByteArrayDat @Throws(IOException::class) fun DataOutputStream.writeTLV0006(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray) { ByteArrayDataOutputStream().let { - it.writeHex("12 12 12 12")//it.writeRandom(4) todo + it.writeRandom(4) it.writeHex("00 02") it.writeQQ(qq) - it.writeHex(Protocol._0825data2) + it.writeHex(Protocol.constantData1) it.writeHex("00 00 01") - val md5_1 = md5(password); - val md5_2 = md5(md5_1 + "00 00 00 00".hexToBytes() + qq.toUInt().toByteArray()) - it.write(md5_1) + val firstMD5 = md5(password) + val secondMD5 = md5(firstMD5 + "00 00 00 00".hexToBytes() + qq.toUInt().toByteArray()) + it.write(firstMD5) it.writeInt(loginTime) - it.writeByte(0); + it.writeByte(0) it.writeZero(4 * 3) it.writeIP(loginIP) it.writeZero(8) it.writeHex("00 10") it.writeHex("15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B") it.write(tgtgtKey) - this.write(TEACryptor.encrypt(it.toByteArray(), md5_2)) + this.write(TEA.encrypt(it.toByteArray(), secondMD5)) } } @@ -216,7 +216,7 @@ fun Int.toLByteArray(): ByteArray = byteArrayOf( ) @ExperimentalUnsignedTypes -fun Int.toHexString(separator: String = " "): String = this.toByteArray().toUByteArray().toUHexString(separator); +fun Int.toHexString(separator: String = " "): String = this.toByteArray().toUByteArray().toUHexString(separator) internal fun md5(str: String): ByteArray = MessageDigest.getInstance("MD5").digest(str.toByteArray()) diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt index d8b1b8040..9fcd36304 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt @@ -24,8 +24,4 @@ class ClientHeartbeatPacket( } } -class ServerHeartbeatResponsePacket(input: DataInputStream) : ServerPacket(input) { - override fun decode() { - - } -} \ No newline at end of file +class ServerHeartbeatResponsePacket(input: DataInputStream) : ServerPacket(input) \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/MessageEvent.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/MessageEvent.kt deleted file mode 100644 index 001cf7571..000000000 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/MessageEvent.kt +++ /dev/null @@ -1,84 +0,0 @@ -package net.mamoe.mirai.network.packet - -import net.mamoe.mirai.network.Protocol -import net.mamoe.mirai.utils.TEACryptor -import net.mamoe.mirai.utils.toUHexString -import java.io.DataInputStream - - -/** - * 告知服务器已经收到数据 - */ -@PacketId("")//随后写入 -@ExperimentalUnsignedTypes -class ClientMessageResponsePacket( - private val qq: Long, - private val packetIdFromServer: ByteArray, - private val sessionKey: ByteArray, - private val eventIdentity: ByteArray -) : ClientPacket() { - override fun encode() { - this.write(packetIdFromServer) - this.writeQQ(qq) - this.writeHex(Protocol._fixVer) - this.encryptAndWrite(sessionKey) { - it.write(eventIdentity) - } - } -} - - -/** - * 群聊和好友消息分发 - */ -@PacketId("00 17") -class ServerMessageEventPacketRaw( - input: DataInputStream, - private val dataLength: Int, - private val packetId: ByteArray -) : ServerPacket(input) { - lateinit var type: ByteArray; - lateinit var eventIdentity: ByteArray; - - override fun decode() { - eventIdentity = this.input.readNBytes(16) - type = this.input.goto(18).readNBytes(2) - } - - fun analyze(): ServerEventPacket = when (val typeHex = type.toUHexString()) { - "00 C4" -> { - if (this.input.goto(33).readBoolean()) { - ServerAndroidOnlineEventPacket(this.input, packetId, eventIdentity) - } else { - ServerAndroidOfflineEventPacket(this.input, packetId, eventIdentity) - } - } - "00 2D" -> ServerGroupUploadFileEventPacket(this.input, packetId, eventIdentity) - - "00 52" -> ServerGroupMessageEventPacket(this.input, packetId, eventIdentity) - - "00 A6" -> ServerFriendMessageEventPacket(this.input, packetId, eventIdentity) - - //"02 10", "00 12" -> ServerUnknownEventPacket(this.input, packetId, eventIdentity) - - else -> UnknownServerEventPacket(this.input, packetId, eventIdentity) - } -} - -class UnknownServerEventPacket(input: DataInputStream, packetId: ByteArray, eventIdentity: ByteArray) : ServerEventPacket(input, packetId, eventIdentity) - -@PacketId("00 17") -class ServerMessageEventPacketRawEncoded(input: DataInputStream, val packetId: ByteArray) : ServerPacket(input) { - - - override fun decode() { - - } - - fun decrypt(sessionKey: ByteArray): ServerMessageEventPacketRaw { - this.input goto 14 - val data = this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) } - return ServerMessageEventPacketRaw(TEACryptor.decrypt(data, sessionKey).dataInputStream(), data.size, packetId); - } - -} \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt index 76b181fca..4ffb53ca3 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt @@ -1,7 +1,7 @@ package net.mamoe.mirai.network.packet import net.mamoe.mirai.network.Protocol -import net.mamoe.mirai.utils.TEACryptor +import net.mamoe.mirai.utils.TEA import java.io.DataInputStream @@ -18,7 +18,7 @@ class ClientSKeyRequestPacket( this.writeRandom(2)//part of packet id this.writeQQ(qq) - this.writeHex(Protocol._fixVer) + this.writeHex(Protocol.fixVer2) this.encryptAndWrite(sessionKey) { it.writeHex("33 00 05 00 08 74 2E 71 71 2E 63 6F 6D 00 0A 71 75 6E 2E 71 71 2E 63 6F 6D 00 0C 71 7A 6F 6E 65 2E 71 71 2E 63 6F 6D 00 0C 6A 75 62 61 6F 2E 71 71 2E 63 6F 6D 00 09 6B 65 2E 71 71 2E 63 6F 6D") } @@ -52,19 +52,13 @@ class ServerSKeyResponsePacket(input: DataInputStream) : ServerPacket(input) { override fun decode() { this.sKey = String(this.input.goto(4).readNBytes(10)) } -} -/** - * @author Him188moe - */ -class ServerSKeyResponsePacketEncrypted(inputStream: DataInputStream) : ServerPacket(inputStream) { - override fun decode() { - } - - fun decrypt(sessionKey: ByteArray): ServerSKeyResponsePacket { - this.input goto 14 - val data = this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) } - return ServerSKeyResponsePacket(TEACryptor.decrypt(data, sessionKey).dataInputStream()); + class Encrypted(inputStream: DataInputStream) : ServerPacket(inputStream) { + fun decrypt(sessionKey: ByteArray): ServerSKeyResponsePacket { + this.input goto 14 + val data = this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) } + return ServerSKeyResponsePacket(TEA.decrypt(data, sessionKey).dataInputStream()); + } } } \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt index acf94031d..ec54aeed5 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt @@ -2,6 +2,7 @@ package net.mamoe.mirai.network.packet import net.mamoe.mirai.message.defaults.MessageChain import net.mamoe.mirai.message.defaults.PlainText +import net.mamoe.mirai.network.Protocol import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.toUHexString import java.io.ByteArrayOutputStream @@ -9,15 +10,50 @@ import java.io.DataInputStream import java.util.zip.GZIPInputStream /** + * Packet id: `00 CE` or `00 17` + * * @author Him188moe */ open class ServerEventPacket(input: DataInputStream, val packetId: ByteArray, val eventIdentity: ByteArray) : ServerPacket(input) { + @PacketId("00 17") + class Raw(input: DataInputStream, private val packetId: ByteArray) : ServerPacket(input) { + @ExperimentalUnsignedTypes + fun distribute(): ServerEventPacket { + val eventIdentity = this.input.readNBytes(16) + val type = this.input.goto(18).readNBytes(2) - override fun decode() { + return when (type.toUHexString()) { + "00 C4" -> { + if (this.input.goto(33).readBoolean()) { + ServerAndroidOnlineEventPacket(this.input, packetId, eventIdentity) + } else { + ServerAndroidOfflineEventPacket(this.input, packetId, eventIdentity) + } + } + "00 2D" -> ServerGroupUploadFileEventPacket(this.input, packetId, eventIdentity) + "00 52" -> ServerGroupMessageEventPacket(this.input, packetId, eventIdentity) + + "00 A6" -> ServerFriendMessageEventPacket(this.input, packetId, eventIdentity) + + //"02 10", "00 12" -> ServerUnknownEventPacket(this.input, packetId, eventIdentity) + + else -> UnknownServerEventPacket(this.input, packetId, eventIdentity) + } + } + + @PacketId("00 17") + class Encrypted(input: DataInputStream, private val packetId: ByteArray) : ServerPacket(input) { + fun decrypt(sessionKey: ByteArray): Raw = Raw(decryptBy(sessionKey), packetId) + } } } +/** + * Unknown event + */ +class UnknownServerEventPacket(input: DataInputStream, packetId: ByteArray, eventIdentity: ByteArray) : ServerEventPacket(input, packetId, eventIdentity) + /** * Android 客户端上线 */ @@ -32,7 +68,7 @@ class ServerAndroidOfflineEventPacket(input: DataInputStream, packetId: ByteArra * 群文件上传 */ class ServerGroupUploadFileEventPacket(input: DataInputStream, packetId: ByteArray, eventIdentity: ByteArray) : ServerEventPacket(input, packetId, eventIdentity) { - lateinit var xmlMessage: String + private lateinit var xmlMessage: String override fun decode() { xmlMessage = String(this.input.goto(65).readNBytes(this.input.goto(60).readShort().toInt())) @@ -147,7 +183,6 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray var qq: Long = 0 lateinit var message: MessageChain - @ExperimentalUnsignedTypes override fun decode() { //start at Sep1.0:27 @@ -166,6 +201,30 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray } } + + +/** + * 告知服务器已经收到数据 + */ +@PacketId("")//随后写入 +@ExperimentalUnsignedTypes +class ClientMessageResponsePacket( + private val qq: Long, + private val packetIdFromServer: ByteArray,//4bytes + private val sessionKey: ByteArray, + private val eventIdentity: ByteArray +) : ClientPacket() { + override fun encode() { + this.write(packetIdFromServer)//packet id 4bytes + + this.writeQQ(qq) + this.writeHex(Protocol.fixVer2) + this.encryptAndWrite(sessionKey) { + it.write(eventIdentity) + } + } +} + /* 3E 03 3F A2 76 E4 B8 DD 00 09 7C 3F 64 5C 2A 60 1F 40 00 A6 00 00 00 2D 00 05 00 02 00 01 00 06 00 04 00 01 2E 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 02 38 03 3E 03 3F A2 76 E4 B8 DD 01 10 9D D6 12 EA BC 07 91 EF DC 29 75 67 A9 1E 00 0B 2F E4 5D 6B A8 F6 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 6B A8 F6 08 7E 90 CE 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E7 89 9B E9 80 BC 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 3E 03 3F A2 76 E4 B8 DD 00 03 5F 85 64 5C 2A A4 1F 40 00 A6 00 00 00 2D 00 05 00 02 00 01 00 06 00 04 00 01 2E 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 02 38 03 3E 03 3F A2 76 E4 B8 DD 01 10 9D D6 12 EA BC 07 91 EF DC 29 75 67 A9 1E 00 0B 2F E5 5D 6B A9 16 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 6B A9 17 1B B3 4D D7 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E7 89 9B E9 80 BC 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt index 980bf9961..cd967e486 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt @@ -3,10 +3,7 @@ package net.mamoe.mirai.network.packet import net.mamoe.mirai.network.packet.login.* import net.mamoe.mirai.network.packet.message.ServerSendFriendMessageResponsePacket import net.mamoe.mirai.network.packet.message.ServerSendGroupMessageResponsePacket -import net.mamoe.mirai.utils.MiraiLogger -import net.mamoe.mirai.utils.getAllDeclaredFields -import net.mamoe.mirai.utils.hexToBytes -import net.mamoe.mirai.utils.toUHexString +import net.mamoe.mirai.utils.* import java.io.DataInputStream /** @@ -14,7 +11,9 @@ import java.io.DataInputStream */ abstract class ServerPacket(val input: DataInputStream) : Packet { - abstract fun decode() + open fun decode() { + + } companion object { @@ -28,23 +27,22 @@ abstract class ServerPacket(val input: DataInputStream) : Packet { return when (val idHex = stream.readInt().toHexString(" ")) { - "08 25 31 01" -> ServerTouchResponsePacketEncrypted(ServerTouchResponsePacket.Type.TYPE_08_25_31_01, stream) - - "08 25 31 02" -> ServerTouchResponsePacketEncrypted(ServerTouchResponsePacket.Type.TYPE_08_25_31_02, stream) + "08 25 31 01" -> ServerTouchResponsePacket.Encrypted(ServerTouchResponsePacket.Type.TYPE_08_25_31_01, stream) + "08 25 31 02" -> ServerTouchResponsePacket.Encrypted(ServerTouchResponsePacket.Type.TYPE_08_25_31_02, stream) "08 36 31 03", "08 36 31 04", "08 36 31 05", "08 36 31 06" -> { when (bytes.size) { - 271, 207 -> return ServerLoginResponseResendPacketEncrypted(stream, when (idHex) { + 271, 207 -> return ServerLoginResponseResendPacket.Encrypted(stream, when (idHex) { "08 36 31 03" -> ServerLoginResponseResendPacket.Flag.`08 36 31 03` else -> { MiraiLogger debug ("ServerLoginResponseResendPacketEncrypted: flag=$idHex"); ServerLoginResponseResendPacket.Flag.OTHER } }) - 871 -> return ServerLoginResponseVerificationCodePacketEncrypted(stream) + 871 -> return ServerLoginResponseVerificationCodeInitPacket.Encrypted(stream) } if (bytes.size > 700) { - return ServerLoginResponseSuccessPacketEncrypted(stream) + return ServerLoginResponseSuccessPacket.Encrypted(stream) } return ServerLoginResponseFailedPacket(when (bytes.size) { @@ -63,20 +61,20 @@ abstract class ServerPacket(val input: DataInputStream) : Packet { }, stream) } - "08 28 04 34" -> ServerSessionKeyResponsePacketEncrypted(stream) + "08 28 04 34" -> ServerSessionKeyResponsePacket.Encrypted(stream) else -> when (idHex.substring(0, 5)) { "00 EC" -> ServerLoginSuccessPacket(stream) - "00 1D" -> ServerSKeyResponsePacketEncrypted(stream) - "00 5C" -> ServerAccountInfoResponsePacketEncrypted(stream) + "00 1D" -> ServerSKeyResponsePacket.Encrypted(stream) + "00 5C" -> ServerAccountInfoResponsePacket.Encrypted(stream) "00 58" -> ServerHeartbeatResponsePacket(stream) - "00 BA" -> ServerVerificationCodePacketEncrypted(stream) + "00 BA" -> ServerVerificationCodePacket.Encrypted(stream) - "00 CE", "00 17" -> ServerMessageEventPacketRawEncoded(stream, idHex.hexToBytes()) + "00 CE", "00 17" -> ServerEventPacket.Raw.Encrypted(stream, idHex.hexToBytes()) "00 81" -> UnknownServerPacket(stream) @@ -101,6 +99,16 @@ abstract class ServerPacket(val input: DataInputStream) : Packet { } } } + + fun decryptBy(key: ByteArray): DataInputStream { + input.goto(14) + return DataInputStream(TEA.decrypt(input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }, key).inputStream()) + } + + @ExperimentalUnsignedTypes + fun decryptBy(keyHex: String): DataInputStream { + return this.decryptBy(keyHex.hexToBytes()) + } } @@ -173,4 +181,6 @@ fun <N : Number> DataInputStream.readByteAt(position: N): Byte { fun <N : Number> DataInputStream.readShortAt(position: N): Short { this.goto(position) return this.readShort(); -} \ No newline at end of file +} + +fun ByteArray.cutTail(length: Int): ByteArray = this.copyOfRange(0, this.size - length) \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Session.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Session.kt index 4f55c4e88..301a2402f 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Session.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Session.kt @@ -2,7 +2,7 @@ package net.mamoe.mirai.network.packet import net.mamoe.mirai.network.Protocol import net.mamoe.mirai.utils.ByteArrayDataOutputStream -import net.mamoe.mirai.utils.TEACryptor +import net.mamoe.mirai.utils.TEA import net.mamoe.mirai.utils.getRandomKey import net.mamoe.mirai.utils.lazyEncode import java.io.DataInputStream @@ -16,8 +16,6 @@ import java.net.InetAddress class ClientSessionRequestPacket( private val qq: Long, private val serverIp: String, - private val loginIP: String, - private val md5_32: ByteArray, private val token38: ByteArray, private val token88: ByteArray, private val encryptionKey: ByteArray, @@ -28,7 +26,7 @@ class ClientSessionRequestPacket( this.writeHex("02 00 00 00 01 2E 01 00 00 68 52 00 30 00 3A") this.writeHex("00 38") this.write(token38) - this.write(TEACryptor.encrypt(object : ByteArrayDataOutputStream() { + this.write(TEA.encrypt(object : ByteArrayDataOutputStream() { override fun toByteArray(): ByteArray { this.writeHex("00 07 00 88") this.write(token88) @@ -36,10 +34,10 @@ class ClientSessionRequestPacket( this.writeIP(serverIp) this.writeHex("1F 40 00 00 00 00 00 15 00 30 00 01")//fix1 this.writeHex("01 92 A5 D2 59 00 10 54 2D CF 9B 60 BF BB EC 0D D4 81 CE 36 87 DE 35 02 AE 6D ED DC 00 10 ") - this.writeHex(Protocol._0836fix) + this.writeHex(Protocol.fix0836) this.writeHex("00 36 00 12 00 02 00 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00") - this.writeHex(Protocol._0825data0) - this.writeHex(Protocol._0825data2) + this.writeHex(Protocol.constantData0) + this.writeHex(Protocol.constantData1) this.writeQQ(qq) this.writeHex("00 00 00 00 00 1F 00 22 00 01") this.writeHex("1A 68 73 66 E4 BA 79 92 CC C2 D4 EC 14 7C 8B AF 43 B0 62 FB 65 58 A9 EB 37 55 1D 26 13 A8 E5 3D")//device ID @@ -51,7 +49,7 @@ class ClientSessionRequestPacket( //fix3 this.writeHex("00 63 3E 00 63 02 04 03 06 02 00 04 00 52 D9 00 00 00 00 A9 58 3E 6D 6D 49 AA F6 A6 D9 33 0A E7 7E 36 84 03 01 00 00 68 20 15 8B 00 00 01 02 00 00 03 00 07 DF 00 0A 00 0C 00 01 00 04 00 03 00 04 20 5C 00") - this.write(md5_32) + this.write(getRandomKey(32))//md5 32 this.writeHex("68") this.writeHex("00 00 00 00 00 2D 00 06 00 01") @@ -106,16 +104,12 @@ class ServerSessionKeyResponsePacket(inputStream: DataInputStream, private val d //tlv0105 = "01 05 00 88 00 01 01 02 00 40 02 01 03 3C 01 03 00 00" + 取文本中间(data, 取文本长度(data) - 367, 167) + “00 40 02 02 03 3C 01 03 00 00 ” + 取文本中间 (data, 取文本长度 (data) - 166, 167) } -} -class ServerSessionKeyResponsePacketEncrypted(inputStream: DataInputStream) : ServerPacket(inputStream) { - override fun decode() { - - } - - fun decrypt(_0828_rec_decr_key: ByteArray): ServerSessionKeyResponsePacket { - this.input goto 14 - val data = this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) } - return ServerSessionKeyResponsePacket(TEACryptor.decrypt(data, _0828_rec_decr_key).dataInputStream(), data.size); + class Encrypted(inputStream: DataInputStream) : ServerPacket(inputStream) { + fun decrypt(_0828_rec_decr_key: ByteArray): ServerSessionKeyResponsePacket { + this.input goto 14 + val data = this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) } + return ServerSessionKeyResponsePacket(TEA.decrypt(data, _0828_rec_decr_key).dataInputStream(), data.size); + } } } \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt index bf3624e84..6e10d37a9 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt @@ -48,24 +48,13 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp } } } -} -class ServerTouchResponsePacketEncrypted(private val type: ServerTouchResponsePacket.Type, inputStream: DataInputStream) : ServerPacket(inputStream) { - override fun decode() { - - } - - @ExperimentalUnsignedTypes - fun decrypt(): ServerTouchResponsePacket { - input.skip(7) - var bytes = input.readAllBytes(); - bytes = bytes.copyOfRange(0, bytes.size - 1); - println(bytes.toUByteArray().toUHexString()) - - return ServerTouchResponsePacket(DataInputStream(TEACryptor.decrypt(bytes, when (type) { - ServerTouchResponsePacket.Type.TYPE_08_25_31_02 -> Protocol.redirectionKey.hexToBytes() - ServerTouchResponsePacket.Type.TYPE_08_25_31_01 -> Protocol._0825key.hexToBytes() - }).inputStream())); + class Encrypted(private val type: Type, inputStream: DataInputStream) : ServerPacket(inputStream) { + @ExperimentalUnsignedTypes + fun decrypt(): ServerTouchResponsePacket = ServerTouchResponsePacket(decryptBy(when (type) { + Type.TYPE_08_25_31_02 -> Protocol.redirectionKey.hexToBytes() + Type.TYPE_08_25_31_01 -> Protocol.key0825.hexToBytes() + })) } } @@ -82,13 +71,13 @@ class ClientTouchPacket(val qq: Long, val serverIp: String) : ClientPacket() { override fun encode() { this.writeQQ(qq) this.writeHex(Protocol.fixVer) - this.writeHex(Protocol._0825key) + this.writeHex(Protocol.key0825) - this.write(TEACryptor.CRYPTOR_0825KEY.encrypt(object : ByteArrayDataOutputStream() { + this.write(TEA.CRYPTOR_0825KEY.encrypt(object : ByteArrayDataOutputStream() { @Throws(IOException::class) override fun toByteArray(): ByteArray { - this.writeHex(Protocol._0825data0) - this.writeHex(Protocol._0825data2) + this.writeHex(Protocol.constantData0) + this.writeHex(Protocol.constantData1) this.writeQQ(qq) this.writeHex("00 00 00 00 03 09 00 08 00 01") this.writeIP(serverIp); @@ -116,11 +105,11 @@ class ClientServerRedirectionPacket(private val serverIP: String, private val qq this.writeHex(Protocol.redirectionKey) - this.write(TEACryptor.encrypt(object : ByteArrayDataOutputStream() { + this.write(TEA.encrypt(object : ByteArrayDataOutputStream() { @Throws(IOException::class) override fun toByteArray(): ByteArray { - this.writeHex(Protocol._0825data0) - this.writeHex(Protocol._0825data2) + this.writeHex(Protocol.constantData0) + this.writeHex(Protocol.constantData1) this.writeQQ(qq) this.writeHex("00 01 00 00 03 09 00 0C 00 01") this.writeIP(serverIP) diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt index ba3e8d377..06e26e7b8 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt @@ -23,11 +23,11 @@ class ClientVerificationCodeTransmissionRequestPacket( this.writeByte(count)//part of packet id this.writeQQ(qq) - this.writeHex(Protocol._fixVer) - this.writeHex(Protocol._00BaKey) - this.encryptAndWrite(Protocol._00BaKey) { + this.writeHex(Protocol.fixVer2) + this.writeHex(Protocol.key00BA) + this.encryptAndWrite(Protocol.key00BA) { it.writeHex("00 02 00 00 08 04 01 E0") - it.writeHex(Protocol._0825data2) + it.writeHex(Protocol.constantData1) it.writeHex("00 00 38") it.write(token0825) it.writeHex("01 03 00 19") @@ -37,7 +37,7 @@ class ClientVerificationCodeTransmissionRequestPacket( it.writeHex("00 28") it.write(token00BA) it.writeHex("00 10") - it.writeHex(Protocol._00BaFixKey) + it.writeHex(Protocol.key00BAFix) } } } @@ -87,22 +87,19 @@ class ServerVerificationCodeRepeatPacket(input: DataInputStream) : ServerVerific } } -abstract class ServerVerificationCodePacket(input: DataInputStream) : ServerPacket(input) +abstract class ServerVerificationCodePacket(input: DataInputStream) : ServerPacket(input) { -@PacketId("00 BA") -class ServerVerificationCodePacketEncrypted(input: DataInputStream) : ServerPacket(input) { - override fun decode() { - - } - - @ExperimentalUnsignedTypes - fun decrypt(): ServerVerificationCodePacket { - this.input goto 14 - val data = TEACryptor.decrypt(this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }, Protocol._00BaKey.hexToBytes()) - return if (data.size == 95) { - ServerVerificationCodeRepeatPacket(data.dataInputStream()) - } else { - ServerVerificationCodeTransmissionPacket(data.dataInputStream(), data.size, this.input.readNBytesAt(3, 4)) + @PacketId("00 BA") + class Encrypted(input: DataInputStream) : ServerPacket(input) { + @ExperimentalUnsignedTypes + fun decrypt(): ServerVerificationCodePacket { + this.input goto 14 + val data = TEA.decrypt(this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }, Protocol.key00BA.hexToBytes()) + return if (data.size == 95) { + ServerVerificationCodeRepeatPacket(data.dataInputStream()) + } else { + ServerVerificationCodeTransmissionPacket(data.dataInputStream(), data.size, this.input.readNBytesAt(3, 4)) + } } } -} \ No newline at end of file +} diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginStatusPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientChangeOnlineStatusPacket.kt similarity index 83% rename from mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginStatusPacket.kt rename to mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientChangeOnlineStatusPacket.kt index 7c2b2eae3..2007b99bc 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginStatusPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientChangeOnlineStatusPacket.kt @@ -5,11 +5,13 @@ import net.mamoe.mirai.network.packet.* import net.mamoe.mirai.utils.ClientLoginStatus /** + * 改变在线状态: "我在线上", "隐身" 等 + * * @author Him188moe */ @ExperimentalUnsignedTypes @PacketId("00 EC") -class ClientLoginStatusPacket( +class ClientChangeOnlineStatusPacket( private val qq: Long, private val sessionKey: ByteArray, private val loginStatus: ClientLoginStatus @@ -18,7 +20,7 @@ class ClientLoginStatusPacket( override fun encode() { this.writeRandom(2)//part of packet id this.writeQQ(qq) - this.writeHex(Protocol._fixVer) + this.writeHex(Protocol.fixVer2) this.encryptAndWrite(sessionKey) { it.writeHex("01 00") it.writeByte(loginStatus.id) diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLogin.kt similarity index 91% rename from mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginPacket.kt rename to mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLogin.kt index 2330c1d30..7066ca1d8 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLogin.kt @@ -4,7 +4,7 @@ import net.mamoe.mirai.network.Protocol import net.mamoe.mirai.network.packet.* import net.mamoe.mirai.util.TestedSuccessfully import net.mamoe.mirai.utils.ByteArrayDataOutputStream -import net.mamoe.mirai.utils.TEACryptor +import net.mamoe.mirai.utils.TEA import net.mamoe.mirai.utils.hexToBytes import net.mamoe.mirai.utils.toUHexString import java.io.DataOutputStream @@ -28,10 +28,10 @@ class ClientPasswordSubmissionPacket( @ExperimentalUnsignedTypes override fun encode() { this.writeQQ(qq) - this.writeHex(Protocol._0836_622_fix1) + this.writeHex(Protocol.passwordSubmissionKey1) this.writeHex(Protocol.publicKey) this.writeHex("00 00 00 10") - this.writeHex(Protocol._0836key1) + this.writeHex(Protocol.key0836) this.encryptAndWrite(Protocol.shareKey.hexToBytes()) { it.writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825) @@ -69,12 +69,12 @@ open class ClientLoginResendPacket internal constructor( ) : ClientPacket() { override fun encode() { this.writeQQ(qq) - this.writeHex(Protocol._0836_622_fix1) + this.writeHex(Protocol.passwordSubmissionKey1) this.writeHex(Protocol.publicKey) this.writeHex("00 00 00 10") - this.writeHex(Protocol._0836key1) + this.writeHex(Protocol.key0836) - this.write(TEACryptor.encrypt(object : ByteArrayDataOutputStream() { + this.write(TEA.encrypt(object : ByteArrayDataOutputStream() { override fun toByteArray(): ByteArray { this.writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825, tlv_0006_encr) @@ -115,12 +115,12 @@ private fun DataOutputStream.writePart1(qq: Long, password: String, loginTime: I this.writeTLV0006(qq, password, loginTime, loginIP, tgtgtKey) } //fix - this.writeHex(Protocol._0836_622_fix2) + this.writeHex(Protocol.passwordSubmissionKey2) this.writeHex("00 1A")//tag this.writeHex("00 40")//length - this.write(TEACryptor.encrypt(Protocol._0836_622_fix2.hexToBytes(), tgtgtKey)) - this.writeHex(Protocol._0825data0) - this.writeHex(Protocol._0825data2) + this.write(TEA.encrypt(Protocol.passwordSubmissionKey2.hexToBytes(), tgtgtKey)) + this.writeHex(Protocol.constantData0) + this.writeHex(Protocol.constantData1) this.writeQQ(qq) this.writeZero(4) diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt index 033f993d9..2313c45b5 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt @@ -1,13 +1,9 @@ package net.mamoe.mirai.network.packet.login import net.mamoe.mirai.network.Protocol -import net.mamoe.mirai.network.packet.ServerPacket -import net.mamoe.mirai.network.packet.goto -import net.mamoe.mirai.network.packet.readNBytesAt -import net.mamoe.mirai.network.packet.readVarString +import net.mamoe.mirai.network.packet.* import net.mamoe.mirai.util.TestedSuccessfully -import net.mamoe.mirai.utils.TEACryptor -import net.mamoe.mirai.utils.hexToBytes +import net.mamoe.mirai.utils.TEA import net.mamoe.mirai.utils.toUHexString import java.io.DataInputStream @@ -117,21 +113,14 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in //this.gender = this.input.goto(packetDataLength - 32).readByteAt().toInt() } -} -class ServerLoginResponseSuccessPacketEncrypted(input: DataInputStream) : ServerPacket(input) { - override fun decode() { + class Encrypted(input: DataInputStream) : ServerPacket(input) { + @ExperimentalUnsignedTypes + fun decrypt(tgtgtKey: ByteArray): ServerLoginResponseSuccessPacket { + input goto 14 + return ServerLoginResponseSuccessPacket(TEA.decrypt(TEA.decrypt(input.readAllBytes().cutTail(1), Protocol.shareKey), tgtgtKey).dataInputStream()); + } } - @ExperimentalUnsignedTypes - fun decrypt(tgtgtKey: ByteArray): ServerLoginResponseSuccessPacket { - input goto 14 - var bytes = input.readAllBytes() - bytes = bytes.copyOfRange(0, bytes.size - 1) - println(bytes.toUByteArray().toUHexString()) - - return ServerLoginResponseSuccessPacket(DataInputStream(TEACryptor.decrypt(TEACryptor.decrypt(bytes, Protocol.shareKey.hexToBytes()), tgtgtKey).inputStream())); - //TeaDecrypt(取文本中间(data, 43, 取文本长度(data) - 45), m_0828_rec_decr_key) - } -} +} \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseResendPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseResendPacket.kt index 0303fcb6e..cfc72a965 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseResendPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseResendPacket.kt @@ -2,10 +2,8 @@ package net.mamoe.mirai.network.packet.login import net.mamoe.mirai.network.packet.PacketId import net.mamoe.mirai.network.packet.ServerPacket -import net.mamoe.mirai.network.packet.dataInputStream import net.mamoe.mirai.network.packet.goto import net.mamoe.mirai.util.TestedSuccessfully -import net.mamoe.mirai.utils.TEACryptor import java.io.DataInputStream /** @@ -43,20 +41,9 @@ class ServerLoginResponseResendPacket(input: DataInputStream, val flag: Flag) : } } } + + class Encrypted(input: DataInputStream, private val flag: Flag) : ServerPacket(input) { + @TestedSuccessfully + fun decrypt(tgtgtKey: ByteArray): ServerLoginResponseResendPacket = ServerLoginResponseResendPacket(decryptBy(tgtgtKey), flag) + } } - -class ServerLoginResponseResendPacketEncrypted(input: DataInputStream, private val flag: ServerLoginResponseResendPacket.Flag) : ServerPacket(input) { - override fun decode() { - - } - - @TestedSuccessfully - fun decrypt(tgtgtKey: ByteArray): ServerLoginResponseResendPacket { - //this.input.skip(7) - this.input goto 14 - var data: ByteArray = this.input.readAllBytes() - data = TEACryptor.CRYPTOR_SHARE_KEY.decrypt(data.let { it.copyOfRange(0, it.size - 1) }); - data = TEACryptor.decrypt(data, tgtgtKey) - return ServerLoginResponseResendPacket(data.dataInputStream(), flag) - } -} \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodeInitPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodeInitPacket.kt index 3d46f3b0f..49bab953e 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodeInitPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodeInitPacket.kt @@ -1,10 +1,11 @@ package net.mamoe.mirai.network.packet.login import net.mamoe.mirai.network.packet.ServerPacket +import net.mamoe.mirai.network.packet.cutTail import net.mamoe.mirai.network.packet.dataInputStream import net.mamoe.mirai.network.packet.goto import net.mamoe.mirai.util.TestedSuccessfully -import net.mamoe.mirai.utils.TEACryptor +import net.mamoe.mirai.utils.TEA import net.mamoe.mirai.utils.hexToUBytes import java.io.DataInputStream @@ -32,6 +33,19 @@ class ServerLoginResponseVerificationCodeInitPacket(input: DataInputStream, priv this.token00BA = this.input.goto(packetLength - 60).readNBytes(40) } + + + class Encrypted(input: DataInputStream) : ServerPacket(input) { + override fun decode() { + + } + + fun decrypt(): ServerLoginResponseVerificationCodeInitPacket { + this.input goto 14 + val data = TEA.CRYPTOR_SHARE_KEY.decrypt(this.input.readAllBytes().cutTail(1)); + return ServerLoginResponseVerificationCodeInitPacket(data.dataInputStream(), data.size) + } + } } fun main() { @@ -54,15 +68,3 @@ verify code token00ba 42 E6 18 57 D4 B1 4D AE 51 27 D5 EF A2 38 91 39 15 37 6C 5A FE 75 93 49 DB FC 57 3C 12 3F 26 D9 16 1D 83 45 8B 78 39 D8 */ - -class ServerLoginResponseVerificationCodePacketEncrypted(input: DataInputStream) : ServerPacket(input) { - override fun decode() { - - } - - fun decrypt(): ServerLoginResponseVerificationCodeInitPacket { - this.input goto 14 - val data = TEACryptor.CRYPTOR_SHARE_KEY.decrypt(this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }); - return ServerLoginResponseVerificationCodeInitPacket(data.dataInputStream(), data.size) - } -} \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginSuccessPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginSuccessPacket.kt index 2aebc04d5..4b5d092d0 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginSuccessPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginSuccessPacket.kt @@ -4,10 +4,8 @@ import net.mamoe.mirai.network.packet.ServerPacket import java.io.DataInputStream /** + * Congratulations! + * * @author Him188moe */ -class ServerLoginSuccessPacket(input: DataInputStream) : ServerPacket(input) { - override fun decode() { - - } -} \ No newline at end of file +class ServerLoginSuccessPacket(input: DataInputStream) : ServerPacket(input) \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendFriendMessagePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendFriendMessagePacket.kt index 6fa63d04d..7313a3bbb 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendFriendMessagePacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendFriendMessagePacket.kt @@ -19,7 +19,7 @@ class ClientSendFriendMessagePacket( override fun encode() { this.writeRandom(2)//part of packet id this.writeQQ(robotQQ) - this.writeHex(Protocol._fixVer) + this.writeHex(Protocol.fixVer2) this.encryptAndWrite(sessionKey) { it.writeQQ(robotQQ) @@ -58,7 +58,4 @@ class ClientSendFriendMessagePacket( } @PacketId("00 CD") -class ServerSendFriendMessageResponsePacket(input: DataInputStream) : ServerPacket(input) { - override fun decode() { - } -} \ No newline at end of file +class ServerSendFriendMessageResponsePacket(input: DataInputStream) : ServerPacket(input) \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendGroupMessagePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendGroupMessagePacket.kt index 2ef2a85cc..c16d27ae5 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendGroupMessagePacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/message/ClientSendGroupMessagePacket.kt @@ -2,7 +2,6 @@ package net.mamoe.mirai.network.packet.message import net.mamoe.mirai.network.Protocol import net.mamoe.mirai.network.packet.* -import net.mamoe.mirai.utils.lazyEncode import net.mamoe.mirai.utils.toUHexString import java.io.DataInputStream @@ -13,14 +12,14 @@ import java.io.DataInputStream @ExperimentalUnsignedTypes class ClientSendGroupMessagePacket( private val groupId: Long,//不是 number - private val qq: Long, + private val robotQQ: Long, private val sessionKey: ByteArray, private val message: String ) : ClientPacket() { override fun encode() { this.writeRandom(2)//part of packet id - this.writeQQ(qq) - this.writeHex(Protocol._fixVer) + this.writeQQ(robotQQ) + this.writeHex(Protocol.fixVer2) this.encryptAndWrite(sessionKey) { val bytes = message.toByteArray() @@ -46,24 +45,5 @@ class ClientSendGroupMessagePacket( } } -fun main() { - println(lazyEncode { - val bytes = "message".toByteArray() - it.writeByte(0x2A) - it.writeInt(580266363) - it.writeShort(19 + bytes.size) - - it.writeByte(0x01) - it.writeByte(0x01) - it.writeShort(bytes.size + 3) - it.writeByte(0x01) - it.writeShort(bytes.size) - it.write(bytes) - }.toUHexString()) -} - @PacketId("00 02") -class ServerSendGroupMessageResponsePacket(input: DataInputStream) : ServerPacket(input) { - override fun decode() { - } -} \ No newline at end of file +class ServerSendGroupMessageResponsePacket(input: DataInputStream) : ServerPacket(input) \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/utils/ClientLoginStatus.java b/mirai-core/src/main/java/net/mamoe/mirai/utils/ClientLoginStatus.java index 45e1976fd..b2864cae6 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/utils/ClientLoginStatus.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/utils/ClientLoginStatus.java @@ -4,10 +4,14 @@ package net.mamoe.mirai.utils; * @author Him188moe */ public enum ClientLoginStatus { + /** + * 我在线上 + */ ONLINE(0x0A); - // TODO: 2019/8/31 add more - public final int id;//1byte + // TODO: 2019/8/31 add more ClientLoginStatus + + public final int id;//1 ubyte ClientLoginStatus(int id) { this.id = id; diff --git a/mirai-core/src/main/java/net/mamoe/mirai/utils/RobotAccount.java b/mirai-core/src/main/java/net/mamoe/mirai/utils/RobotAccount.java new file mode 100644 index 000000000..0f2bea143 --- /dev/null +++ b/mirai-core/src/main/java/net/mamoe/mirai/utils/RobotAccount.java @@ -0,0 +1,17 @@ +package net.mamoe.mirai.utils; + +import lombok.Data; + +/** + * @author Him188moe + */ +@Data +public final class RobotAccount { + public final long qqNumber; + public final String password; + + public RobotAccount(long qqNumber, String password) { + this.qqNumber = qqNumber; + this.password = password; + } +} diff --git a/mirai-core/src/main/java/net/mamoe/mirai/utils/TEACryptor.java b/mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.java similarity index 91% rename from mirai-core/src/main/java/net/mamoe/mirai/utils/TEACryptor.java rename to mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.java index 9b6269c49..84121e2eb 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/utils/TEACryptor.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.java @@ -8,10 +8,10 @@ import java.util.Random; /** * @author iweiz https://github.com/iweizime/StepChanger/blob/master/app/src/main/java/me/iweizi/stepchanger/qq/Cryptor.java */ -public class TEACryptor { - public static final TEACryptor CRYPTOR_SHARE_KEY = new TEACryptor(Protocol.Companion.hexToBytes(Protocol.shareKey)); - public static final TEACryptor CRYPTOR_0825KEY = new TEACryptor(Protocol.Companion.hexToBytes(Protocol._0825key)); - public static final TEACryptor CRYPTOR_00BAKEY = new TEACryptor(Protocol.Companion.hexToBytes(Protocol._00BaKey)); +public class TEA { + public static final TEA CRYPTOR_SHARE_KEY = new TEA(Protocol.Companion.hexToBytes(Protocol.shareKey)); + public static final TEA CRYPTOR_0825KEY = new TEA(Protocol.Companion.hexToBytes(Protocol.key0825)); + public static final TEA CRYPTOR_00BAKEY = new TEA(Protocol.Companion.hexToBytes(Protocol.key00BA)); private static final long UINT32_MASK = 0xffffffffL; private final long[] mKey; @@ -25,7 +25,7 @@ public class TEACryptor { private boolean isFirstBlock; private boolean isRand; - public TEACryptor(byte[] key) { + public TEA(byte[] key) { mKey = new long[4]; for (int i = 0; i < 4; i++) { mKey[i] = pack(key, i * 4, 4); @@ -36,11 +36,19 @@ public class TEACryptor { } public static byte[] encrypt(byte[] source, byte[] key) { - return new TEACryptor(key).encrypt(source); + return new TEA(key).encrypt(source); + } + + public static byte[] encrypt(byte[] source, String keyHex) { + return encrypt(source, UtilsKt.hexToBytes(keyHex)); } public static byte[] decrypt(byte[] source, byte[] key) { - return new TEACryptor(key).decrypt(source); + return new TEA(key).decrypt(source); + } + + public static byte[] decrypt(byte[] source, String keyHex) { + return decrypt(source, UtilsKt.hexToBytes(keyHex)); } private static long pack(byte[] bytes, int offset, int len) {