diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt index 1081ed989..51b822ef2 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt @@ -11,9 +11,12 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.* import net.mamoe.mirai.qqandroid.utils.GuidSource import net.mamoe.mirai.qqandroid.utils.MacOrAndroidIdChangeFlag import net.mamoe.mirai.qqandroid.utils.guidFlag -import net.mamoe.mirai.utils.* +import net.mamoe.mirai.utils.MiraiDebugAPI +import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.cryptor.contentToString import net.mamoe.mirai.utils.cryptor.decryptBy +import net.mamoe.mirai.utils.currentTimeMillis +import net.mamoe.mirai.utils.currentTimeSeconds import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.utils.io.discardExact @@ -220,11 +223,12 @@ internal object LoginPacket : PacketFactory("wt sealed class LoginPacketResponse : Packet { - object Success : LoginPacketResponse(){ + object Success : LoginPacketResponse() { override fun toString(): String { return "LoginPacketResponse.Success" } } + data class Error( val title: String, val message: String, @@ -236,7 +240,7 @@ internal object LoginPacket : PacketFactory("wt class Slider( val data: IoBuffer, val sign: ByteArray - ) : Captcha(){ + ) : Captcha() { override fun toString(): String { return "LoginPacketResponse.Captcha.Slider" } @@ -245,7 +249,7 @@ internal object LoginPacket : PacketFactory("wt class Picture( val data: IoBuffer, val sign: ByteArray - ) : Captcha(){ + ) : Captcha() { override fun toString(): String { return "LoginPacketResponse.Captcha.Picture" } @@ -282,7 +286,7 @@ internal object LoginPacket : PacketFactory("wt 2 -> onSolveLoginCaptcha(tlvMap, bot) 160 /*-96*/ -> onUnsafeDeviceLogin(tlvMap) 204 /*-52*/ -> onSMSVerifyNeeded(tlvMap, bot) - else -> error("unknown login result type: $type") + else -> tlvMap[0x149]?.let { bot.client.analysisTlv149(it) } ?: error("unknown login result type: $type") } } @@ -314,7 +318,7 @@ internal object LoginPacket : PacketFactory("wt @InternalAPI @UseExperimental(MiraiDebugAPI::class) - private fun onSolveLoginCaptcha(tlvMap: TlvMap, bot: QQAndroidBot): LoginPacketResponse. Captcha { + private fun onSolveLoginCaptcha(tlvMap: TlvMap, bot: QQAndroidBot): LoginPacketResponse.Captcha { // val ret = tlvMap[0x104]?.let { println(it.toUHexString()) } println() val question = tlvMap[0x165] ?: error("CAPTCHA QUESTION UNKNOWN") @@ -358,7 +362,6 @@ internal object LoginPacket : PacketFactory("wt DebugLogger.warning(bytes.encodeToString()) } - tlvMap119[0x149]?.let { client.analysisTlv149(it) } tlvMap119[0x130]?.let { client.analysisTlv130(it) } tlvMap119[0x113]?.let { client.analysisTlv113(it) } @@ -655,22 +658,16 @@ internal object LoginPacket : PacketFactory("wt /** * 错误消息 */ - private fun QQAndroidClient.analysisTlv149(t149: ByteArray) { - data class ErrorMessage( - val type: Short, - val title: String, - val content: String, - val otherInfo: String - ) + private fun QQAndroidClient.analysisTlv149(t149: ByteArray): LoginPacketResponse.Error { - t149.read { + return t149.read { val type: Short = readShort() val title: String = readUShortLVString() val content: String = readUShortLVString() val otherInfo: String = readUShortLVString() // do not write class into read{} block. CompilationException!! - error("Got error message: " + ErrorMessage(type, title, content, otherInfo)) // nice toString + LoginPacketResponse.Error(title = title, message = content, errorInfo = otherInfo) // nice toString } } diff --git a/mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt b/mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt index 0796323bf..4bdaff37a 100644 --- a/mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt +++ b/mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt @@ -4,7 +4,10 @@ package androidPacketTests import kotlinx.io.core.* import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketLogger -import net.mamoe.mirai.utils.cryptor.* +import net.mamoe.mirai.utils.cryptor.ECDH +import net.mamoe.mirai.utils.cryptor.contentToString +import net.mamoe.mirai.utils.cryptor.decryptBy +import net.mamoe.mirai.utils.cryptor.initialPublicKey import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.utils.io.discardExact import net.mamoe.mirai.utils.md5 @@ -205,7 +208,7 @@ fun ByteReadPacket.analysisOneFullPacket(): ByteReadPacket = debugIfFail("Failed ECDH.calculateShareKey( loadPrivateKey(ecdhPrivateKeyS), //"04cb366698561e936e80c157e074cab13b0bb68ddeb2824548a1b18dd4fb6122afe12fe48c5266d8d7269d7651a8eb6fe7".chunkedHexToBytes().adjustToPublicKey() // QQ: 04cb366698561e936e80c157e074cab13b0bb68ddeb2824548a1b18dd4fb6122afe12fe48c5266d8d7269d7651a8eb6fe7 - publicKey.adjustToPublicKey() + ECDH.constructPublicKey("30 46 30 10 06 07 2A 86 48 CE 3D 02 01 06 05 2B 81 04 00 1F 03 32 00".hexToBytes() + publicKey) ) } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/ECDH.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/ECDH.kt index e922dd287..e93a21355 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/ECDH.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/ECDH.kt @@ -66,13 +66,7 @@ private const val constantHead = "3046301006072A8648CE3D020106052B8104001F033200 private val byteArray_04 = byteArrayOf(0x04) fun ByteArray.adjustToPublicKey(): ECDHPublicKey { - val key = if (this[0].toInt() == 0x02) { // from server - commonHeadFor02 + this - } else if (!this.toUHexString("").startsWith(constantHead)) { - commonHeadForNot02 + - if (this[0].toInt() == 0x04) this - else (byteArray_04 + this) - } else this + val head = if(this.size<30) "302E301006072A8648CE3D020106052B8104001F031A00" else "3046301006072A8648CE3D020106052B8104001F03320004" - return ECDH.constructPublicKey(key) + return ECDH.constructPublicKey((head + this.toUHexString("")).chunkedHexToBytes()) } \ No newline at end of file