From fc7e756f3fee2b2e6c545de4f62f0b7f47056afa Mon Sep 17 00:00:00 2001
From: Him188moe <Him188@mamoe.net>
Date: Sun, 18 Aug 2019 15:34:05 +0800
Subject: [PATCH] update

---
 .../java/net/mamoe/mirai/network/Robot.kt     | 110 ++++++------
 .../network/packet/client/ClientPacket.kt     |  43 ++++-
 .../packet/client/login/ClientLoginPacket.kt  | 158 ++++++++++++++++++
 .../login/ClientLoginResendPacket3104.kt      |  17 --
 .../ClientLoginVerificationCodePacket.kt      |  40 +++++
 .../login/ClientPasswordSubmissionPacket.kt   | 106 ------------
 .../packet/client/touch/ClientTouchPacket.kt  |   4 +-
 .../network/packet/server/ServerPacket.kt     |  39 ++---
 ....kt => ServerLoginResponseFailedPacket.kt} |   2 +-
 .../server/login/ServerLoginResponsePacket.kt |   5 +
 ....kt => ServerLoginResponseResendPacket.kt} |  14 +-
 ....md => ServerLoginResponseResendPacket.md} |  19 ++-
 .../login/ServerLoginResponseSucceedPacket.kt |  53 ++++++
 ...rverLoginResponseVerificationCodePacket.kt |  26 +++
 .../login/ServerLoginSucceedResponsePacket.kt |  15 --
 ...rverLoginVerificationCodeResponsePacket.kt |  19 ---
 .../java/net/mamoe/mirai/util/TEACryptor.java |   5 +-
 .../main/java/net/mamoe/mirai/util/Utils.kt   |   3 +
 18 files changed, 440 insertions(+), 238 deletions(-)
 create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginPacket.kt
 delete mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginResendPacket3104.kt
 create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginVerificationCodePacket.kt
 delete mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientPasswordSubmissionPacket.kt
 rename mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/{ServerLoginFailedResponsePacket.kt => ServerLoginResponseFailedPacket.kt} (91%)
 create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponsePacket.kt
 rename mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/{ServerLoginResendResponsePacket.kt => ServerLoginResponseResendPacket.kt} (63%)
 rename mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/{ServerLoginResendResponsePacket.md => ServerLoginResponseResendPacket.md} (81%)
 create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseSucceedPacket.kt
 create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseVerificationCodePacket.kt
 delete mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginSucceedResponsePacket.kt
 delete mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginVerificationCodeResponsePacket.kt

diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/Robot.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/Robot.kt
index 2840cd658..264533207 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/Robot.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/Robot.kt
@@ -11,15 +11,15 @@ import io.netty.channel.socket.nio.NioSocketChannel
 import io.netty.handler.codec.bytes.ByteArrayDecoder
 import io.netty.handler.codec.bytes.ByteArrayEncoder
 import net.mamoe.mirai.network.packet.client.ClientPacket
-import net.mamoe.mirai.network.packet.client.login.ClientPasswordSubmissionPacket
-import net.mamoe.mirai.network.packet.client.login.ClientServerRedirectionPacket
+import net.mamoe.mirai.network.packet.client.login.*
 import net.mamoe.mirai.network.packet.client.writeHex
 import net.mamoe.mirai.network.packet.server.ServerPacket
-import net.mamoe.mirai.network.packet.server.login.ServerLoginFailedResponsePacket
-import net.mamoe.mirai.network.packet.server.login.ServerLoginResendResponsePacket
-import net.mamoe.mirai.network.packet.server.login.ServerLoginSucceedResponsePacket
-import net.mamoe.mirai.network.packet.server.login.ServerLoginVerificationCodeResponsePacket
+import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseFailedPacket
+import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseResendPacket
+import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseSucceedPacket
+import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseVerificationCodePacket
 import net.mamoe.mirai.network.packet.server.touch.ServerTouchResponsePacket
+import net.mamoe.mirai.util.getRandomKey
 import net.mamoe.mirai.utils.MiraiLogger
 import java.net.DatagramPacket
 import java.net.InetSocketAddress
