Updated network

This commit is contained in:
Him188moe 2019-09-13 12:51:14 +08:00
parent 96a9e6f386
commit 37fa8055b5
27 changed files with 349 additions and 401 deletions

View File

@ -185,7 +185,7 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
* Not async
*/
@Synchronized
@ExperimentalUnsignedTypes
override fun sendPacket(packet: ClientPacket) {
checkNotNull(socket) { "network closed" }
if (socket!!.isClosed) {

View File

@ -1,3 +1,5 @@
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.network
import java.net.InetAddress
@ -72,7 +74,7 @@ object Protocol {
private val hexToByteArrayCacheMap: MutableMap<Int, ByteArray> = mutableMapOf()
@ExperimentalUnsignedTypes
fun hexToBytes(hex: String): ByteArray {
hex.hashCode().let { id ->
if (hexToByteArrayCacheMap.containsKey(id)) {
@ -86,7 +88,7 @@ object Protocol {
}
}
@ExperimentalUnsignedTypes
fun hexToUBytes(hex: String): UByteArray = Arrays
.stream(hex.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray())
.map { value -> value.trim { it <= ' ' } }

View File

@ -31,7 +31,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
private var sKeyRefresherFuture: ScheduledFuture<*>? = null
@ExperimentalUnsignedTypes
override fun onPacketReceived(packet: ServerPacket) {
when (packet) {
is ServerCanAddFriendResponsePacket -> {
@ -74,12 +74,12 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
}
}
@ExperimentalUnsignedTypes
fun addFriend(qqNumber: Long, message: Supplier<String>) {
addFriend(qqNumber, lazy { message.get() })
}
@ExperimentalUnsignedTypes
@JvmSynthetic
fun addFriend(qqNumber: Long, message: Lazy<String> = lazyOf("")): CompletableFuture<AddFriendResult> {
val future = CompletableFuture<AddFriendResult>()
@ -89,12 +89,12 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
return future
}
@ExperimentalUnsignedTypes
fun requestSKey() {
session.socket.sendPacket(ClientSKeyRequestPacket(session.bot.account.qqNumber, session.sessionKey))
}
@ExperimentalUnsignedTypes
fun requestAccountInfo() {
session.socket.sendPacket(ClientAccountInfoRequestPacket(session.bot.account.qqNumber, session.sessionKey))
}
@ -111,7 +111,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
) : Closeable {
lateinit var id: ByteArray
@ExperimentalUnsignedTypes
fun onPacketReceived(packet: ServerPacket) {
if (!::id.isInitialized) {
return
@ -164,7 +164,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
) : Closeable {
lateinit var id: ByteArray
@ExperimentalUnsignedTypes
fun onPacketReceived(packet: ServerPacket) {
if (!::id.isInitialized) {
return
@ -201,7 +201,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
}
}
@ExperimentalUnsignedTypes
fun sendAddRequest() {
session.socket.sendPacket(ClientCanAddFriendPacket(session.bot.account.qqNumber, qq, session.sessionKey).also { this.id = it.packetIdLast })
}

View File

@ -16,7 +16,7 @@ interface DataPacketSocket : Closeable {
fun distributePacket(packet: ServerPacket)
@ExperimentalUnsignedTypes
fun sendPacket(packet: ClientPacket)
fun isClosed(): Boolean

View File

@ -74,7 +74,7 @@ class MessagePacketHandler(session: LoginSession) : PacketHandler(session) {
session.socket.sendPacket(ClientSendFriendMessagePacket(session.bot.account.qqNumber, qq.number, session.sessionKey, message))
}
fun sendGroupMessage(group: Group, message: Message): Unit {
fun sendGroupMessage(group: Group, message: Message) {
TODO()
//sendPacket(ClientSendGroupMessagePacket(group.groupId, bot.account.qqNumber, sessionKey, message))
}

View File

@ -1,3 +1,5 @@
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package net.mamoe.mirai.network.packet
import lombok.Getter
@ -12,12 +14,12 @@ import java.security.MessageDigest
/**
* @author Him188moe
*/
@ExperimentalUnsignedTypes
abstract class ClientPacket : ByteArrayDataOutputStream(), Packet {
@Getter
val idHex: String
var encoded: Boolean = false
private var encoded: Boolean = false
init {
val annotation = this.javaClass.getAnnotation(PacketId::class.java)
@ -84,7 +86,6 @@ abstract class ClientPacket : ByteArrayDataOutputStream(), Packet {
}
@ExperimentalUnsignedTypes
@Throws(IOException::class)
fun DataOutputStream.writeIP(ip: String) {
for (s in ip.trim().split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
@ -97,10 +98,9 @@ fun DataOutputStream.writeTime() {
this.writeInt(System.currentTimeMillis().toInt())
}
@ExperimentalUnsignedTypes
@Throws(IOException::class)
fun DataOutputStream.writeHex(hex: String) {
for (s in hex.trim().split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
fun DataOutputStream.writeHex(uHex: String) {
for (s in uHex.trim().split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
if (s.isEmpty()) {
continue
}
@ -116,12 +116,10 @@ fun DataOutputStream.encryptAndWrite(key: ByteArray, encoder: (ByteArrayDataOutp
this.write(TEA.encrypt(ByteArrayDataOutputStream().also(encoder).toByteArray(), key))
}
@ExperimentalUnsignedTypes
fun DataOutputStream.encryptAndWrite(keyHex: String, encoder: (ByteArrayDataOutputStream) -> Unit) {
this.encryptAndWrite(keyHex.hexToBytes(), encoder)
}
@ExperimentalUnsignedTypes
@Throws(IOException::class)
fun DataOutputStream.writeTLV0006(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray) {
ByteArrayDataOutputStream().let {
@ -146,12 +144,10 @@ fun DataOutputStream.writeTLV0006(qq: Long, password: String, loginTime: Int, lo
}
}
@ExperimentalUnsignedTypes
@TestedSuccessfully
@Tested
fun DataOutputStream.writeCRC32() = writeCRC32(getRandomByteArray(16))
@ExperimentalUnsignedTypes
fun DataOutputStream.writeCRC32(key: ByteArray) {
key.let {
write(it)//key
@ -159,8 +155,8 @@ fun DataOutputStream.writeCRC32(key: ByteArray) {
}
}
@ExperimentalUnsignedTypes
@TestedSuccessfully
@Tested
fun DataOutputStream.writeDeviceName(random: Boolean = false) {
val deviceName: String = if (random) {
String(getRandomByteArray(10))
@ -185,7 +181,7 @@ fun Int.toByteArray(): ByteArray = byteArrayOf(
/**
* 255u -> 00 00 00 FF
*/
@ExperimentalUnsignedTypes
fun UInt.toByteArray(): ByteArray = byteArrayOf(
(this.shr(24) and 255u).toByte(),
(this.shr(16) and 255u).toByte(),
@ -193,24 +189,14 @@ fun UInt.toByteArray(): ByteArray = byteArrayOf(
(this.shr(0) and 255u).toByte()
)
/**
* 255 -> FF 00 00 00
*/
fun Int.toLByteArray(): ByteArray = byteArrayOf(
(this.ushr(0) and 0xFF).toByte(),
(this.ushr(8) and 0xFF).toByte(),
(this.ushr(16) and 0xFF).toByte(),
(this.ushr(24) and 0xFF).toByte()
)
@ExperimentalUnsignedTypes
fun Int.toUHexString(separator: String = " "): String = this.toByteArray().toUHexString(separator)
internal fun md5(str: String): ByteArray = MessageDigest.getInstance("MD5").digest(str.toByteArray())
internal fun md5(byteArray: ByteArray): ByteArray = MessageDigest.getInstance("MD5").digest(byteArray)
@ExperimentalUnsignedTypes
@Throws(IOException::class)
fun DataOutputStream.writeZero(count: Int) {
repeat(count) {
@ -225,13 +211,13 @@ fun DataOutputStream.writeRandom(length: Int) {
}
}
@ExperimentalUnsignedTypes
@Throws(IOException::class)
fun DataOutputStream.writeQQ(qq: Long) {
this.write(qq.toUInt().toByteArray())
}
@ExperimentalUnsignedTypes
@Throws(IOException::class)
fun DataOutputStream.writeGroup(groupIdOrGroupNumber: Long) {
this.write(groupIdOrGroupNumber.toUInt().toByteArray())

View File

@ -9,7 +9,7 @@ import java.io.DataInputStream
*
* @author Him188moe
*/
@ExperimentalUnsignedTypes
@PacketId("00 5C")
class ClientAccountInfoRequestPacket(
private val qq: Long,

View File

@ -7,7 +7,7 @@ import java.io.IOException
/**
* @author Him188moe
*/
@ExperimentalUnsignedTypes
@PacketId("00 58")
class ClientHeartbeatPacket(
private val qq: Long,

View File

@ -10,7 +10,7 @@ import java.io.DataInputStream
*
* @author Him188moe
*/
@ExperimentalUnsignedTypes
@PacketId("00 1D")
class ClientSKeyRequestPacket(
private val qq: Long,
@ -31,7 +31,7 @@ class ClientSKeyRequestPacket(
* @author Him188moe
*/
@PacketId("00 1D")
@ExperimentalUnsignedTypes
class ClientSKeyRefreshmentRequestPacket(
private val qq: Long,
private val sessionKey: ByteArray

View File

@ -1,3 +1,5 @@
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.network.packet
import net.mamoe.mirai.message.FaceID
@ -22,7 +24,7 @@ import java.util.zip.GZIPInputStream
abstract 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)
@ -80,6 +82,7 @@ class ServerGroupUploadFileEventPacket(input: DataInputStream, packetId: ByteArr
}//todo test
}
@Suppress("EXPERIMENTAL_API_USAGE")
class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray, eventIdentity: ByteArray) : ServerEventPacket(input, packetId, eventIdentity) {
var groupNumber: Long = 0
var qq: Long = 0
@ -100,16 +103,16 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray,
OTHER,
}
@ExperimentalUnsignedTypes
override fun decode() {
groupNumber = this.input.goto(51).readInt().toLong()
qq = this.input.goto(56).readLong().toUInt().toLong()
qq = this.input.goto(56).readLong()
val fontLength = this.input.goto(108).readShort()
//println(this.input.goto(110 + fontLength).readNBytesAt(2).toUHexString())//always 00 00
messageType = when (val id = this.input.goto(110 + fontLength + 2).readByte().toInt()) {
0x13 -> MessageType.NORMAL
0xE -> MessageType.XML
0x0E -> MessageType.XML
0x06 -> MessageType.AT
@ -188,7 +191,7 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
var qq: Long = 0
lateinit var message: MessageChain
@ExperimentalUnsignedTypes
override fun decode() {
input.goto(0)
println()
@ -291,7 +294,7 @@ B1 89 BE 09 8F 00 1A E5 00 0B 03 A2 09 90 BB 7A 1F 40 00 A6 00 00 00 20 00 05 00
* 告知服务器已经收到数据
*/
@PacketId("")//随后写入
@ExperimentalUnsignedTypes
class ClientMessageResponsePacket(
private val qq: Long,
private val packetIdFromServer: ByteArray,//4bytes
@ -329,7 +332,7 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
lateinit var message: String
@ExperimentalUnsignedTypes
override fun decode() {
//start at Sep1.0:27
qq = input.readIntAt(0)

View File

@ -2,7 +2,6 @@ package net.mamoe.mirai.network.packet
import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.utils.TEA
import net.mamoe.mirai.utils.getRandomByteArray
import net.mamoe.mirai.utils.lazyEncode
import java.io.DataInputStream
import java.net.InetAddress
@ -10,7 +9,7 @@ import java.net.InetAddress
/**
* @author Him188moe
*/
@ExperimentalUnsignedTypes
@PacketId("08 28 04 34")
class ClientSessionRequestPacket(
private val qq: Long,
@ -48,12 +47,12 @@ class ClientSessionRequestPacket(
it.writeHex("01 0B 00 85 00 02")
it.writeHex("B9 ED EF D7 CD E5 47 96 7A B5 28 34 CA 93 6B 5C")//fix2
it.write(getRandomByteArray(1))
it.writeRandom(1)
it.writeHex("10 00 00 00 00 00 00 00 02")
//fix3
it.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")
it.write(getRandomByteArray(32))//md5 32
it.writeRandom(32)//md5 32
it.writeHex("68")
it.writeHex("00 00 00 00 00 2D 00 06 00 01")
@ -70,7 +69,7 @@ class ServerSessionKeyResponsePacket(inputStream: DataInputStream, private val d
lateinit var sessionKey: ByteArray
lateinit var tlv0105: ByteArray
@ExperimentalUnsignedTypes
override fun decode() {
when (dataLength) {
407 -> {

View File

@ -1,6 +1,7 @@
package net.mamoe.mirai.network.packet
import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.login.ClientPasswordSubmissionPacket
import net.mamoe.mirai.utils.ByteArrayDataOutputStream
import net.mamoe.mirai.utils.TEA
import net.mamoe.mirai.utils.hexToBytes
@ -11,11 +12,12 @@ import java.io.IOException
/**
* A packet received when logging in, used to redirect server address
*
* @see net.mamoe.mirai.network.packet.client.login.ClientServerRedirectionPacket
* @see net.mamoe.mirai.network.packet.client.login.ClientPasswordSubmissionPacket
* @see ClientServerRedirectionPacket
* @see ClientPasswordSubmissionPacket
*
* @author Him188moe
*/
@Suppress("EXPERIMENTAL_API_USAGE")
@PacketId("08 25 31 01")
class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inputStream) {
var serverIP: String? = null
@ -29,9 +31,9 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
TYPE_08_25_31_02,
}
@ExperimentalUnsignedTypes
override fun decode() {
when (val id = input.readByte().toUByte().toInt()) {
when (val id = input.readByte().toInt()) {
0xFE -> {
input.skip(94)
serverIP = input.readIP()
@ -52,7 +54,7 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
}
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()
@ -65,10 +67,10 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
*
* @author Him188moe
*/
@ExperimentalUnsignedTypes
@PacketId("08 25 31 01")
class ClientTouchPacket(private val qq: Long, private val serverIp: String) : ClientPacket() {
@ExperimentalUnsignedTypes
@Throws(IOException::class)
override fun encode() {
this.writeQQ(qq)
@ -80,7 +82,7 @@ class ClientTouchPacket(private val qq: Long, private val serverIp: String) : Cl
it.writeHex(Protocol.constantData2)
it.writeQQ(qq)
it.writeHex("00 00 00 00 03 09 00 08 00 01")
it.writeIP(serverIp);
it.writeIP(serverIp)
it.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")
it.writeHex(Protocol.publicKey)
}
@ -92,10 +94,10 @@ class ClientTouchPacket(private val qq: Long, private val serverIp: String) : Cl
*
* @author Him188moe
*/
@ExperimentalUnsignedTypes
@PacketId("08 25 31 02")
class ClientServerRedirectionPacket(private val serverIP: String, private val qq: Long) : ClientPacket() {
@ExperimentalUnsignedTypes
override fun encode() {
this.writeQQ(qq)
this.writeHex(Protocol.fixVer)

View File

@ -2,14 +2,14 @@ package net.mamoe.mirai.network.packet
import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.utils.TEA
import net.mamoe.mirai.utils.TestedSuccessfully
import net.mamoe.mirai.utils.Tested
import net.mamoe.mirai.utils.hexToBytes
import java.io.DataInputStream
/**
* 客户端请求验证码图片数据的第几部分
*/
@ExperimentalUnsignedTypes
@PacketId("00 BA 31")
class ClientVerificationCodeTransmissionRequestPacket(
private val packetId: Int,
@ -18,7 +18,7 @@ class ClientVerificationCodeTransmissionRequestPacket(
private val verificationSequence: Int,
private val token00BA: ByteArray
) : ClientPacket() {
@TestedSuccessfully
@Tested
override fun encode() {
this.writeByte(packetId)//part of packet id
@ -46,7 +46,7 @@ class ClientVerificationCodeTransmissionRequestPacket(
* 提交验证码
*/
@PacketId("00 BA 32")
@ExperimentalUnsignedTypes
class ClientVerificationCodeSubmitPacket(
private val packetIdLast: Int,
private val qq: Long,
@ -93,7 +93,7 @@ class ClientVerificationCodeSubmitPacket(
* 刷新验证码
*/
@PacketId("00 BA 31")
@ExperimentalUnsignedTypes
class ClientVerificationCodeRefreshPacket(
private val packetIdLast: Int,
private val qq: Long,
@ -142,7 +142,7 @@ open class ServerVerificationCodeTransmissionPacket(input: DataInputStream, priv
lateinit var token00BA: ByteArray//40 bytes
var packetIdLast: Int = 0
@ExperimentalUnsignedTypes
override fun decode() {
this.verificationToken = this.input.readNBytesAt(10, 56)
@ -181,7 +181,7 @@ class ServerVerificationCodeCorrectPacket(input: DataInputStream) : ServerVerifi
lateinit var token00BA: ByteArray//56 bytes
@ExperimentalUnsignedTypes
override fun decode() {
token00BA = this.input.readNBytesAt(10, 56)
}
@ -191,7 +191,7 @@ abstract class ServerVerificationCodePacket(input: DataInputStream) : ServerPack
@PacketId("00 BA")
class Encrypted(input: DataInputStream, private val id: String) : ServerPacket(input) {
@ExperimentalUnsignedTypes
fun decrypt(): ServerVerificationCodePacket {
this.input goto 14
val data = TEA.decrypt(this.input.readAllBytes().cutTail(1), Protocol.key00BA.hexToBytes())

View File

@ -1,3 +1,5 @@
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package net.mamoe.mirai.network.packet.action
import net.mamoe.mirai.network.Protocol
@ -13,7 +15,7 @@ import java.util.*
* @author Him188moe
*/
@PacketId("00 A7")
@ExperimentalUnsignedTypes
class ClientCanAddFriendPacket(
val bot: Long,
val qq: Long,
@ -47,7 +49,7 @@ class ServerCanAddFriendResponsePacket(input: DataInputStream) : ServerPacket(in
FAILED,
}
@ExperimentalUnsignedTypes
override fun decode() {
val data = input.goto(0).readAllBytes()
if (data.size == 99) {
@ -78,7 +80,7 @@ class ServerCanAddFriendResponsePacket(input: DataInputStream) : ServerPacket(in
* 请求添加好友
*/
@PacketId("00 AE")
@ExperimentalUnsignedTypes
class ClientAddFriendPacket(
val bot: Long,
val qq: Long,

View File

@ -10,7 +10,7 @@ import java.io.DataInputStream
* @author Him188moe
*/
@PacketId("00 CD")
@ExperimentalUnsignedTypes
class ClientSendFriendMessagePacket(
private val botQQ: Long,
private val targetQQ: Long,

View File

@ -9,7 +9,7 @@ import java.io.DataInputStream
* @author Him188moe
*/
@PacketId("00 02")
@ExperimentalUnsignedTypes
class ClientSendGroupMessagePacket(
private val groupId: Long,//不是 number
private val botQQ: Long,

View File

@ -1,3 +1,5 @@
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package net.mamoe.mirai.network.packet.image
import net.mamoe.mirai.network.packet.*
@ -15,7 +17,7 @@ import java.io.DataInputStream
* @author Him188moe
*/
@PacketId("03 88")
@ExperimentalUnsignedTypes
class ClientTryGetGroupImageIDPacket(
private val bot: Long,
private val sessionKey: ByteArray,
@ -108,7 +110,7 @@ abstract class ServerTryUploadGroupImageResponsePacket(input: DataInputStream) :
class ServerTryUploadGroupImageSuccessPacket(input: DataInputStream) : ServerTryUploadGroupImageResponsePacket(input) {
lateinit var uKey: ByteArray
@ExperimentalUnsignedTypes
override fun decode() {
uKey = this.input.gotoWhere(ubyteArrayOf(0x42u, 0x80u, 0x01u)).readNBytes(128)
}

View File

@ -9,7 +9,7 @@ import net.mamoe.mirai.utils.ClientLoginStatus
*
* @author Him188moe
*/
@ExperimentalUnsignedTypes
@PacketId("00 EC")
class ClientChangeOnlineStatusPacket(
private val qq: Long,

View File

@ -4,7 +4,7 @@ import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.utils.ByteArrayDataOutputStream
import net.mamoe.mirai.utils.TEA
import net.mamoe.mirai.utils.TestedSuccessfully
import net.mamoe.mirai.utils.Tested
import net.mamoe.mirai.utils.hexToBytes
import java.io.DataOutputStream
@ -14,8 +14,8 @@ import java.io.DataOutputStream
* @author Him188moe
*/
@PacketId("08 36 31 03")
@ExperimentalUnsignedTypes
@TestedSuccessfully
@Tested
class ClientPasswordSubmissionPacket(
private val qq: Long,
private val password: String,
@ -24,7 +24,7 @@ class ClientPasswordSubmissionPacket(
private val tgtgtKey: ByteArray,
private val token0825: ByteArray
) : ClientPacket() {
@ExperimentalUnsignedTypes
override fun encode() {
this.writeQQ(qq)
this.writeHex(Protocol.passwordSubmissionKey1)
@ -40,21 +40,21 @@ class ClientPasswordSubmissionPacket(
}
@PacketId("08 36 31 04")
@ExperimentalUnsignedTypes
class ClientLoginResendPacket3104(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray, tlv0006: ByteArray? = null)
: ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA, tlv0006)
@PacketId("08 36 31 05")
@ExperimentalUnsignedTypes
class ClientLoginResendPacket3105(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray)
: ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA, null)
@PacketId("08 36 31 06")
@ExperimentalUnsignedTypes
class ClientLoginResendPacket3106(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, token00BA: ByteArray, tlv0006: ByteArray? = null)
: ClientLoginResendPacket(qq, password, loginTime, loginIP, tgtgtKey, token0825, token00BA, tlv0006)
@ExperimentalUnsignedTypes
open class ClientLoginResendPacket internal constructor(
val qq: Long,
val password: String,
@ -93,7 +93,7 @@ open class ClientLoginResendPacket internal constructor(
/**
* @author Him188moe
*/
@ExperimentalUnsignedTypes
private fun DataOutputStream.writePart1(qq: Long, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray, tlv0006: ByteArray? = null) {
//this.writeInt(System.currentTimeMillis().toInt())
@ -130,7 +130,7 @@ private fun DataOutputStream.writePart1(qq: Long, password: String, loginTime: I
this.writeHex("60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6")//key
}
@ExperimentalUnsignedTypes
private fun DataOutputStream.writePart2() {
this.writeHex("03 12")//tag

View File

@ -4,7 +4,7 @@ import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.PacketId
import net.mamoe.mirai.network.packet.ServerPacket
import net.mamoe.mirai.network.packet.goto
import net.mamoe.mirai.utils.TestedSuccessfully
import net.mamoe.mirai.utils.Tested
import java.io.DataInputStream
/**
@ -23,7 +23,7 @@ class ServerLoginResponseKeyExchangePacket(input: DataInputStream, val flag: Fla
var tokenUnknown: ByteArray? = null
lateinit var tgtgtKey: ByteArray//16bytes
@TestedSuccessfully
@Tested
override fun decode() {
this.input.skip(5)
tgtgtKey = this.input.readNBytes(16)//22
@ -46,8 +46,8 @@ class ServerLoginResponseKeyExchangePacket(input: DataInputStream, val flag: Fla
}
class Encrypted(input: DataInputStream, private val flag: Flag) : ServerPacket(input) {
@ExperimentalUnsignedTypes
@TestedSuccessfully
@Tested
fun decrypt(tgtgtKey: ByteArray): ServerLoginResponseKeyExchangePacket {
return ServerLoginResponseKeyExchangePacket(this.decryptBy(Protocol.shareKey, tgtgtKey), flag).setId(this.idHex)
}

View File

@ -1,3 +1,5 @@
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.network.packet.login
import net.mamoe.mirai.network.Protocol
@ -5,7 +7,7 @@ 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.readString
import net.mamoe.mirai.utils.TestedSuccessfully
import net.mamoe.mirai.utils.Tested
import net.mamoe.mirai.utils.toUHexString
import java.io.DataInputStream
@ -21,8 +23,8 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in
lateinit var encryptionKey: ByteArray
@TestedSuccessfully
@ExperimentalUnsignedTypes
@Tested
override fun decode() {
this.input.skip(7)//8
this.encryptionKey = this.input.readNBytes(16)//24
@ -52,7 +54,7 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in
class Encrypted(input: DataInputStream) : ServerPacket(input) {
@ExperimentalUnsignedTypes
fun decrypt(tgtgtKey: ByteArray): ServerLoginResponseSuccessPacket {
input goto 14
return ServerLoginResponseSuccessPacket(this.decryptBy(Protocol.shareKey, tgtgtKey)).setId(this.idHex)

View File

@ -1,10 +1,12 @@
@file:Suppress("EXPERIMENTAL_API_USAGE")
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.dataInputStream
import net.mamoe.mirai.network.packet.goto
import net.mamoe.mirai.utils.TestedSuccessfully
import net.mamoe.mirai.utils.Tested
import net.mamoe.mirai.utils.hexToUBytes
import java.io.DataInputStream
@ -20,8 +22,8 @@ class ServerLoginResponseVerificationCodeInitPacket(input: DataInputStream, priv
var unknownBoolean: Boolean? = null
@TestedSuccessfully
@ExperimentalUnsignedTypes
@Tested
override fun decode() {
val verifyCodeLength = this.input.goto(78).readShort()//2bytes
this.verifyCodePart1 = this.input.readNBytes(verifyCodeLength.toInt())
@ -39,7 +41,7 @@ class ServerLoginResponseVerificationCodeInitPacket(input: DataInputStream, priv
}
@ExperimentalUnsignedTypes
fun decrypt(): ServerLoginResponseVerificationCodeInitPacket {
this.input goto 14
val data = this.decryptBy(Protocol.shareKey).goto(0).readAllBytes()

View File

@ -1,277 +1,269 @@
package net.mamoe.mirai.utils
import net.mamoe.mirai.network.Protocol
import java.nio.ByteBuffer
import java.util.*
import kotlin.experimental.and
import kotlin.experimental.xor
/**
* @author Him188moe
*/
/**
* TEA 加密
*
* @author iweiz https://github.com/iweizime/StepChanger/blob/master/app/src/main/java/me/iweizi/stepchanger/qq/Cryptor.java
*/
class TEA(private val key: ByteArray) {
object TEA {
private const val UINT32_MASK = 0xffffffffL
private fun doOption(data: ByteArray, key: ByteArray, encrypt: Boolean): ByteArray {
val mRandom = Random()
lateinit var mOutput: ByteArray
lateinit var mInBlock: ByteArray
var mIndexPos: Int
lateinit var mIV: ByteArray
var mOutPos = 0
var mPreOutPos = 0
var isFirstBlock = true
companion object {
val CRYPTOR_SHARE_KEY = TEA(Protocol.hexToBytes(Protocol.shareKey))
val CRYPTOR_0825KEY = TEA(Protocol.hexToBytes(Protocol.key0825))
val mKey = LongArray(4)
private val UINT32_MASK = 0xffffffffL
for (i in 0..3) {
mKey[i] = pack(key, i * 4, 4)
}
fun doOption(data: ByteArray, key: ByteArray, encrypt: Boolean): ByteArray {
val mRandom = Random()
lateinit var mOutput: ByteArray
lateinit var mInBlock: ByteArray
var mIndexPos: Int
lateinit var mIV: ByteArray
var mOutPos = 0
var mPreOutPos = 0
var isFirstBlock: Boolean = true
fun rand(): Int {
return mRandom.nextInt()
}
val mKey = LongArray(4)
fun encode(bytes: ByteArray): ByteArray {
var v0 = pack(bytes, 0, 4)
var v1 = pack(bytes, 4, 4)
var sum: Long = 0
val delta = 0x9e3779b9L
for (i in 0..15) {
sum = sum + delta and UINT32_MASK
v0 += (v1 shl 4) + mKey[0] xor v1 + sum xor v1.ushr(5) + mKey[1]
v0 = v0 and UINT32_MASK
v1 += (v0 shl 4) + mKey[2] xor v0 + sum xor v0.ushr(5) + mKey[3]
v1 = v1 and UINT32_MASK
}
return ByteBuffer.allocate(8).putInt(v0.toInt()).putInt(v1.toInt()).array()
}
for (i in 0..3) {
mKey[i] = pack(key, i * 4, 4)
fun decode(bytes: ByteArray, offset: Int): ByteArray {
var v0 = pack(bytes, offset, 4)
var v1 = pack(bytes, offset + 4, 4)
val delta = 0x9e3779b9L
var sum = delta shl 4 and UINT32_MASK
for (i in 0..15) {
v1 -= (v0 shl 4) + mKey[2] xor v0 + sum xor v0.ushr(5) + mKey[3]
v1 = v1 and UINT32_MASK
v0 -= (v1 shl 4) + mKey[0] xor v1 + sum xor v1.ushr(5) + mKey[1]
v0 = v0 and UINT32_MASK
sum = sum - delta and UINT32_MASK
}
return ByteBuffer.allocate(8).putInt(v0.toInt()).putInt(v1.toInt()).array()
}
fun encodeOneBlock() {
mIndexPos = 0
while (mIndexPos < 8) {
mInBlock[mIndexPos] = if (isFirstBlock)
mInBlock[mIndexPos]
else
(mInBlock[mIndexPos] xor mOutput[mPreOutPos + mIndexPos])
mIndexPos++
}
fun rand(): Int {
return mRandom.nextInt()
System.arraycopy(encode(mInBlock), 0, mOutput, mOutPos, 8)
mIndexPos = 0
while (mIndexPos < 8) {
val outPos = mOutPos + mIndexPos
mOutput[outPos] = (mOutput[outPos] xor mIV[mIndexPos])
mIndexPos++
}
System.arraycopy(mInBlock, 0, mIV, 0, 8)
mPreOutPos = mOutPos
mOutPos += 8
mIndexPos = 0
isFirstBlock = false
}
fun encode(bytes: ByteArray): ByteArray {
var v0 = pack(bytes, 0, 4)
var v1 = pack(bytes, 4, 4)
var sum: Long = 0
val delta = 0x9e3779b9L
for (i in 0..15) {
sum = sum + delta and UINT32_MASK
v0 += (v1 shl 4) + mKey[0] xor v1 + sum xor v1.ushr(5) + mKey[1]
v0 = v0 and UINT32_MASK
v1 += (v0 shl 4) + mKey[2] xor v0 + sum xor v0.ushr(5) + mKey[3]
v1 = v1 and UINT32_MASK
}
return ByteBuffer.allocate(8).putInt(v0.toInt()).putInt(v1.toInt()).array()
}
fun decode(bytes: ByteArray, offset: Int): ByteArray {
var v0 = pack(bytes, offset, 4)
var v1 = pack(bytes, offset + 4, 4)
val delta = 0x9e3779b9L
var sum = delta shl 4 and UINT32_MASK
for (i in 0..15) {
v1 -= (v0 shl 4) + mKey[2] xor v0 + sum xor v0.ushr(5) + mKey[3]
v1 = v1 and UINT32_MASK
v0 -= (v1 shl 4) + mKey[0] xor v1 + sum xor v1.ushr(5) + mKey[1]
v0 = v0 and UINT32_MASK
sum = sum - delta and UINT32_MASK
}
return ByteBuffer.allocate(8).putInt(v0.toInt()).putInt(v1.toInt()).array()
}
fun encodeOneBlock() {
mIndexPos = 0
while (mIndexPos < 8) {
mInBlock[mIndexPos] = if (isFirstBlock)
mInBlock[mIndexPos]
else
(mInBlock[mIndexPos] xor mOutput[mPreOutPos + mIndexPos])
fun decodeOneBlock(ciphertext: ByteArray, offset: Int, len: Int): Boolean {
mIndexPos = 0
while (mIndexPos < 8) {
if (mOutPos + mIndexPos < len) {
mIV[mIndexPos] = (mIV[mIndexPos] xor ciphertext[mOutPos + offset + mIndexPos])
mIndexPos++
continue
}
System.arraycopy(encode(mInBlock), 0, mOutput, mOutPos, 8)
mIndexPos = 0
while (mIndexPos < 8) {
val out_pos = mOutPos + mIndexPos
mOutput[out_pos] = (mOutput[out_pos] xor mIV[mIndexPos])
mIndexPos++
}
System.arraycopy(mInBlock, 0, mIV, 0, 8)
mPreOutPos = mOutPos
mOutPos += 8
mIndexPos = 0
isFirstBlock = false
}
fun decodeOneBlock(ciphertext: ByteArray, offset: Int, len: Int): Boolean {
mIndexPos = 0
while (mIndexPos < 8) {
if (mOutPos + mIndexPos < len) {
mIV[mIndexPos] = (mIV[mIndexPos] xor ciphertext[mOutPos + offset + mIndexPos])
mIndexPos++
continue
}
return true
}
mIV = decode(mIV, 0)
mOutPos += 8
mIndexPos = 0
return true
}
fun encrypt(plaintext: ByteArray, offset: Int, len: Int): ByteArray {
var len = len;
var offset = offset;
mInBlock = ByteArray(8)
mIV = ByteArray(8)
mOutPos = 0
mPreOutPos = 0
isFirstBlock = true
mIndexPos = (len + 10) % 8
if (mIndexPos != 0) {
mIndexPos = 8 - mIndexPos
}
mOutput = ByteArray(mIndexPos + len + 10)
mInBlock[0] = (rand() and 0xf8 or mIndexPos).toByte()
for (i in 1..mIndexPos) {
mInBlock[i] = (rand() and 0xff).toByte()
}
++mIndexPos
for (i in 0..7) {
mIV[i] = 0
}
mIV = decode(mIV, 0)
mOutPos += 8
mIndexPos = 0
return true
var g = 0
while (g < 2) {
if (mIndexPos < 8) {
mInBlock[mIndexPos++] = (rand() and 0xff).toByte()
++g
}
if (mIndexPos == 8) {
encodeOneBlock()
}
}
}
while (len > 0) {
if (mIndexPos < 8) {
mInBlock[mIndexPos++] = plaintext[offset++]
}
if (mIndexPos == 8) {
encodeOneBlock()
}
len--
}
g = 0
while (g < 7) {
if (mIndexPos < 8) {
mInBlock[mIndexPos++] = 0.toByte()
}
if (mIndexPos == 8) {
encodeOneBlock()
}
g++
}
return mOutput
@Suppress("NAME_SHADOWING")
fun encrypt(plaintext: ByteArray, offset: Int, len: Int): ByteArray {
var len = len
var offset = offset
mInBlock = ByteArray(8)
mIV = ByteArray(8)
mOutPos = 0
mPreOutPos = 0
isFirstBlock = true
mIndexPos = (len + 10) % 8
if (mIndexPos != 0) {
mIndexPos = 8 - mIndexPos
}
mOutput = ByteArray(mIndexPos + len + 10)
mInBlock[0] = (rand() and 0xf8 or mIndexPos).toByte()
for (i in 1..mIndexPos) {
mInBlock[i] = (rand() and 0xff).toByte()
}
++mIndexPos
for (i in 0..7) {
mIV[i] = 0
}
fun decrypt(cipherText: ByteArray, offset: Int, len: Int): ByteArray? {
require(!(len % 8 != 0 || len < 16)) { "must len % 8 == 0 && len >= 16" }
mIV = decode(cipherText, offset)
mIndexPos = (mIV[0] and 7).toInt()
var plen = len - mIndexPos - 10
isFirstBlock = true
if (plen < 0) {
return null
var g = 0
while (g < 2) {
if (mIndexPos < 8) {
mInBlock[mIndexPos++] = (rand() and 0xff).toByte()
++g
}
mOutput = ByteArray(plen)
mPreOutPos = 0
mOutPos = 8
++mIndexPos
var g = 0
while (g < 2) {
if (mIndexPos < 8) {
++mIndexPos
++g
}
if (mIndexPos == 8) {
isFirstBlock = false
if (!decodeOneBlock(cipherText, offset, len)) {
throw RuntimeException("Unable to decode")
}
}
if (mIndexPos == 8) {
encodeOneBlock()
}
}
var outpos = 0
while (plen != 0) {
if (mIndexPos < 8) {
mOutput[outpos++] = if (isFirstBlock)
mIV[mIndexPos]
else
(cipherText[mPreOutPos + offset + mIndexPos] xor mIV[mIndexPos])
while (len > 0) {
if (mIndexPos < 8) {
mInBlock[mIndexPos++] = plaintext[offset++]
}
if (mIndexPos == 8) {
encodeOneBlock()
}
len--
}
g = 0
while (g < 7) {
if (mIndexPos < 8) {
mInBlock[mIndexPos++] = 0.toByte()
}
if (mIndexPos == 8) {
encodeOneBlock()
}
g++
}
return mOutput
}
fun decrypt(cipherText: ByteArray, offset: Int, len: Int): ByteArray? {
require(!(len % 8 != 0 || len < 16)) { "must len % 8 == 0 && len >= 16" }
mIV = decode(cipherText, offset)
mIndexPos = (mIV[0] and 7).toInt()
var plen = len - mIndexPos - 10
isFirstBlock = true
if (plen < 0) {
return null
}
mOutput = ByteArray(plen)
mPreOutPos = 0
mOutPos = 8
++mIndexPos
var g = 0
while (g < 2) {
if (mIndexPos < 8) {
++mIndexPos
++g
}
if (mIndexPos == 8) {
isFirstBlock = false
if (!decodeOneBlock(cipherText, offset, len)) {
throw RuntimeException("Unable to decode")
}
}
}
var outpos = 0
while (plen != 0) {
if (mIndexPos < 8) {
mOutput[outpos++] = if (isFirstBlock)
mIV[mIndexPos]
else
(cipherText[mPreOutPos + offset + mIndexPos] xor mIV[mIndexPos])
++mIndexPos
}
if (mIndexPos == 8) {
mPreOutPos = mOutPos - 8
isFirstBlock = false
if (!decodeOneBlock(cipherText, offset, len)) {
throw RuntimeException("Unable to decode")
}
}
plen--
}
g = 0
while (g < 7) {
if (mIndexPos < 8) {
if (cipherText[mPreOutPos + offset + mIndexPos].xor(mIV[mIndexPos]).toInt() != 0) {
throw RuntimeException()
} else {
++mIndexPos
}
if (mIndexPos == 8) {
mPreOutPos = mOutPos - 8
isFirstBlock = false
if (!decodeOneBlock(cipherText, offset, len)) {
throw RuntimeException("Unable to decode")
}
}
plen--
}
g = 0
while (g < 7) {
if (mIndexPos < 8) {
if (cipherText[mPreOutPos + offset + mIndexPos].xor(mIV[mIndexPos]).toInt() != 0) {
throw RuntimeException()
} else {
++mIndexPos
}
if (mIndexPos == 8) {
mPreOutPos = mOutPos
if (!decodeOneBlock(cipherText, offset, len)) {
throw RuntimeException("Unable to decode")
}
if (mIndexPos == 8) {
mPreOutPos = mOutPos
if (!decodeOneBlock(cipherText, offset, len)) {
throw RuntimeException("Unable to decode")
}
}
g++
}
return mOutput
g++
}
return mOutput
}
return if (encrypt) {
encrypt(data, 0, data.size)
} else {
try {
return decrypt(data, 0, data.size)!!
} catch (e: Exception) {
println("Source: " + data.toUHexString(" "))
println("Key: " + key.toUHexString(" "))
throw e
}
return if (encrypt) {
encrypt(data, 0, data.size)
} else {
try {
return decrypt(data, 0, data.size)!!
} catch (e: Exception) {
println("Source: " + data.toUHexString(" "))
println("Key: " + key.toUHexString(" "))
throw e
}
}
fun encrypt(source: ByteArray, key: ByteArray): ByteArray {
return doOption(source, key, true)
}
fun encrypt(source: ByteArray, keyHex: String): ByteArray {
return encrypt(source, keyHex.hexToBytes())
}
fun decrypt(source: ByteArray, key: ByteArray): ByteArray {
return doOption(source, key, false)
}
fun decrypt(source: ByteArray, keyHex: String): ByteArray {
return decrypt(source, keyHex.hexToBytes())
}
private fun pack(bytes: ByteArray, offset: Int, len: Int): Long {
var result: Long = 0
val max_offset = if (len > 8) offset + 8 else offset + len
for (index in offset until max_offset) {
result = result shl 8 or (bytes[index].toLong() and 0xffL)
}
return result shr 32 or (result and UINT32_MASK)
}
}
fun encrypt(source: ByteArray, key: ByteArray): ByteArray {
return doOption(source, key, true)
}
@Suppress("unused")
fun encrypt(source: ByteArray, keyHex: String): ByteArray {
return encrypt(source, keyHex.hexToBytes())
}
fun decrypt(source: ByteArray, key: ByteArray): ByteArray {
return doOption(source, key, false)
}
fun decrypt(source: ByteArray, keyHex: String): ByteArray {
return decrypt(source, keyHex.hexToBytes())
}
@Suppress("SameParameterValue")
private fun pack(bytes: ByteArray, offset: Int, len: Int): Long {
var result: Long = 0
val maxOffset = if (len > 8) offset + 8 else offset + len
for (index in offset until maxOffset) {
result = result shl 8 or (bytes[index].toLong() and 0xffL)
}
return result shr 32 or (result and UINT32_MASK)
}
}

View File

@ -5,4 +5,4 @@ package net.mamoe.mirai.utils
*
* @author Him188moe
*/
internal annotation class TestedSuccessfully
internal annotation class Tested

View File

@ -1,3 +1,5 @@
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package net.mamoe.mirai.utils
import net.mamoe.mirai.network.Protocol
@ -26,14 +28,14 @@ fun ByteArray.toHexString(separator: String = " "): String = this.joinToString(s
return@joinToString ret
}
@ExperimentalUnsignedTypes
fun ByteArray.toUHexString(separator: String = " "): String = this.toUByteArray().toUHexString(separator)
@ExperimentalUnsignedTypes
@JvmSynthetic
fun ByteArray.toUHexString(): String = this.toUByteArray().toUHexString()
@ExperimentalUnsignedTypes
@JvmSynthetic
fun UByteArray.toUHexString(separator: String = " "): String {
return this.joinToString(separator) {
@ -45,36 +47,36 @@ fun UByteArray.toUHexString(separator: String = " "): String {
}
}
@ExperimentalUnsignedTypes
@JvmSynthetic
fun UByteArray.toUHexString(): String = this.toUHexString(" ")
@ExperimentalUnsignedTypes
fun Byte.toUHexString(): String = this.toUByte().toString(16)
@ExperimentalUnsignedTypes
fun String.hexToBytes(): ByteArray = Protocol.hexToBytes(this)
@ExperimentalUnsignedTypes
fun String.hexToUBytes(): UByteArray = Protocol.hexToUBytes(this)
@ExperimentalUnsignedTypes
fun String.hexToInt(): Int = hexToBytes().toUInt().toInt()
@ExperimentalUnsignedTypes
fun ByteArray.toUInt(): UInt =
this[0].toUInt().and(255u).shl(24) + this[1].toUInt().and(255u).shl(16) + this[2].toUInt().and(255u).shl(8) + this[3].toUInt().and(255u).shl(0)
open class ByteArrayDataOutputStream : DataOutputStream(ByteArrayOutputStream()) {
open fun toByteArray(): ByteArray = (out as ByteArrayOutputStream).toByteArray()
@ExperimentalUnsignedTypes
open fun toUByteArray(): UByteArray = (out as ByteArrayOutputStream).toByteArray().toUByteArray()
}
@JvmSynthetic
fun lazyEncode(t: (ByteArrayDataOutputStream) -> Unit): ByteArray = ByteArrayDataOutputStream().also(t).toByteArray()
@ExperimentalUnsignedTypes
fun getRandomByteArray(length: Int): ByteArray {
val bytes = LinkedList<Byte>()
repeat(length) { bytes.add((Math.random() * 255).toByte()) }

View File

@ -1,4 +1,5 @@
@file:JvmName("Varint")
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.utils
@ -21,7 +22,7 @@ fun encodeZigZag32(signedInt: Int): Long {
return (signedInt shl 1 xor (signedInt shr 31)).toLong()
}
@ExperimentalUnsignedTypes
@JvmSynthetic
fun decodeZigZag32(uint: UInt): Int {
return decodeZigZag32(uint.toLong())
@ -39,25 +40,25 @@ fun decodeZigZag64(signedLong: Long): Long {
return signedLong.ushr(1) xor -(signedLong and 1)
}
@ExperimentalUnsignedTypes
@Throws(IOException::class)
fun DataInputStream.readVarInt(): Int {
return decodeZigZag32(this.readUnsignedVarInt())
}
@ExperimentalUnsignedTypes
@Throws(IOException::class)
fun DataInputStream.readUnsignedVarInt(): UInt {
return read(this, 5).toUInt()
}
@ExperimentalUnsignedTypes
@Throws(IOException::class)
fun DataInputStream.readVarLong(): Long {
return decodeZigZag64(readUnsignedVarLong().toLong())
}
@ExperimentalUnsignedTypes
@Throws(IOException::class)
fun DataInputStream.readUnsignedVarLong(): ULong {
return read(this, 10).toULong()
@ -68,7 +69,7 @@ fun DataOutputStream.writeVarInt(signedInt: Int) {
this.writeUVarInt(encodeZigZag32(signedInt))
}
@ExperimentalUnsignedTypes
@Throws(IOException::class)
fun DataOutputStream.writeUVarInt(uint: UInt) {
return writeUVarInt(uint.toLong())

View File

@ -1,47 +0,0 @@
import net.mamoe.mirai.network.packet.login.ClientPasswordSubmissionPacket
import net.mamoe.mirai.utils.toUHexString
@ExperimentalUnsignedTypes
fun main(){
/*
val data = "00 37 13 08 25 31 01 EB 10 08 30 69 50 1C 84 A9 C2 16 D7 52 B9 1C 79 CA 5A CF FD BC EB 10 08 30 69 50 1C 84 A9 C2 16 D7 52 B9 1C 79 CA 5A CF FD BC AE D8 A6 BB DC 21 6E 79 26 E1 A2 23 11 AA B0 9A AE D8 A6 BB DC 21 6E 79 26 E1 A2 23 11 AA B0 9A 76 E4 B8 DD 03 00 00 00 01 2E 01 00 00 68 52 00 00 00 00 A4 F1 91 88 C9 82 14 99 0C 9E 56 55 91 23 C8 3D C3 47 F0 25 A1 8E 74 EF 1E 0B 32 5B 20 8A FA 3B 0B 52 8F 86 E6 04 F1 D6 F8 63 75 60 8C 0C 7D 06 D1 E0 22 F8 49 EF AF 61 EE 7E 69 72 EB 10 08 30 69 50 1C 84 A9 C2 16 D7 52 B9 1C 79 CA 5A CF FD BC AE D8 A6 BB DC 21 6E 79 26 E1 A2 23 11 AA B0 9A 49 39 72 ED 61 12 B6 88 4D A2 56 23 E9 92 11 92 27 4A 70 00 C9 01 7B 03";
val s = DataInputStream(data.hexToBytes().inputStream())
val packet = ServerTouchResponsePacket(ServerTouchResponsePacket.Type.TYPE_08_25_31_01, s)
packet.decode()
System.out.println(packet.token.toUByteArray().toUHexString(" "))
System.out.println(packet.loginTime.toUHexString(" "))
System.out.println(packet.loginIP)
*/
// val packet = ClientPasswordSubmissionPacket(1994701021,"xiaoqqq",)
/*
val data = "00 01 09 00 70 00 01 5C 71 80 A6 BA 20 62 2E C1 BE BF F2 47 37 40 A1 00 38 91 25 85 58 18 D3 67 77 2C 4D 02 D8 66 A6 F7 3E 57 D8 CE 01 47 7F D0 8F 13 C8 3A E5 19 A2 60 BC 4C 9A 35 4E 92 9F 21 48 6C 67 68 36 6B 94 C1 6F 11 8D 55 6B 04 9A 22 C3 00 20 29 7E D4 A7 16 02 07 14 41 90 3A 65 06 AC CB 28 AB 90 DB 46 33 C9 C0 1D 06 44 7A 92 17 C3 A5 F3 00 00 01 03 00 14 00 01 00 10 60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6 01 07 01 D3 00 01 00 16 00 00 00 01 00 00 00 64 00 00 0D B6 00 09 3A 80 00 00 00 3C 00 02 2E 29 4E 47 5F 68 78 2C 47 25 5F 59 50 65 60 5D 00 88 00 04 5D 59 45 17 B7 5F F8 D4 00 00 00 00 00 78 38 E0 3B 23 4A C5 0E 93 CB C1 66 96 37 8B 46 B2 86 23 3F 2D 09 45 E0 16 1C E9 9C 11 7A FA 2D A8 50 47 42 74 01 06 84 76 0E 5F C6 04 29 1A 4A 65 AA 93 49 DF BD 00 ED 80 B8 26 CA 80 E8 20 6D 15 43 DD D8 E6 48 C2 8A 5A F8 70 6B 51 3A E2 2D 21 95 4B 6A 75 A8 90 CA B1 C0 E5 73 99 D7 59 D8 DD 3D C9 5C E4 49 61 22 11 60 85 48 C4 7D E0 84 62 AD B3 13 84 61 C1 9E 19 35 41 44 44 37 3F 21 33 64 4B 37 5D 77 6D 61 3F 00 78 00 01 5D 59 45 17 00 70 A4 D9 44 9E 95 51 B4 B0 91 CC 1E DB 34 F9 F7 13 8B 30 08 C0 AE 33 22 9C FF 87 CF 9B A2 B0 E5 E1 D0 E0 AD DD 8F E9 F6 1E 01 1F AA 74 46 66 B4 81 54 B9 29 E5 FC 0B 7F C9 13 AE 32 BA D6 55 2E B0 A1 30 24 B6 F2 E7 62 F9 2E 00 E4 51 61 50 7C D1 36 E8 61 96 36 FF B7 32 74 3C 2A F7 74 63 DA 7D 57 84 18 ED 84 E9 D8 87 6D 66 1D D5 84 D4 23 99 00 83 01 63 2A 69 2E 25 79 28 3B 29 33 29 40 28 54 7E 21 00 70 00 01 5D 59 45 17 00 68 6F 1F FB 31 7B D7 B7 D8 91 32 D7 20 8B 8A F6 02 C8 22 E5 24 8C 25 F2 6A C5 B0 ED 35 01 BF AF 42 72 33 4E FB 3F D3 02 BA F4 46 2B 68 20 0B E3 39 81 B1 D3 8A E0 1B 0F 69 D1 70 AE 49 A5 24 4F BB 58 4F F8 31 A0 37 4C CD F1 12 35 80 99 7D 25 CA F9 E9 45 B6 B0 57 56 66 61 C5 7B 90 57 BF E2 2C 94 91 80 1A B0 D7 21 A8 44 2C 33 4A 29 77 5F 71 40 41 38 3D 7A 41 65 33 01 08 00 29 00 01 00 25 00 1D 02 5B 14 28 E0 B9 91 E2 80 A2 CC 80 CF 89 E2 80 A2 CC 81 E0 B9 91 29 02 13 80 02 00 05 00 04 00 00 00 01 01 15 00 10 F9 86 85 81 30 F6 1B E0 E7 97 98 F6 46 C3 4F B2"
val s = DataInputStream(data.hexToBytes().inputStream())
val packet = ServerLoginResponseSuccessPacket(s,(data.length+1)/3)
packet.decode()
System.out.println("0828key: \n" + packet._0828_rec_decr_key.toUByteArray().toUHexString(" "))
System.out.println("token88: \n" + packet.token88.toUByteArray().toUHexString(" "))
System.out.println("token38: \n" + packet.token38.toUByteArray().toUHexString(" "))
System.out.println("enckey: \n" + packet.encryptionKey.toUByteArray().toUHexString(" "))
System.out.println("nick: " + packet.nick)
System.out.println("age: " + packet.age)
System.out.println("gender: " + packet.gender)
*/
/*
val data = "FB 01 04 03 33 00 01 00 BA 02 03 2C 13 00 05 01 00 00 01 23 00 38 F5 C3 CF F4 B4 27 C5 8F 9B D3 ED 18 73 7D E9 CB 43 1F 57 43 BE D3 1B 9A F5 26 2B F4 D9 43 14 9A ED 3B C3 6C E5 7F 4E B0 0C BA 55 57 18 06 78 E1 13 A7 B2 A8 7F 47 E1 1C 02 BC 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 00 00 00 82 00 00 00 35 08 03 00 00 00 BA 12 C3 02 00 00 00 04 67 41 4D 41 00 00 B1 8F 0B FC 61 05 00 00 00 01 73 52 47 42 00 AE CE 1C E9 00 00 00 6C 50 4C 54 45 F6 F8 F4 E3 EE FD E5 FD FF EE FD F0 F6 F9 E7 F7 F9 EC F4 FE FF F7 F7 F9 F5 F4 FF EC F7 FF E6 F4 E0 F5 FC F8 49 5B 8F CB DB FA BB C9 F5 2B 40 7C D6 E6 FF FD FB FF ED F1 F0 2A 43 B3 D6 F6 FF FC F1 FC 1C 38 91 A7 BD F6 63 74 BD 70 8B CC 34 4F A5 DE F3 F1 75 88 E7 A4 B7 D3 73 82 A1 8C A3 DC F3 FB D8 4D 68 B9 94 A8 FB 8D 9C B6 CB 42 B0 8E 00 00 0A 6F 49 44 41 54 58 C3 B4 57 89 76 EB 2A 12 14 20 B1 09 10 42 68 DF 2C FB FF FF 71 0A 79 49 E2 E4 CE CC 79 37 8F 13 59 B6 72 EC 2E AA BB AB 9A 2C FB 61 89 8F 95 E5 79 A9 70 CB B2 22 C7 2A 65 DB 5E 72 21 F1 A9 90 B2 28 C4 F9 AF 5F 5F 05 30 9C 28 D2 4B C6 58 F9 8C 92 17 39 13 6D 9B FF EB 10 8A 3B 0F 2F 10 52 64 45 51 64 42 A6 37 79 21 DA FC F2 6F 40 08 9F AE B7 9C A4 C8 27 31 F2 C4 50 A4 D4 9C F9 01 BC A2 90 0F 08 E1 2F AE 1F E3 7E 7D 24 52 F4 67 2C 91 02 E3 CA 13 2F 78 97 00 86 DF 4E C4 23 56 F1 F8 7B 10 90 42 3D D2 93 EE 27 04 F1 80 F0 4B 99 10 4F 62 5E D9 2D EE 57 8A F1 A0 E1 64 20 2B 55 F9 C8 C3 67 08 F8 81 7F F2 F7 BE FD 67 1D 9E 9B 4F EB 89 25 21 28 19 63 09 5D A9 94 2A 59 AA 87 B3 32 4E 84 FF 3C 13 8F AF 06 F1 29 FD E2 C1 02 54 E0 8C 5E 5C 2E A5 72 43 65 F4 E5 72 61 5C 4A 45 81 41 97 79 0A 9E FF 62 22 C2 EB 7E 42 48 45 80 2B 0F 58 B9 66 D6 1C 63 75 D3 97 BC F4 08 0F 08 5C 6B 8D CC 14 1F 10 C4 5F B4 C3 37 66 EE E5 78 CF 42 12 05 CD F5 4D 29 EB 36 AD 19 82 CF 76 35 C6 86 B2 94 A7 36 FC 62 39 BE A8 B8 D7 02 78 08 8F 66 E4 44 45 DF BB AB A3 34 92 14 DF 54 C6 32 1D 00 21 7F 41 08 7F C9 7F F8 28 88 4F B5 90 89 3A 21 90 9E DF E8 DE 34 4D 8C D1 EF C6 AC 6B 7F 74 8E B1 FA 84 90 7F B0 F0 CF 5A E2 27 4C AF 8E 28 EF 24 48 B2 AF B1 9A 96 3E F6 43 75 38 6F 29 5D 1A C7 59 78 87 F0 1B B2 F0 95 05 3C 93 B2 26 B6 9F BA 18 AB AE 59 EC 88 17 17 A9 8F 4B B3 CE 60 A1 CD F2 CB 03 42 10 7F D9 06 1F 76 80 8E 4F 6D 9F 56 99 05 25 A5 DD AA EB 62 7A 6F 87 E6 B8 0E 5D 33 C6 99 C6 C4 02 24 EB 74 8C 87 98 64 F8 5E A9 9E 1E F7 72 FB FF B3 21 8A A4 00 01 00 28 F9 59 C5 E6 34 43 53 95 C8 17 2E 62 78 BF E8 27 BF 20 BA 11 5A 74 D1 7C D0 95 6C F6 A3 41 D2 84 BD 7D F6 64 BC 27 40 50 01 15 00 10 44 98 EB B8 30 3B DE 7D 2B CC 4C 41 B3 1C 92 86"
val s = DataInputStream(data.hexToBytes().inputStream())
val packet = ServerLoginResponseVerificationCodePacket(s,(data.length+1)/3)
packet.decode()
println(packet.token00BA.toUByteArray().toUHexString(" "))
println(packet.verifyCode.toUByteArray().toUHexString(" "))
println(packet.verifyCodeLength)
File(System.getProperty("user.dir") + "/5.png").createNewFile()
packet.verifyCode.inputStream().transferTo(FileOutputStream(System.getProperty("user.dir") + "/5.png"))
*/
val packet = ClientPasswordSubmissionPacket(1994701021, "xiaoqqq", 131513, "123.123.123.123", "tgtgtKey".toByteArray(), "".toByteArray())
packet.encodeToByteArray().toUByteArray().toUHexString(" ")
}