mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-25 03:30:15 +08:00
Update login protocol (#2433)
* Update login protocol Still need testing * Turn off debug option and make t547 null when failed * Fix wrong convert method and improve tips * Remove unused part and improve tips * Fix typo * Inline resultStatus for performance * Rename pow to PoW, the name should be "Proof of Work" * Add shadow and deps-test for kt-bignum * Try to fix deps-test * Fix deps-test again
This commit is contained in:
parent
56dea84336
commit
cc7f35519e
@ -267,6 +267,9 @@ const val `netty-transport` = "io.netty:netty-transport:${Versions.netty}"
|
|||||||
const val `netty-buffer` = "io.netty:netty-buffer:${Versions.netty}"
|
const val `netty-buffer` = "io.netty:netty-buffer:${Versions.netty}"
|
||||||
const val `bouncycastle` = "org.bouncycastle:bcprov-jdk15on:${Versions.bouncycastle}"
|
const val `bouncycastle` = "org.bouncycastle:bcprov-jdk15on:${Versions.bouncycastle}"
|
||||||
|
|
||||||
|
const val `kt-bignum` = "com.ionspin.kotlin:bignum:0.3.7"
|
||||||
|
val `kt-bignum_relocated` = RelocatedDependency(`kt-bignum`, "com.ionspin.kotlin.bignum")
|
||||||
|
|
||||||
const val `maven-resolver-api` = "org.apache.maven.resolver:maven-resolver-api:${Versions.mavenArtifactResolver}"
|
const val `maven-resolver-api` = "org.apache.maven.resolver:maven-resolver-api:${Versions.mavenArtifactResolver}"
|
||||||
const val `maven-resolver-impl` = "org.apache.maven.resolver:maven-resolver-impl:${Versions.mavenArtifactResolver}"
|
const val `maven-resolver-impl` = "org.apache.maven.resolver:maven-resolver-impl:${Versions.mavenArtifactResolver}"
|
||||||
const val `maven-resolver-connector-basic` =
|
const val `maven-resolver-connector-basic` =
|
||||||
|
@ -25,6 +25,7 @@ dependencies {
|
|||||||
api(project(":mirai-core-utils"))
|
api(project(":mirai-core-utils"))
|
||||||
implementation(`slf4j-api`) // Required by mirai-console
|
implementation(`slf4j-api`) // Required by mirai-console
|
||||||
|
|
||||||
|
relocateImplementation(project, `kt-bignum_relocated`)
|
||||||
relocateImplementation(project, `ktor-client-core_relocated`)
|
relocateImplementation(project, `ktor-client-core_relocated`)
|
||||||
relocateImplementation(project, `ktor-client-okhttp_relocated`)
|
relocateImplementation(project, `ktor-client-okhttp_relocated`)
|
||||||
relocateImplementation(project, `ktor-io_relocated`)
|
relocateImplementation(project, `ktor-io_relocated`)
|
||||||
|
@ -24,6 +24,9 @@ public fun String.sha1(): ByteArray = toByteArray().sha1()
|
|||||||
|
|
||||||
public expect fun ByteArray.sha1(offset: Int = 0, length: Int = size - offset): ByteArray
|
public expect fun ByteArray.sha1(offset: Int = 0, length: Int = size - offset): ByteArray
|
||||||
|
|
||||||
|
public fun String.sha256(): ByteArray = toByteArray().sha256()
|
||||||
|
|
||||||
|
public expect fun ByteArray.sha256(offset: Int = 0, length: Int = size - offset): ByteArray
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// How to choose 'inflate', 'inflateAllAvailable', 'InflateInput'?
|
// How to choose 'inflate', 'inflateAllAvailable', 'InflateInput'?
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
package net.mamoe.mirai.utils
|
package net.mamoe.mirai.utils
|
||||||
|
|
||||||
import io.ktor.utils.io.core.*
|
import io.ktor.utils.io.core.*
|
||||||
import io.ktor.utils.io.streams.asInput
|
import io.ktor.utils.io.streams.*
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
@ -50,6 +50,10 @@ public fun InputStream.sha1(): ByteArray {
|
|||||||
return digest("SHA-1")
|
return digest("SHA-1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun InputStream.sha256(): ByteArray {
|
||||||
|
return digest("SHA-256")
|
||||||
|
}
|
||||||
|
|
||||||
public actual fun ByteArray.md5(offset: Int, length: Int): ByteArray {
|
public actual fun ByteArray.md5(offset: Int, length: Int): ByteArray {
|
||||||
checkOffsetAndLength(offset, length)
|
checkOffsetAndLength(offset, length)
|
||||||
return MessageDigest.getInstance("MD5").apply { update(this@md5, offset, length) }.digest()
|
return MessageDigest.getInstance("MD5").apply { update(this@md5, offset, length) }.digest()
|
||||||
@ -62,6 +66,12 @@ public actual fun ByteArray.sha1(offset: Int, length: Int): ByteArray {
|
|||||||
return MessageDigest.getInstance("SHA-1").apply { update(this@sha1, offset, length) }.digest()
|
return MessageDigest.getInstance("SHA-1").apply { update(this@sha1, offset, length) }.digest()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
public actual fun ByteArray.sha256(offset: Int, length: Int): ByteArray {
|
||||||
|
checkOffsetAndLength(offset, length)
|
||||||
|
return MessageDigest.getInstance("SHA-256").apply { update(this@sha256, offset, length) }.digest()
|
||||||
|
}
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
public actual fun ByteArray.gzip(offset: Int, length: Int): ByteArray {
|
public actual fun ByteArray.gzip(offset: Int, length: Int): ByteArray {
|
||||||
ByteArrayOutputStream().use { buf ->
|
ByteArrayOutputStream().use { buf ->
|
||||||
|
@ -31,6 +31,11 @@ public actual fun ByteArray.sha1(offset: Int, length: Int): ByteArray = SHA1.cre
|
|||||||
return digest().bytes
|
return digest().bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public actual fun ByteArray.sha256(offset: Int, length: Int): ByteArray = SHA256.create().run {
|
||||||
|
update(this@sha256, offset, length)
|
||||||
|
return digest().bytes
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WARNING: DO NOT SET THIS BUFFER TOO SMALL, OR YOU WILL SEE COMPRESSION ERROR.
|
* WARNING: DO NOT SET THIS BUFFER TOO SMALL, OR YOU WILL SEE COMPRESSION ERROR.
|
||||||
*/
|
*/
|
||||||
|
@ -272,3 +272,79 @@ internal class SHA1 : SHA(chunkSize = 64, digestSize = 20) {
|
|||||||
for (n in out.indices) out[n] = (h[n / 4] ushr (24 - 8 * (n % 4))).toByte()
|
for (n in out.indices) out[n] = (h[n / 4] ushr (24 - 8 * (n % 4))).toByte()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class SHA256 : SHA(chunkSize = 64, digestSize = 32) {
|
||||||
|
companion object : HasherFactory({ SHA256() }) {
|
||||||
|
private val H = intArrayOf(
|
||||||
|
0x6a09e667, -0x4498517b, 0x3c6ef372, -0x5ab00ac6,
|
||||||
|
0x510e527f, -0x64fa9774, 0x1f83d9ab, 0x5be0cd19
|
||||||
|
)
|
||||||
|
|
||||||
|
private val K = intArrayOf(
|
||||||
|
0x428a2f98, 0x71374491, -0x4a3f0431, -0x164a245b,
|
||||||
|
0x3956c25b, 0x59f111f1, -0x6dc07d5c, -0x54e3a12b,
|
||||||
|
-0x27f85568, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||||
|
0x72be5d74, -0x7f214e02, -0x6423f959, -0x3e640e8c,
|
||||||
|
-0x1b64963f, -0x1041b87a, 0x0fc19dc6, 0x240ca1cc,
|
||||||
|
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||||
|
-0x67c1aeae, -0x57ce3993, -0x4ffcd838, -0x40a68039,
|
||||||
|
-0x391ff40d, -0x2a586eb9, 0x06ca6351, 0x14292967,
|
||||||
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||||
|
0x650a7354, 0x766a0abb, -0x7e3d36d2, -0x6d8dd37b,
|
||||||
|
-0x5d40175f, -0x57e599b5, -0x3db47490, -0x3893ae5d,
|
||||||
|
-0x2e6d17e7, -0x2966f9dc, -0xbf1ca7b, 0x106aa070,
|
||||||
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||||
|
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||||
|
0x748f82ee, 0x78a5636f, -0x7b3787ec, -0x7338fdf8,
|
||||||
|
-0x6f410006, -0x5baf9315, -0x41065c09, -0x398e870e
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val h = IntArray(8)
|
||||||
|
private val r = IntArray(8)
|
||||||
|
private val w = IntArray(64)
|
||||||
|
|
||||||
|
init {
|
||||||
|
coreReset()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun coreReset() {
|
||||||
|
arraycopy(H, 0, h, 0, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun coreUpdate(chunk: ByteArray) {
|
||||||
|
arraycopy(h, 0, r, 0, 8)
|
||||||
|
|
||||||
|
for (j in 0 until 16) w[j] = chunk.readS32_be(j * 4)
|
||||||
|
for (j in 16 until 64) {
|
||||||
|
val s0 = w[j - 15].rotateRight(7) xor w[j - 15].rotateRight(18) xor w[j - 15].ushr(3)
|
||||||
|
val s1 = w[j - 2].rotateRight(17) xor w[j - 2].rotateRight(19) xor w[j - 2].ushr(10)
|
||||||
|
w[j] = w[j - 16] + s0 + w[j - 7] + s1
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j in 0 until 64) {
|
||||||
|
val s1 = r[4].rotateRight(6) xor r[4].rotateRight(11) xor r[4].rotateRight(25)
|
||||||
|
val ch = r[4] and r[5] xor (r[4].inv() and r[6])
|
||||||
|
val t1 = r[7] + s1 + ch + K[j] + w[j]
|
||||||
|
val s0 = r[0].rotateRight(2) xor r[0].rotateRight(13) xor r[0].rotateRight(22)
|
||||||
|
val maj = r[0] and r[1] xor (r[0] and r[2]) xor (r[1] and r[2])
|
||||||
|
val t2 = s0 + maj
|
||||||
|
r[7] = r[6]
|
||||||
|
r[6] = r[5]
|
||||||
|
r[5] = r[4]
|
||||||
|
r[4] = r[3] + t1
|
||||||
|
r[3] = r[2]
|
||||||
|
r[2] = r[1]
|
||||||
|
r[1] = r[0]
|
||||||
|
r[0] = t1 + t2
|
||||||
|
|
||||||
|
}
|
||||||
|
for (j in 0 until 8) h[j] += r[j]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun coreDigest(out: ByteArray) {
|
||||||
|
for (n in out.indices) out[n] = (h[n / 4] ushr (24 - 8 * (n % 4))).toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ kotlin {
|
|||||||
api(`kotlinx-serialization-json`)
|
api(`kotlinx-serialization-json`)
|
||||||
api(`kotlinx-coroutines-core`)
|
api(`kotlinx-coroutines-core`)
|
||||||
|
|
||||||
|
implementation(`kt-bignum`)
|
||||||
implementation(project(":mirai-core-utils"))
|
implementation(project(":mirai-core-utils"))
|
||||||
implementation(`kotlinx-serialization-protobuf`)
|
implementation(`kotlinx-serialization-protobuf`)
|
||||||
implementation(`kotlinx-atomicfu`)
|
implementation(`kotlinx-atomicfu`)
|
||||||
@ -108,6 +109,14 @@ kotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Kt bignum
|
||||||
|
findByName("jvmBaseMain")?.apply {
|
||||||
|
dependencies {
|
||||||
|
relocateImplementation(`kt-bignum_relocated`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Ktor
|
// Ktor
|
||||||
|
|
||||||
findByName("commonMain")?.apply {
|
findByName("commonMain")?.apply {
|
||||||
|
@ -166,6 +166,7 @@ internal open class QQAndroidClient(
|
|||||||
var reserveUinInfo: ReserveUinInfo? = null
|
var reserveUinInfo: ReserveUinInfo? = null
|
||||||
var t402: ByteArray? = null
|
var t402: ByteArray? = null
|
||||||
lateinit var t104: ByteArray
|
lateinit var t104: ByteArray
|
||||||
|
var t547: ByteArray? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val QQAndroidClient.apkId: ByteArray get() = "com.tencent.mobileqq".toByteArray()
|
internal val QQAndroidClient.apkId: ByteArray get() = "com.tencent.mobileqq".toByteArray()
|
||||||
|
@ -275,6 +275,15 @@ internal fun BytePacketBuilder.t104(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun BytePacketBuilder.t547(
|
||||||
|
t547Data: ByteArray
|
||||||
|
) {
|
||||||
|
writeShort(0x547)
|
||||||
|
writeShortLVPacket {
|
||||||
|
writeFully(t547Data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal fun BytePacketBuilder.t174(
|
internal fun BytePacketBuilder.t174(
|
||||||
t174Data: ByteArray
|
t174Data: ByteArray
|
||||||
) {
|
) {
|
||||||
|
@ -210,6 +210,7 @@ internal class WtLogin {
|
|||||||
tlvMap[0x161]?.let { bot.client.analysisTlv161(it) }
|
tlvMap[0x161]?.let { bot.client.analysisTlv161(it) }
|
||||||
tlvMap[0x403]?.let { bot.client.randSeed = it }
|
tlvMap[0x403]?.let { bot.client.randSeed = it }
|
||||||
tlvMap[0x402]?.let { bot.client.t402 = it }
|
tlvMap[0x402]?.let { bot.client.t402 = it }
|
||||||
|
tlvMap[0x546]?.let { bot.client.analysisTlv546(it) }
|
||||||
// tlvMap[0x402]?.let { t402 ->
|
// tlvMap[0x402]?.let { t402 ->
|
||||||
// bot.client.G = buildPacket {
|
// bot.client.G = buildPacket {
|
||||||
// writeFully(bot.client.device.guid)
|
// writeFully(bot.client.device.guid)
|
||||||
|
@ -43,7 +43,7 @@ internal object WtLogin10 : WtLoginExt {
|
|||||||
0x0810
|
0x0810
|
||||||
) {
|
) {
|
||||||
writeShort(11) // subCommand
|
writeShort(11) // subCommand
|
||||||
writeShort(17)
|
writeShort(18)
|
||||||
t100(appId, subAppId, client.appClientVersion, client.ssoVersion, mainSigMap)
|
t100(appId, subAppId, client.appClientVersion, client.ssoVersion, mainSigMap)
|
||||||
t10a(client.wLoginSigInfo.tgt)
|
t10a(client.wLoginSigInfo.tgt)
|
||||||
t116(client.miscBitMap, client.subSigMap)
|
t116(client.miscBitMap, client.subSigMap)
|
||||||
@ -80,6 +80,7 @@ internal object WtLogin10 : WtLoginExt {
|
|||||||
t188(client.device.androidId)
|
t188(client.device.androidId)
|
||||||
t194(client.device.imsiMd5)
|
t194(client.device.imsiMd5)
|
||||||
t511()
|
t511()
|
||||||
|
t202(client.device.wifiBSSID, client.device.wifiSSID)
|
||||||
//t544()
|
//t544()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,11 +26,20 @@ internal object WtLogin2 : WtLoginExt {
|
|||||||
writeSsoPacket(client, client.subAppId, WtLogin.Login.commandName, sequenceId = sequenceId) {
|
writeSsoPacket(client, client.subAppId, WtLogin.Login.commandName, sequenceId = sequenceId) {
|
||||||
writeOicqRequestPacket(client, commandId = 0x0810) {
|
writeOicqRequestPacket(client, commandId = 0x0810) {
|
||||||
writeShort(2) // subCommand
|
writeShort(2) // subCommand
|
||||||
writeShort(4) // count of TLVs
|
writeShort(
|
||||||
|
if (client.t547 == null) {
|
||||||
|
4
|
||||||
|
} else {
|
||||||
|
5
|
||||||
|
}
|
||||||
|
) // count of TLVs
|
||||||
t193(ticket)
|
t193(ticket)
|
||||||
t8(2052)
|
t8(2052)
|
||||||
t104(client.t104)
|
t104(client.t104)
|
||||||
t116(client.miscBitMap, client.subSigMap)
|
t116(client.miscBitMap, client.subSigMap)
|
||||||
|
client.t547?.let {
|
||||||
|
t547(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,11 +52,20 @@ internal object WtLogin2 : WtLoginExt {
|
|||||||
writeSsoPacket(client, client.subAppId, WtLogin.Login.commandName, sequenceId = sequenceId) {
|
writeSsoPacket(client, client.subAppId, WtLogin.Login.commandName, sequenceId = sequenceId) {
|
||||||
writeOicqRequestPacket(client, commandId = 0x0810) {
|
writeOicqRequestPacket(client, commandId = 0x0810) {
|
||||||
writeShort(2) // subCommand
|
writeShort(2) // subCommand
|
||||||
writeShort(4) // count of TLVs
|
writeShort(
|
||||||
|
if (client.t547 == null) {
|
||||||
|
4
|
||||||
|
} else {
|
||||||
|
5
|
||||||
|
}
|
||||||
|
) // count of TLVs
|
||||||
t2(captchaAnswer, captchaSign, 0)
|
t2(captchaAnswer, captchaSign, 0)
|
||||||
t8(2052)
|
t8(2052)
|
||||||
t104(client.t104)
|
t104(client.t104)
|
||||||
t116(client.miscBitMap, client.subSigMap)
|
t116(client.miscBitMap, client.subSigMap)
|
||||||
|
client.t547?.let {
|
||||||
|
t547(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.internal.network.protocol.packet.login.wtlogin
|
package net.mamoe.mirai.internal.network.protocol.packet.login.wtlogin
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.bignum.integer.BigInteger
|
||||||
|
import com.ionspin.kotlin.bignum.integer.util.fromTwosComplementByteArray
|
||||||
|
import com.ionspin.kotlin.bignum.integer.util.toTwosComplementByteArray
|
||||||
import io.ktor.utils.io.core.*
|
import io.ktor.utils.io.core.*
|
||||||
import net.mamoe.mirai.internal.QQAndroidBot
|
import net.mamoe.mirai.internal.QQAndroidBot
|
||||||
import net.mamoe.mirai.internal.network.LoginExtraData
|
import net.mamoe.mirai.internal.network.LoginExtraData
|
||||||
@ -171,6 +174,126 @@ internal interface WtLoginExt { // so as not to register to global extension
|
|||||||
this.t150 = Tlv(t150)
|
this.t150 = Tlv(t150)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun QQAndroidClient.analysisTlv546(t546: ByteArray) {
|
||||||
|
val version: Byte
|
||||||
|
val algorithmType: Byte
|
||||||
|
val hashType: Byte
|
||||||
|
val maxIndex: Short
|
||||||
|
val reserveBytes: ByteArray
|
||||||
|
val inputBigNumArr: ByteArray
|
||||||
|
val targetHashArr: ByteArray
|
||||||
|
val reserveHashArr: ByteArray
|
||||||
|
var resultArr: ByteArray = EMPTY_BYTE_ARRAY;
|
||||||
|
var costTimeMS: Int = 0;
|
||||||
|
var recursiveDepth: Int = 0;
|
||||||
|
var failed = false
|
||||||
|
|
||||||
|
fun getPadRemaining(bigNumArr: ByteArray, bound: Short): Int {
|
||||||
|
if (bound > 32) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
var maxLoopCount = 255
|
||||||
|
var index = 0
|
||||||
|
while (maxLoopCount >= 0 && index < bound) {
|
||||||
|
if (bigNumArr[maxLoopCount / 8].toInt() and (1 shl maxLoopCount) % 8 != 0) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
maxLoopCount--
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun calcType1(bigNumArrIn: ByteArray, maxLength: Short) {
|
||||||
|
var bigIntArrClone = bigNumArrIn.copyOf()
|
||||||
|
val originLength = bigIntArrClone.size
|
||||||
|
var bigInteger = BigInteger.fromTwosComplementByteArray(bigIntArrClone)
|
||||||
|
while (true) {
|
||||||
|
if (getPadRemaining(bigIntArrClone.sha256().copyOf(32), maxLength) == 0) {
|
||||||
|
resultArr = bigIntArrClone
|
||||||
|
return
|
||||||
|
}
|
||||||
|
recursiveDepth++
|
||||||
|
bigInteger = bigInteger.add(BigInteger.ONE)
|
||||||
|
bigIntArrClone = bigInteger.toTwosComplementByteArray()
|
||||||
|
if (bigIntArrClone.size > originLength) {
|
||||||
|
failed = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun calcType2(bigNumArrIn: ByteArray, hashTarget: ByteArray) {
|
||||||
|
var bigIntArrClone = bigNumArrIn.copyOf()
|
||||||
|
val originLength = bigIntArrClone.size
|
||||||
|
var bigInteger = BigInteger.fromTwosComplementByteArray(bigIntArrClone)
|
||||||
|
while (true) {
|
||||||
|
if (bigIntArrClone.sha256().copyOf(32).contentEquals(hashTarget)) {
|
||||||
|
resultArr = bigIntArrClone
|
||||||
|
return
|
||||||
|
}
|
||||||
|
recursiveDepth++
|
||||||
|
bigInteger = bigInteger.add(BigInteger.ONE)
|
||||||
|
bigIntArrClone = bigInteger.toTwosComplementByteArray()
|
||||||
|
if (bigIntArrClone.size > originLength) {
|
||||||
|
failed = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t546.toReadPacket().apply {
|
||||||
|
version = readByte()
|
||||||
|
algorithmType = readByte()
|
||||||
|
hashType = readByte()
|
||||||
|
readByte() // Ignore resultStatus since it's useless
|
||||||
|
maxIndex = readShort()
|
||||||
|
reserveBytes = readBytes(2)
|
||||||
|
inputBigNumArr = readBytes(readShort().toInt())
|
||||||
|
targetHashArr = readBytes(readShort().toInt())
|
||||||
|
reserveHashArr = readBytes(readShort().toInt())
|
||||||
|
}
|
||||||
|
val startTimeMS: Long = currentTimeMillis()
|
||||||
|
costTimeMS = 0
|
||||||
|
recursiveDepth = 0
|
||||||
|
if (hashType == 1.toByte()) {
|
||||||
|
bot.logger.info("Calculating type $algorithmType PoW, it can take some time....")
|
||||||
|
when (algorithmType.toInt()) {
|
||||||
|
1 -> calcType1(inputBigNumArr, maxIndex)
|
||||||
|
2 -> calcType2(inputBigNumArr, targetHashArr)
|
||||||
|
else -> {
|
||||||
|
failed = true
|
||||||
|
bot.logger.warning("Unsupported tlv546 algorithm type:${algorithmType}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
failed = true
|
||||||
|
bot.logger.warning("Unsupported tlv546 hash type:${hashType}")
|
||||||
|
}
|
||||||
|
if (!failed) {
|
||||||
|
costTimeMS = (currentTimeMillis() - startTimeMS).toInt()
|
||||||
|
bot.logger.info("Got PoW result, cost: $costTimeMS ms")
|
||||||
|
this.t547 = buildPacket {
|
||||||
|
writeByte(version)
|
||||||
|
writeByte(algorithmType)
|
||||||
|
writeByte(hashType)
|
||||||
|
writeByte(1) //resultStatus
|
||||||
|
writeShort(maxIndex)
|
||||||
|
writeFully(reserveBytes)
|
||||||
|
writeShortLVByteArray(inputBigNumArr)
|
||||||
|
writeShortLVByteArray(targetHashArr)
|
||||||
|
writeShortLVByteArray(reserveHashArr)
|
||||||
|
writeShortLVByteArray(resultArr)
|
||||||
|
writeInt(costTimeMS)
|
||||||
|
writeInt(recursiveDepth)
|
||||||
|
}.readBytes()
|
||||||
|
} else {
|
||||||
|
bot.logger.warning("Failed to get PoW result, login may fail with error 0x6!")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fun QQAndroidClient.analysisTlv161(t161: ByteArray) {
|
fun QQAndroidClient.analysisTlv161(t161: ByteArray) {
|
||||||
val tlv = t161.toReadPacket().apply { discardExact(2) }.withUse { _readTLVMap() }
|
val tlv = t161.toReadPacket().apply { discardExact(2) }.withUse { _readTLVMap() }
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ class CoreShadowRelocationTest : AbstractTest() {
|
|||||||
private const val KtorOkHttp = "io.ktor.client.engine.okhttp.OkHttp"
|
private const val KtorOkHttp = "io.ktor.client.engine.okhttp.OkHttp"
|
||||||
private const val OkHttp = "okhttp3.OkHttp"
|
private const val OkHttp = "okhttp3.OkHttp"
|
||||||
private const val OkIO = "okio.ByteString"
|
private const val OkIO = "okio.ByteString"
|
||||||
|
private const val BigInteger = "com.ionspin.kotlin.bignum.integer.BigInteger"
|
||||||
|
|
||||||
fun relocated(string: String): String {
|
fun relocated(string: String): String {
|
||||||
return "net.mamoe.mirai.internal.deps.$string"
|
return "net.mamoe.mirai.internal.deps.$string"
|
||||||
@ -38,6 +39,7 @@ class CoreShadowRelocationTest : AbstractTest() {
|
|||||||
-both(`ktor-client-okhttp`)
|
-both(`ktor-client-okhttp`)
|
||||||
-both(`okhttp3-okhttp`)
|
-both(`okhttp3-okhttp`)
|
||||||
-both(okio)
|
-both(okio)
|
||||||
|
-both(`kt-bignum`)
|
||||||
}
|
}
|
||||||
applyCodeFragment(fragment)
|
applyCodeFragment(fragment)
|
||||||
buildFile.appendText(
|
buildFile.appendText(
|
||||||
@ -59,6 +61,7 @@ class CoreShadowRelocationTest : AbstractTest() {
|
|||||||
-both(`ktor-client-okhttp`)
|
-both(`ktor-client-okhttp`)
|
||||||
-both(`okhttp3-okhttp`)
|
-both(`okhttp3-okhttp`)
|
||||||
-both(okio)
|
-both(okio)
|
||||||
|
-both(`kt-bignum`)
|
||||||
+relocated(`ExternalResource-input`)
|
+relocated(`ExternalResource-input`)
|
||||||
}
|
}
|
||||||
applyCodeFragment(fragment)
|
applyCodeFragment(fragment)
|
||||||
@ -82,6 +85,7 @@ class CoreShadowRelocationTest : AbstractTest() {
|
|||||||
+relocated(`okhttp3-okhttp`)
|
+relocated(`okhttp3-okhttp`)
|
||||||
+relocated(okio)
|
+relocated(okio)
|
||||||
+relocated(`ExternalResource-input`)
|
+relocated(`ExternalResource-input`)
|
||||||
|
+relocated(`kt-bignum`)
|
||||||
}
|
}
|
||||||
applyCodeFragment(fragment)
|
applyCodeFragment(fragment)
|
||||||
buildFile.appendText(
|
buildFile.appendText(
|
||||||
@ -106,6 +110,7 @@ class CoreShadowRelocationTest : AbstractTest() {
|
|||||||
+relocated(`ktor-client-okhttp`)
|
+relocated(`ktor-client-okhttp`)
|
||||||
+relocated(`okhttp3-okhttp`)
|
+relocated(`okhttp3-okhttp`)
|
||||||
+relocated(okio)
|
+relocated(okio)
|
||||||
|
+relocated(`kt-bignum`)
|
||||||
}
|
}
|
||||||
applyCodeFragment(fragment)
|
applyCodeFragment(fragment)
|
||||||
buildFile.appendText(
|
buildFile.appendText(
|
||||||
@ -130,6 +135,7 @@ class CoreShadowRelocationTest : AbstractTest() {
|
|||||||
-both(`ktor-client-okhttp`)
|
-both(`ktor-client-okhttp`)
|
||||||
-both(`okhttp3-okhttp`)
|
-both(`okhttp3-okhttp`)
|
||||||
-both(okio)
|
-both(okio)
|
||||||
|
-both(`kt-bignum`)
|
||||||
// +relocated(`ExternalResource-input`) // Will fail with no class def found error because there is no runtime ktor-io
|
// +relocated(`ExternalResource-input`) // Will fail with no class def found error because there is no runtime ktor-io
|
||||||
}
|
}
|
||||||
applyCodeFragment(fragment)
|
applyCodeFragment(fragment)
|
||||||
@ -155,6 +161,7 @@ class CoreShadowRelocationTest : AbstractTest() {
|
|||||||
+relocated(`okhttp3-okhttp`)
|
+relocated(`okhttp3-okhttp`)
|
||||||
+relocated(okio)
|
+relocated(okio)
|
||||||
+relocated(`ExternalResource-input`)
|
+relocated(`ExternalResource-input`)
|
||||||
|
+relocated(`kt-bignum`)
|
||||||
}
|
}
|
||||||
applyCodeFragment(fragment)
|
applyCodeFragment(fragment)
|
||||||
|
|
||||||
@ -231,6 +238,7 @@ class CoreShadowRelocationTest : AbstractTest() {
|
|||||||
val `ktor-client-okhttp` = ClassTestCase("ktor-client-core OkHttp", KtorOkHttp)
|
val `ktor-client-okhttp` = ClassTestCase("ktor-client-core OkHttp", KtorOkHttp)
|
||||||
val `okhttp3-okhttp` = ClassTestCase("okhttp3 OkHttp", OkHttp)
|
val `okhttp3-okhttp` = ClassTestCase("okhttp3 OkHttp", OkHttp)
|
||||||
val okio = ClassTestCase("okio ByteString", OkIO)
|
val okio = ClassTestCase("okio ByteString", OkIO)
|
||||||
|
val `kt-bignum` = ClassTestCase("kt-bignum BigInteger", BigInteger)
|
||||||
val `ExternalResource-input` =
|
val `ExternalResource-input` =
|
||||||
FunctionTestCase(
|
FunctionTestCase(
|
||||||
"ExternalResource_input",
|
"ExternalResource_input",
|
||||||
|
Loading…
Reference in New Issue
Block a user