@@ -30,11 +30,22 @@ import java.net.InetSocketAddress
  * @author Him188moe @ Mirai Project
  */
 class Robot(val number: Int, private val password: String) {
+    private var sequence: Int = 0
+
     private var channel: Channel? = null
 
+    private lateinit var token00BA: ByteArray
+    private lateinit var token0825: ByteArray
+    private var loginTime: Int = 0
+    private lateinit var loginIP: String
+    private var tgtgtKey: ByteArray? = null
+
+    @ExperimentalUnsignedTypes
+    private var md5_32: ByteArray = getRandomKey(32)
+
 
     @ExperimentalUnsignedTypes
-    internal fun onPacketReceived(packet: ServerPacket) {
+    private fun onPacketReceived(packet: ServerPacket) {
         packet.decode()
         when (packet) {
             is ServerTouchResponsePacket -> {
@@ -45,6 +56,10 @@ class Robot(val number: Int, private val password: String) {
                             qq = number
                     ))
                 } else {//password submission
+                    this.loginIP = packet.loginIP
+                    this.loginTime = packet.loginTime
+                    this.token0825 = packet.token
+                    this.tgtgtKey = packet.tgtgtKey
                     sendPacket(ClientPasswordSubmissionPacket(
                             qq = this.number,
                             password = this.password,
@@ -56,22 +71,55 @@ class Robot(val number: Int, private val password: String) {
                 }
             }
 
-            is ServerLoginFailedResponsePacket -> {
+            is ServerLoginResponseFailedPacket -> {
                 channel = null
                 println("Login failed: " + packet.state.toString())
                 return
             }
 
-            is ServerLoginVerificationCodeResponsePacket -> {
+            is ServerLoginResponseVerificationCodePacket -> {
+                //[token00BA]可能来自这里
+                this.token00BA = packet.token00BA
+                if (packet.unknownBoolean != null && packet.unknownBoolean!!) {
+                    this.sequence = 1
+                    sendPacket(ClientLoginVerificationCodePacket(
+                            qq = this.number,
+                            token0825 = this.token0825,
+                            token00BA = this.token00BA,
+                            sequence = this.sequence
+                    ))
+                }
 
             }
 
-            is ServerLoginSucceedResponsePacket -> {
+            is ServerLoginResponseSucceedPacket -> {
 
             }
 
-            is ServerLoginResendResponsePacket -> {
-
+            //这个有可能是客户端发送验证码之后收到的回复验证码是否正确?
+            is ServerLoginResponseResendPacket -> {
+                if (packet.flag == ServerLoginResponseResendPacket.Flag.`08 36 31 03`) {
+                    this.tgtgtKey = packet.tgtgtKey
+                    sendPacket(ClientLoginResendPacket3104(
+                            tgtgtKey = packet.tgtgtKey,
+                            token00BA = packet.token,
+                            qq = this.number,
+                            password = this.password,
+                            loginIP = this.loginIP,
+                            loginTime = this.loginTime,
+                            token0825 = this.token0825
+                    ))
+                } else {
+                    sendPacket(ClientLoginResendPacket3106(
+                            tgtgtKey = packet.tgtgtKey,
+                            token00BA = packet.token,
+                            qq = this.number,
+                            password = this.password,
+                            loginIP = this.loginIP,
+                            loginTime = this.loginTime,
+                            token0825 = this.token0825
+                    ))
+                }
             }
 
             else -> throw IllegalStateException()
@@ -82,7 +130,7 @@ class Robot(val number: Int, private val password: String) {
     @ExperimentalUnsignedTypes
     private fun sendPacket(packet: ClientPacket) {
         packet.encode()
-        packet.writeHex(Protocol.tail);
+        packet.writeHex(Protocol.tail)
         channel!!.writeAndFlush(DatagramPacket(packet.toByteArray()))
     }
 
@@ -115,7 +163,7 @@ class Robot(val number: Int, private val password: String) {
                                             Reader.init()
                                             remaining
                                         }*/
-                                        this@Robot.onPacketReceived(ServerPacket.ofByteArray(bytes))
+                                        this@Robot.onPacketReceived(ServerPacket.ofByteArray(bytes, tgtgtKey))
                                     } catch (e: Exception) {
                                         MiraiLogger.catching(e)
                                     }
@@ -132,42 +180,10 @@ class Robot(val number: Int, private val password: String) {
                         }
                     })
 
-            channel = b.connect().sync().channel();
+            channel = b.connect().sync().channel()
             channel!!.closeFuture().sync()
         } finally {
             group.shutdownGracefully().sync()
         }
     }
-
-    private object Reader {
-        private var length: Int? = null
-        private lateinit var bytes: ByteArray
-
-        fun init(bytes: ByteArray) {
-            this.length = bytes.size
-            this.bytes = bytes
-        }
-
-        /**
-         * Reads bytes, combining them to create a packet, returning remaining bytes.
-         */
-        fun read(bytes: ByteArray): ByteArray? {
-            checkNotNull(this.length)
-            val needSize = length!! - this.bytes.size//How many bytes we need
-            if (needSize == bytes.size || needSize > bytes.size) {
-                this.bytes += bytes
-                return null
-            }
-
-            //We got more than we need
-            this.bytes += bytes.copyOfRange(0, needSize)
-            return bytes.copyOfRange(needSize, bytes.size - needSize)//We got remaining bytes, that is of another packet
-        }
-
-        fun isPacketAvailable() = this.length == this.bytes.size
-
-        fun toServerPacket(): ServerPacket {
-            return ServerPacket.ofByteArray(this.bytes)
-        }
-    }
 }
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.kt
index ede45f97b..f8580e48c 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.kt
@@ -4,12 +4,10 @@ import lombok.Getter
 import net.mamoe.mirai.network.Protocol
 import net.mamoe.mirai.network.packet.Packet
 import net.mamoe.mirai.network.packet.PacketId
-import net.mamoe.mirai.util.ByteArrayDataOutputStream
-import net.mamoe.mirai.util.TEACryptor
-import net.mamoe.mirai.util.hexToBytes
-import net.mamoe.mirai.util.toHexString
+import net.mamoe.mirai.util.*
 import java.io.DataOutputStream
 import java.io.IOException
+import java.net.InetAddress
 import java.security.MessageDigest
 
 /**
@@ -76,6 +74,28 @@ fun DataOutputStream.writeHex(hex: String) {
     }
 }
 
+@ExperimentalUnsignedTypes
+fun DataOutputStream.writeVarInt(dec: UInt) {
+    /*.判断开始 (n < 256)
+    返回 (取文本右边 (“0” + 取十六进制文本 (n), 2))
+    .判断 (n ≥ 256)
+    hex = 取文本右边 (“0” + 取十六进制文本 (n), 4)
+    返回 (取文本左边 (hex, 2) + “ ” + 取文本右边 (hex, 2))
+    .默认
+    返回 (“”)
+    .判断结束*/
+
+    if (dec < 256u) {
+        this.writeByte(dec.toByte().toInt())//drop other bits
+    }
+
+    if (dec > 256u) {
+        this.writeShort(dec.toShort().toInt())
+    }
+
+    throw UnsupportedOperationException()
+}
+
 @ExperimentalUnsignedTypes
 @Throws(IOException::class)
 fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray) {
@@ -100,6 +120,21 @@ fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, log
     }
 }
 
+@ExperimentalUnsignedTypes
+fun DataOutputStream.writeCRC32() {
+    getRandomKey(16).let {
+        write(it)//key
+        writeLong(getCrc32(it))//todo may be int? check that.
+    }
+}
+
+fun DataOutputStream.writeHostname() {
+    val hostName: String = InetAddress.getLocalHost().hostName.let { it.substring(0, it.length - 3) };
+    this.writeShort(hostName.length / 2);//todo check that
+    this.writeShort(hostName.length);
+    this.writeBytes(hostName)//todo 这个对吗?
+}
+
 fun Int.toByteArray(): ByteArray = byteArrayOf(//todo 检查这方法对不对, 这其实就是从 DataInputStream copy来的
         (this.ushr(24) and 0xFF).toByte(),
         (this.ushr(16) and 0xFF).toByte(),
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginPacket.kt
new file mode 100644
index 000000000..b2c0002b8
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginPacket.kt
@@ -0,0 +1,158 @@
+package net.mamoe.mirai.network.packet.client.login
+
+import net.mamoe.mirai.network.Protocol
+import net.mamoe.mirai.network.packet.PacketId
+import net.mamoe.mirai.network.packet.client.*
+import net.mamoe.mirai.util.ByteArrayDataOutputStream
+import net.mamoe.mirai.util.TEACryptor
+import net.mamoe.mirai.util.hexToBytes
+
+/**
+ * Password submission (0836_622)
+ *
+ * @author Him188moe @ Mirai Project
+ */
+@PacketId("08 36 31 03")
+@ExperimentalUnsignedTypes
+class ClientPasswordSubmissionPacket(private val qq: Int, private val password: String, private val loginTime: Int, private val loginIP: String, private val tgtgtKey: ByteArray, private val token0825: ByteArray) : ClientPacket() {
+    @ExperimentalUnsignedTypes
+    override fun encode() {
+        this.writeQQ(qq)
+        this.writeHex(Protocol._0836_622_fix1)
+        this.writeHex(Protocol.publicKey)
+        this.writeHex("00 00 00 10")
+        this.writeHex(Protocol._0836key1)
+
+        this.write(TEACryptor.encrypt(object : ByteArrayDataOutputStream() {
+            override fun toByteArray(): ByteArray {
+                writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825)
+                writePart2()
+                return super.toByteArray()
+            }
+        }.toByteArray(), Protocol.shareKey.hexToBytes()))
+    }
+}
+
+/**
+ * Dispose_0836
+ *
+ * @author Him188moe @ Mirai Project
+ */
+@PacketId("08 36 31 04")
+@ExperimentalUnsignedTypes
+class ClientLoginResendPacket3104(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray) : ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA)
+
+/**
+ * Dispose_0836
+ *
+ * @author Him188moe @ Mirai Project
+ */
+@PacketId("08 36 31 06")
+@ExperimentalUnsignedTypes
+class ClientLoginResendPacket3106(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray) : ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA)
+
+/**
+ * Dispose_0836
+ *
+ * @author Him188moe @ Mirai Project
+ */
+@ExperimentalUnsignedTypes
+open class ClientLoginResendPacket(val qq: Int, val password: String, val loginTime: Int, val loginIP: String, val tgtgtKey: ByteArray, val token0825: ByteArray, val token00BA: ByteArray) : ClientPacket() {
+    override fun encode() {
+        this.writeQQ(qq)
+        this.writeHex(Protocol._0836_622_fix1)
+        this.writeHex(Protocol.publicKey)
+        this.writeHex("00 00 00 10")
+        this.writeHex(Protocol._0836key1)
+
+        this.write(TEACryptor.encrypt(object : ByteArrayDataOutputStream() {
+            override fun toByteArray(): ByteArray {
+                writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825)
+
+                this.writeHex("01 10") //tag
+                this.writeHex("00 3C")//length
+                this.writeHex("00 01")//tag
+                this.writeHex("00 38")//length
+                this.write(token00BA)//value
+
+                writePart2()
+                return super.toByteArray()
+            }
+        }.toByteArray(), Protocol.shareKey.hexToBytes()))
+    }
+}
+
+/**
+ * @author Him188moe @ Mirai Project
+ */
+@ExperimentalUnsignedTypes
+private fun ClientPacket.writePart1(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray) {
+
+    this.writeQQ(System.currentTimeMillis().toInt())//that's correct
+    this.writeHex("01 12")//tag
+    this.writeHex("00 38")//length
+    this.write(token0825)//length
+    this.writeHex("03 0F")//tag
+    this.writeHostname()//todo 务必检查这个
+    /*易语言源码: PCName就是HostName
+    PCName = BytesToStr (Ansi转Utf8 (取主机名 ()))
+    PCName = 取文本左边 (PCName, 取文本长度 (PCName) - 3)*/
+
+    this.writeHex("00 05 00 06 00 02")
+    this.writeQQ(qq)
+    this.writeHex("00 06")//tag
+    this.writeHex("00 78")//length
+    this.writeTLV0006(qq, password, loginTime, loginIP, tgtgtKey)
+    //fix
+    this.writeHex(Protocol._0836_622_fix2)
+    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.writeQQ(qq)
+    this.writeZero(4)
+
+    this.writeHex("01 03")//tag
+    this.writeHex("00 14")//length
+
+    this.writeHex("00 01")//tag
+    this.writeHex("00 10")//length
+    this.writeHex("60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6")//key
+}
+
+@ExperimentalUnsignedTypes
+private fun ClientPacket.writePart2() {
+
+    this.writeHex("03 12")//tag
+    this.writeHex("00 05")//length
+    this.writeHex("01 00 00 00 01")//value
+
+    this.writeHex("05 08")//tag
+    this.writeHex("00 05")//length
+    this.writeHex("10 00 00 00 00")//value
+
+    this.writeHex("03 13")//tag
+    this.writeHex("00 19")//length
+    this.writeHex("01")//value
+
+    this.writeHex("01 02")//tag
+    this.writeHex("00 10")//length
+    this.writeHex("04 EA 78 D1 A4 FF CD CC 7C B8 D4 12 7D BB 03 AA")//key
+    this.writeZero(3)
+    this.writeByte(0)//maybe 00, 0F, 1F
+
+    this.writeHex("01 02")//tag
+    this.writeHex("00 62")//length
+    this.writeHex("00 01")//word?
+    this.writeHex("04 EB B7 C1 86 F9 08 96 ED 56 84 AB 50 85 2E 48")//key
+    this.writeHex("00 38")//length
+    //value
+    this.writeHex("E9 AA 2B 4D 26 4C 76 18 FE 59 D5 A9 82 6A 0C 04 B4 49 50 D7 9B B1 FE 5D 97 54 8D 82 F3 22 C2 48 B9 C9 22 69 CA 78 AD 3E 2D E9 C9 DF A8 9E 7D 8C 8D 6B DF 4C D7 34 D0 D3")
+
+    this.writeHex("00 14")//length
+    writeCRC32()
+
+}
+
+
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginResendPacket3104.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginResendPacket3104.kt
deleted file mode 100644
index e97196684..000000000
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginResendPacket3104.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package net.mamoe.mirai.network.packet.client.login
-
-import net.mamoe.mirai.network.packet.PacketId
-import net.mamoe.mirai.network.packet.client.ClientPacket
-
-/**
- * Dispose_0836
- *
- * @author Him188moe @ Mirai Project
- */
-@PacketId("08 36 31 04")
-@ExperimentalUnsignedTypes
-class ClientLoginResendPacket3104(val tgtgtKey: ByteArray, val token00BA: ByteArray) : ClientPacket() {
-    override fun encode() {
-
-    }
-}
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginVerificationCodePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginVerificationCodePacket.kt
new file mode 100644
index 000000000..dbfbbaf4b
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginVerificationCodePacket.kt
@@ -0,0 +1,40 @@
+package net.mamoe.mirai.network.packet.client.login
+
+import net.mamoe.mirai.network.Protocol
+import net.mamoe.mirai.network.packet.PacketId
+import net.mamoe.mirai.network.packet.client.ClientPacket
+import net.mamoe.mirai.network.packet.client.writeHex
+import net.mamoe.mirai.network.packet.client.writeQQ
+import net.mamoe.mirai.network.packet.client.writeVarInt
+import net.mamoe.mirai.util.ByteArrayDataOutputStream
+import net.mamoe.mirai.util.TEACryptor
+
+/**
+ * @author Him188moe @ Mirai Project
+ */
+@PacketId("00 BA 31 01")
+@ExperimentalUnsignedTypes
+class ClientLoginVerificationCodePacket(private val qq: Int, private val token0825: ByteArray, private val sequence: Int, private val token00BA: ByteArray) : ClientPacket() {
+    override fun encode() {
+        this.writeQQ(qq)
+        this.writeHex(Protocol.fixVer)
+        this.writeHex(Protocol._00BaKey)
+        this.write(TEACryptor.CRYPTOR_0825KEY.encrypt(object : ByteArrayDataOutputStream() {
+            override fun toByteArray(): ByteArray {
+                this.writeHex("00 02 00 00 08 04 01 E0")
+                this.writeHex(Protocol._0825data2)
+                this.writeHex("00 00 38")
+                this.write(token0825)
+                this.writeHex("01 03 00 19")
+                this.writeHex(Protocol.publicKey)
+                this.writeHex("13 00 05 00 00 00 00")
+                this.writeVarInt(sequence.toUInt())
+                this.writeHex("00 28")
+                this.write(token00BA)
+                this.writeHex("00 10")
+                this.writeHex(Protocol._00BaFixKey)
+                return super.toByteArray()
+            }
+        }.toByteArray()))
+    }
+}
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientPasswordSubmissionPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientPasswordSubmissionPacket.kt
deleted file mode 100644
index 4e6475b85..000000000
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientPasswordSubmissionPacket.kt
+++ /dev/null
@@ -1,106 +0,0 @@
-package net.mamoe.mirai.network.packet.client.login
-
-import net.mamoe.mirai.network.Protocol
-import net.mamoe.mirai.network.packet.PacketId
-import net.mamoe.mirai.network.packet.client.*
-import net.mamoe.mirai.util.TEACryptor
-import net.mamoe.mirai.util.getCrc32
-import net.mamoe.mirai.util.getRandomKey
-import net.mamoe.mirai.util.hexToBytes
-import java.io.IOException
-import java.net.InetAddress
-
-/**
- * Password submission (0836_622)
- *
- * @author Him188moe @ Mirai Project
- */
-@PacketId("08 36 31 03")
-@ExperimentalUnsignedTypes
-class ClientPasswordSubmissionPacket(private val qq: Int, private val password: String, private val loginTime: Int, private val loginIP: String, private val tgtgtKey: ByteArray, private val token0825: ByteArray) : ClientPacket() {
-    @ExperimentalUnsignedTypes
-    override fun encode() {
-        this.writeQQ(qq)
-        this.writeHex(Protocol._0836_622_fix1)
-        this.writeHex(Protocol.publicKey)
-        this.writeHex("00 00 00 10")
-        this.writeHex(Protocol._0836key1)
-
-        //TEA 加密
-        this.write(TEACryptor.encrypt(object : ClientPacket() {
-            @Throws(IOException::class)
-            override fun encode() {
-                val hostName: String = InetAddress.getLocalHost().hostName.let { it.substring(0, it.length - 3) };
-
-                this.writeQQ(System.currentTimeMillis().toInt())//that's correct
-                this.writeHex("01 12");//tag
-                this.writeHex("00 38");//length
-                this.write(token0825);//length
-                this.writeHex("03 0F");//tag
-                this.writeShort(hostName.length / 2);//todo check that
-                this.writeShort(hostName.length);
-                this.writeBytes(hostName)//todo 这个对吗?
-                /*易语言源码: PCName就是HostName
-                PCName = BytesToStr (Ansi转Utf8 (取主机名 ()))
-                PCName = 取文本左边 (PCName, 取文本长度 (PCName) - 3)*/
-
-                this.writeHex("00 05 00 06 00 02")
-                this.writeQQ(qq)
-                this.writeHex("00 06")//tag
-                this.writeHex("00 78")//length
-                this.writeTLV0006(qq, password, loginTime, loginIP, tgtgtKey)
-                //fix
-                this.writeHex(Protocol._0836_622_fix2)
-                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.writeQQ(qq)
-                this.writeZero(4)
-
-                this.writeHex("01 03")//tag
-                this.writeHex("00 14")//length
-
-                this.writeHex("00 01")//tag
-                this.writeHex("00 10")//length
-                this.writeHex("60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6")//key
-
-                this.writeHex("03 12")//tag
-                this.writeHex("00 05")//length
-                this.writeHex("01 00 00 00 01")//value
-
-                this.writeHex("05 08")//tag
-                this.writeHex("00 05")//length
-                this.writeHex("10 00 00 00 00")//value
-
-                this.writeHex("03 13")//tag
-                this.writeHex("00 19")//length
-                this.writeHex("01")//value
-
-                this.writeHex("01 02")//tag
-                this.writeHex("00 10")//length
-                this.writeHex("04 EA 78 D1 A4 FF CD CC 7C B8 D4 12 7D BB 03 AA")//key
-                this.writeZero(3)
-                this.writeByte(0)//maybe 00, 0F, 1F
-
-                this.writeHex("01 02")//tag
-                this.writeHex("00 62")//length
-                this.writeHex("00 01")//word?
-                this.writeHex("04 EB B7 C1 86 F9 08 96 ED 56 84 AB 50 85 2E 48")//key
-                this.writeHex("00 38")//length
-                //value
-                this.writeHex("E9 AA 2B 4D 26 4C 76 18 FE 59 D5 A9 82 6A 0C 04 B4 49 50 D7 9B B1 FE 5D 97 54 8D 82 F3 22 C2 48 B9 C9 22 69 CA 78 AD 3E 2D E9 C9 DF A8 9E 7D 8C 8D 6B DF 4C D7 34 D0 D3")
-
-                this.writeHex("00 14")//length
-
-                getRandomKey(16).let {
-                    write(it)//key
-                    writeLong(getCrc32(it))//todo may be int? check that.
-                }
-            }
-        }.encodeToByteArray(), Protocol.shareKey.hexToBytes()))
-    }
-
-
-}
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/touch/ClientTouchPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/touch/ClientTouchPacket.kt
index 7d388af07..a5169fecb 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/touch/ClientTouchPacket.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/touch/ClientTouchPacket.kt
@@ -43,8 +43,8 @@ class ClientTouchPacket : ClientPacket() {
                 this.writeHex(Protocol._0825data2)
                 this.writeQQ(qq)
                 this.writeHex("00 00 00 00 03 09 00 08 00 01")
-                this.writeIP("192.168.1.1");
-                //this.writeIP(Protocol.SERVER_IP[2]);
+                //this.writeIP("192.168.1.1");
+                this.writeIP(Protocol.SERVER_IP[2]);
                 //this.writeIP("123456789")
                 this.writeHex("00 02 00 36 00 12 00 02 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 14 00 1D 01 02 00 19")
                 this.writeHex(Protocol.publicKey)
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.kt
index 8416f3aa7..a0dd764e9 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.kt
@@ -1,10 +1,10 @@
 package net.mamoe.mirai.network.packet.server
 
 import net.mamoe.mirai.network.packet.Packet
-import net.mamoe.mirai.network.packet.server.login.ServerLoginFailedResponsePacket
-import net.mamoe.mirai.network.packet.server.login.ServerLoginResendResponsePacket
-import net.mamoe.mirai.network.packet.server.login.ServerLoginSucceedResponsePacket
-import net.mamoe.mirai.network.packet.server.login.ServerLoginVerificationCodeResponsePacket
+import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseFailedPacket
+import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseResendPacket
+import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseSucceedPacket
+import net.mamoe.mirai.network.packet.server.login.ServerLoginResponseVerificationCodePacket
 import net.mamoe.mirai.network.packet.server.touch.ServerTouchResponsePacket
 import net.mamoe.mirai.util.toHexString
 import java.io.DataInputStream
@@ -18,35 +18,36 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
 
     companion object {
 
-        fun ofByteArray(bytes: ByteArray): ServerPacket {
+        fun ofByteArray(bytes: ByteArray, tgtgtKey: ByteArray?): ServerPacket {
 
             val stream = DataInputStream(bytes.inputStream())
 
             stream.skipUntil(10)
             val idBytes = stream.readUntil(11)
 
-            return when (idBytes.joinToString("") { it.toString(16) }) {
+            return when (val flag = idBytes.joinToString("") { it.toString(16) }) {
                 "08 25 31 01" -> ServerTouchResponsePacket(ServerTouchResponsePacket.Type.TYPE_08_25_31_01, stream)
                 "08 25 31 02" -> ServerTouchResponsePacket(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 -> {
-                            ServerLoginResendResponsePacket(stream)
-                        }
-                        871 -> return ServerLoginVerificationCodeResponsePacket(stream)
+                        271, 207 -> return ServerLoginResponseResendPacket(stream, when (flag) {
+                            "08 36 31 03" -> ServerLoginResponseResendPacket.Flag.`08 36 31 03`
+                            else -> ServerLoginResponseResendPacket.Flag.OTHER
+                        })
+                        871 -> return ServerLoginResponseVerificationCodePacket(stream)
                     }
 
                     if (bytes.size > 700) {
-                        return ServerLoginSucceedResponsePacket(stream)
+                        return ServerLoginResponseSucceedPacket(stream)
                     }
 
-                    return ServerLoginFailedResponsePacket(when (bytes.size) {
-                        319 -> ServerLoginFailedResponsePacket.State.WRONG_PASSWORD
-                        135 -> ServerLoginFailedResponsePacket.State.RETYPE_PASSWORD
-                        279 -> ServerLoginFailedResponsePacket.State.BLOCKED
-                        263 -> ServerLoginFailedResponsePacket.State.UNKNOWN_QQ_NUMBER
-                        551, 487 -> ServerLoginFailedResponsePacket.State.DEVICE_LOCK
-                        359 -> ServerLoginFailedResponsePacket.State.TAKEN_BACK
+                    return ServerLoginResponseFailedPacket(when (bytes.size) {
+                        319 -> ServerLoginResponseFailedPacket.State.WRONG_PASSWORD
+                        135 -> ServerLoginResponseFailedPacket.State.RETYPE_PASSWORD
+                        279 -> ServerLoginResponseFailedPacket.State.BLOCKED
+                        263 -> ServerLoginResponseFailedPacket.State.UNKNOWN_QQ_NUMBER
+                        551, 487 -> ServerLoginResponseFailedPacket.State.DEVICE_LOCK
+                        359 -> ServerLoginResponseFailedPacket.State.TAKEN_BACK
                         else -> throw IllegalStateException()
                     }, stream)
                 }
@@ -77,7 +78,7 @@ fun DataInputStream.readUntil(byte: Byte): ByteArray {
 fun DataInputStream.readIP(): String {
     var buff = ""
     for (i in 0..3) {
-        val byte = readByte();
+        val byte = readByte()
         buff += (byte.toUByte().toString())
         if (i != 3) buff += "."
         println(byte.toHexString())
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginFailedResponsePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseFailedPacket.kt
similarity index 91%
rename from mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginFailedResponsePacket.kt
rename to mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseFailedPacket.kt
index b258b0279..7cf34dc0a 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginFailedResponsePacket.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseFailedPacket.kt
@@ -6,7 +6,7 @@ import java.io.DataInputStream
 /**
  * @author Him188moe @ Mirai Project
  */
-class ServerLoginFailedResponsePacket(val state: State, input: DataInputStream) : ServerPacket(input) {
+class ServerLoginResponseFailedPacket(val state: State, input: DataInputStream) : ServerPacket(input) {
     enum class State {
         WRONG_PASSWORD,
         // UNKNOWN,//? 要再次发送某数据包
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponsePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponsePacket.kt
new file mode 100644
index 000000000..5b8895ad8
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponsePacket.kt
@@ -0,0 +1,5 @@
+package net.mamoe.mirai.network.packet.server.login
+
+/**
+ * @author Him188moe @ Mirai Project
+ */
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResendResponsePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseResendPacket.kt
similarity index 63%
rename from mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResendResponsePacket.kt
rename to mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseResendPacket.kt
index 3764c020a..80d084dcd 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResendResponsePacket.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseResendPacket.kt
@@ -8,7 +8,7 @@ import java.io.DataInputStream
  * @author Him188moe @ Mirai Project
  */
 @PacketId("08 36 31 03")
-class ServerLoginResendResponsePacket(input: DataInputStream, private val flag: Flag) : ServerPacket(input) {
+class ServerLoginResponseResendPacket(input: DataInputStream, val flag: Flag) : ServerPacket(input) {
     enum class Flag {
         `08 36 31 03`,
         OTHER,
@@ -18,11 +18,16 @@ class ServerLoginResendResponsePacket(input: DataInputStream, private val flag:
     lateinit var token: ByteArray
     lateinit var tgtgtKey: ByteArray
 
-    override fun decode() {
-        _0836_tlv0006_encr = 取文本中间(data, 76, 359)
+    override fun decode() {//todo 检查
+        this.input.skip(8)
+        tgtgtKey = this.input.readNBytes(13)
+        this.input.skip(17)
+
+        _0836_tlv0006_encr = this.input.readNBytes(179)
         when (flag) {
             Flag.`08 36 31 03` -> {
-                token = 取文本中间(data, 460, 167)
+                this.input.skip(13)
+                token = this.input.readNBytes(83)
             }
 
             Flag.OTHER -> {
@@ -30,6 +35,5 @@ class ServerLoginResendResponsePacket(input: DataInputStream, private val flag:
                 //[this.token] will be set in [Robot]
             }
         }
-        m_tgtgtKey = 取文本中间(data, 16, 47)
     }
 }
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResendResponsePacket.md b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseResendPacket.md
similarity index 81%
rename from mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResendResponsePacket.md
rename to mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseResendPacket.md
index 99e4d7898..ac0e9f61a 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResendResponsePacket.md
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseResendPacket.md
@@ -1,7 +1,7 @@
 
 # ServerLoginResendResponsePacket
 
-## Dispose_0836
+## Dispose_0836 (RESEND)
 data = TeaDecrypt (取文本中间 (data, 43, 取文本长度 (data) - 45), #shareKey)
 data = TeaDecrypt (data, m_tgtgtKey)
 .如果真 (data ≠ “”)
@@ -98,3 +98,20 @@ pack.PutDword (crc32_data)
 调试输出 (pack.GetPacket ())
 ret = #head + “37 13 08 36 ” + seq + “ ” + g_QQ + fix1 + #publicKey + “ 00 00 00 10 ” + _0836key1 + TeaEncrypt (pack.GetPacket (), #shareKey) + #tail
 返回 (ret)
+
+
+
+
+
+## Dispose_0836 (VERIFICATION CODE)
+data = 取文本中间 (data, 43, 取文本长度 (data) - 45)
+data = TeaDecrypt (data, #shareKey)
+verifyCode_length = HexToDec (取文本中间 (data, 235, 5))
+g_verifyCode = 取文本中间 (data, 241, verifyCode_length × 3 - 1)
+m_bool = 取文本中间 (data, 245 + verifyCode_length × 3 - 1, 2) = “01”
+m_00BaToken = 取文本中间 (data, 取文本长度 (data) - 178, 119)
+.如果真 (m_bool)
+    g_sequence = 1
+    SendUdp (#head + #ver + “00 BA 31 01 ” + g_QQ + #fixVer + #_00BaKey + “ ” + TeaEncrypt (“00 02 00 00 08 04 01 E0 ” + #_0825date2 + “00 00 38 ” + m_0825token + “ 01 03 00 19 ” + #publicKey + “ 13 00 05 00 00 00 00 ” + DecToHex (g_sequence) + “ 00 28 ” + m_00BaToken + “ 00 10 ” + #_00BaFixKey, #_00BaKey) + #tail)
+.如果真结束
+返回 ()
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseSucceedPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseSucceedPacket.kt
new file mode 100644
index 000000000..c5064185e
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseSucceedPacket.kt
@@ -0,0 +1,53 @@
+package net.mamoe.mirai.network.packet.server.login
+
+import net.mamoe.mirai.network.Protocol
+import net.mamoe.mirai.network.packet.server.ServerPacket
+import net.mamoe.mirai.util.TEACryptor
+import net.mamoe.mirai.util.hexToBytes
+import net.mamoe.mirai.util.hexToShort
+import java.io.DataInputStream
+
+/**
+ * @author Him188moe @ Mirai Project
+ */
+class ServerLoginResponseSucceedPacket(input: DataInputStream, val tgtgtKey: ByteArray) : ServerPacket(input) {
+    lateinit var _0828_rec_decr_key: ByteArray
+    lateinit var nick_length: ByteArray
+    var age: Int = 0
+    var gender: Boolean = false//from 1byte
+    lateinit var nick: String
+    lateinit var clientKey: String
+
+
+    @ExperimentalUnsignedTypes
+    override fun decode() {
+        input.skip(21)
+        val data = input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }//Drop tail
+
+        val decryptedData = TEACryptor.decrypt(TEACryptor.decrypt(data, Protocol.shareKey.hexToBytes()), tgtgtKey);
+
+        DataInputStream(decryptedData.inputStream()).let {
+            //换成 readShort
+
+            it.skip(212)
+            val msgLength = when (it.readShort()) {
+                "01 07".hexToShort() -> 0
+                "00 33".hexToShort() -> 28 * 3
+                "01 10".hexToShort() -> 64 * 3
+                else -> throw IllegalStateException()
+            }
+
+            it.skip(((514 + msgLength) / 2 - 212 - 2).toLong())
+            _0828_rec_decr_key = it.readBytes(取文本中间(it, 514 + msgLength, 47))
+            nick_length = it.readByte(取文本中间(it, 1873 + msgLength, 2))
+            nick = it.readBytes(取文本中间(it, 1876 + msgLength, 3 * nick_length - 1)).toString()
+
+            age = it.readShort(取文本中间(it, 取文本长度(it) - 82, 5)).toBoolean()
+            gender = it.readByte(取文本中间(it, 取文本长度(it) - 94, 2))
+            clientKey = it.readBytes(取文本中间(it, 484 * 3 + msgLength + 1, 112 * 3 - 1))
+        }
+
+
+        //SendUdp (Construct_0828 (“04 34”, 取文本中间 (data, 76, 167), 取文本中间 (data, 568 + msg_length, 407), 取文本中间 (data, 22, 47)))
+    }
+}
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseVerificationCodePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseVerificationCodePacket.kt
new file mode 100644
index 000000000..7cc2d5067
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginResponseVerificationCodePacket.kt
@@ -0,0 +1,26 @@
+package net.mamoe.mirai.network.packet.server.login
+
+import net.mamoe.mirai.network.Protocol
+import net.mamoe.mirai.network.packet.server.ServerPacket
+import java.io.DataInputStream
+
+/**
+ * @author Him188moe @ Mirai Project
+ */
+class ServerLoginResponseVerificationCodePacket(input: DataInputStream) : ServerPacket(input) {
+    var verifyCodeLength: Int = 0
+    lateinit var verifyCode: String
+    lateinit var token00BA: ByteArray
+    var unknownBoolean: Boolean? = null
+
+
+    override fun decode() {
+        data = 取文本中间(data, 43, 取文本长度(data) - 45)
+        data = TeaDecrypt(data, Protocol.shareKey)
+
+        verifyCodeLength = HexToDec(取文本中间(data, 235, 5))
+        verifyCode = 取文本中间(data, 241, verifyCodeLength * 3 - 1)
+        unknownBoolean = 取文本中间(data, 245 + verifyCodeLength * 3 - 1, 2) == "01"
+        token00BA = 取文本中间(data, 取文本长度(data) - 178, 119)
+    }
+}
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginSucceedResponsePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginSucceedResponsePacket.kt
deleted file mode 100644
index c030e730a..000000000
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginSucceedResponsePacket.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package net.mamoe.mirai.network.packet.server.login
-
-import net.mamoe.mirai.network.packet.server.ServerPacket
-import java.io.DataInputStream
-
-/**
- * @author Him188moe @ Mirai Project
- */
-class ServerLoginSucceedResponsePacket(input: DataInputStream) : ServerPacket(input) {
-
-
-    override fun decode() {
-        TODO()
-    }
-}
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginVerificationCodeResponsePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginVerificationCodeResponsePacket.kt
deleted file mode 100644
index 803553d72..000000000
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/login/ServerLoginVerificationCodeResponsePacket.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package net.mamoe.mirai.network.packet.server.login
-
-import net.mamoe.mirai.network.packet.server.ServerPacket
-import java.io.DataInputStream
-
-/**
- * @author Him188moe @ Mirai Project
- */
-class ServerLoginVerificationCodeResponsePacket(input: DataInputStream) : ServerPacket(input) {
-    private var verifyCodeLength: Int = 0
-    private lateinit var verifyCode: String
-    private lateinit var token00BA: ByteArray
-
-
-    override fun decode() {
-
-        TODO()
-    }
-}
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/util/TEACryptor.java b/mirai-core/src/main/java/net/mamoe/mirai/util/TEACryptor.java
index a69fc0dd2..6b24973e8 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/util/TEACryptor.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/util/TEACryptor.java
@@ -10,6 +10,7 @@ import java.util.Random;
  */
 public class TEACryptor {
     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));
 
     private static final long UINT32_MASK = 0xffffffffL;
     private final long[] mKey;
@@ -33,11 +34,11 @@ public class TEACryptor {
         isFirstBlock = true;
     }
 
-    public static byte[] encrypt(byte[] key, byte[] source) {
+    public static byte[] encrypt(byte[] source, byte[] key) {
         return new TEACryptor(key).encrypt(source);
     }
 
-    public static byte[] decrypt(byte[] key, byte[] source) {
+    public static byte[] decrypt(byte[] source, byte[] key) {
         return new TEACryptor(key).decrypt(source);
     }
 
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/util/Utils.kt b/mirai-core/src/main/java/net/mamoe/mirai/util/Utils.kt
index 5b9eea91c..e92d8e9fe 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/util/Utils.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/util/Utils.kt
@@ -42,6 +42,9 @@ fun String.hexToBytes(): ByteArray = Protocol.hexToBytes(this)
 @ExperimentalUnsignedTypes
 fun String.hexToUBytes(): UByteArray = Protocol.hexToUBytes(this)
 
+@ExperimentalUnsignedTypes//todo test that
+fun String.hexToShort(): Short = hexToBytes().let { ((it[1].toInt() shl 8) + it[0]).toShort() }
+
 open class ByteArrayDataOutputStream : DataOutputStream(ByteArrayOutputStream()) {
     open fun toByteArray(): ByteArray = (out as ByteArrayOutputStream).toByteArray()
     @ExperimentalUnsignedTypes