Skip to content

Commit cc7f355

Browse files
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
1 parent 56dea84 commit cc7f355

File tree

14 files changed

+273
-5
lines changed

14 files changed

+273
-5
lines changed

buildSrc/src/main/kotlin/Versions.kt

+3
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,9 @@ const val `netty-transport` = "io.netty:netty-transport:${Versions.netty}"
267267
const val `netty-buffer` = "io.netty:netty-buffer:${Versions.netty}"
268268
const val `bouncycastle` = "org.bouncycastle:bcprov-jdk15on:${Versions.bouncycastle}"
269269

270+
const val `kt-bignum` = "com.ionspin.kotlin:bignum:0.3.7"
271+
val `kt-bignum_relocated` = RelocatedDependency(`kt-bignum`, "com.ionspin.kotlin.bignum")
272+
270273
const val `maven-resolver-api` = "org.apache.maven.resolver:maven-resolver-api:${Versions.mavenArtifactResolver}"
271274
const val `maven-resolver-impl` = "org.apache.maven.resolver:maven-resolver-impl:${Versions.mavenArtifactResolver}"
272275
const val `maven-resolver-connector-basic` =

mirai-core-all/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ dependencies {
2525
api(project(":mirai-core-utils"))
2626
implementation(`slf4j-api`) // Required by mirai-console
2727

28+
relocateImplementation(project, `kt-bignum_relocated`)
2829
relocateImplementation(project, `ktor-client-core_relocated`)
2930
relocateImplementation(project, `ktor-client-okhttp_relocated`)
3031
relocateImplementation(project, `ktor-io_relocated`)

mirai-core-utils/src/commonMain/kotlin/ByteArrayOp.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ public fun String.sha1(): ByteArray = toByteArray().sha1()
2424

2525
public expect fun ByteArray.sha1(offset: Int = 0, length: Int = size - offset): ByteArray
2626

27+
public fun String.sha256(): ByteArray = toByteArray().sha256()
28+
29+
public expect fun ByteArray.sha256(offset: Int = 0, length: Int = size - offset): ByteArray
2730

2831
///////////////////////////////////////////////////////////////////////////
2932
// How to choose 'inflate', 'inflateAllAvailable', 'InflateInput'?
@@ -112,4 +115,4 @@ public expect fun DeflateInput(source: Input): Input
112115
/**
113116
* @see DeflateInput
114117
*/
115-
public fun Input.deflateInput(): Input = DeflateInput(this)
118+
public fun Input.deflateInput(): Input = DeflateInput(this)

mirai-core-utils/src/jvmBaseMain/kotlin/ByteArrayOp.kt

+11-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
package net.mamoe.mirai.utils
1414

1515
import io.ktor.utils.io.core.*
16-
import io.ktor.utils.io.streams.asInput
16+
import io.ktor.utils.io.streams.*
1717
import java.io.ByteArrayInputStream
1818
import java.io.ByteArrayOutputStream
1919
import java.io.InputStream
@@ -50,6 +50,10 @@ public fun InputStream.sha1(): ByteArray {
5050
return digest("SHA-1")
5151
}
5252

53+
public fun InputStream.sha256(): ByteArray {
54+
return digest("SHA-256")
55+
}
56+
5357
public actual fun ByteArray.md5(offset: Int, length: Int): ByteArray {
5458
checkOffsetAndLength(offset, length)
5559
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 {
6266
return MessageDigest.getInstance("SHA-1").apply { update(this@sha1, offset, length) }.digest()
6367
}
6468

69+
@JvmOverloads
70+
public actual fun ByteArray.sha256(offset: Int, length: Int): ByteArray {
71+
checkOffsetAndLength(offset, length)
72+
return MessageDigest.getInstance("SHA-256").apply { update(this@sha256, offset, length) }.digest()
73+
}
74+
6575
@JvmOverloads
6676
public actual fun ByteArray.gzip(offset: Int, length: Int): ByteArray {
6777
ByteArrayOutputStream().use { buf ->

mirai-core-utils/src/nativeMain/kotlin/ByteArrayOp.kt

+5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ public actual fun ByteArray.sha1(offset: Int, length: Int): ByteArray = SHA1.cre
3131
return digest().bytes
3232
}
3333

34+
public actual fun ByteArray.sha256(offset: Int, length: Int): ByteArray = SHA256.create().run {
35+
update(this@sha256, offset, length)
36+
return digest().bytes
37+
}
38+
3439
/**
3540
* WARNING: DO NOT SET THIS BUFFER TOO SMALL, OR YOU WILL SEE COMPRESSION ERROR.
3641
*/

mirai-core-utils/src/nativeMain/kotlin/CommonDigest.kt

+76
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,79 @@ internal class SHA1 : SHA(chunkSize = 64, digestSize = 20) {
272272
for (n in out.indices) out[n] = (h[n / 4] ushr (24 - 8 * (n % 4))).toByte()
273273
}
274274
}
275+
276+
internal class SHA256 : SHA(chunkSize = 64, digestSize = 32) {
277+
companion object : HasherFactory({ SHA256() }) {
278+
private val H = intArrayOf(
279+
0x6a09e667, -0x4498517b, 0x3c6ef372, -0x5ab00ac6,
280+
0x510e527f, -0x64fa9774, 0x1f83d9ab, 0x5be0cd19
281+
)
282+
283+
private val K = intArrayOf(
284+
0x428a2f98, 0x71374491, -0x4a3f0431, -0x164a245b,
285+
0x3956c25b, 0x59f111f1, -0x6dc07d5c, -0x54e3a12b,
286+
-0x27f85568, 0x12835b01, 0x243185be, 0x550c7dc3,
287+
0x72be5d74, -0x7f214e02, -0x6423f959, -0x3e640e8c,
288+
-0x1b64963f, -0x1041b87a, 0x0fc19dc6, 0x240ca1cc,
289+
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
290+
-0x67c1aeae, -0x57ce3993, -0x4ffcd838, -0x40a68039,
291+
-0x391ff40d, -0x2a586eb9, 0x06ca6351, 0x14292967,
292+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
293+
0x650a7354, 0x766a0abb, -0x7e3d36d2, -0x6d8dd37b,
294+
-0x5d40175f, -0x57e599b5, -0x3db47490, -0x3893ae5d,
295+
-0x2e6d17e7, -0x2966f9dc, -0xbf1ca7b, 0x106aa070,
296+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
297+
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
298+
0x748f82ee, 0x78a5636f, -0x7b3787ec, -0x7338fdf8,
299+
-0x6f410006, -0x5baf9315, -0x41065c09, -0x398e870e
300+
)
301+
}
302+
303+
304+
private val h = IntArray(8)
305+
private val r = IntArray(8)
306+
private val w = IntArray(64)
307+
308+
init {
309+
coreReset()
310+
}
311+
312+
override fun coreReset() {
313+
arraycopy(H, 0, h, 0, 8)
314+
}
315+
316+
override fun coreUpdate(chunk: ByteArray) {
317+
arraycopy(h, 0, r, 0, 8)
318+
319+
for (j in 0 until 16) w[j] = chunk.readS32_be(j * 4)
320+
for (j in 16 until 64) {
321+
val s0 = w[j - 15].rotateRight(7) xor w[j - 15].rotateRight(18) xor w[j - 15].ushr(3)
322+
val s1 = w[j - 2].rotateRight(17) xor w[j - 2].rotateRight(19) xor w[j - 2].ushr(10)
323+
w[j] = w[j - 16] + s0 + w[j - 7] + s1
324+
}
325+
326+
for (j in 0 until 64) {
327+
val s1 = r[4].rotateRight(6) xor r[4].rotateRight(11) xor r[4].rotateRight(25)
328+
val ch = r[4] and r[5] xor (r[4].inv() and r[6])
329+
val t1 = r[7] + s1 + ch + K[j] + w[j]
330+
val s0 = r[0].rotateRight(2) xor r[0].rotateRight(13) xor r[0].rotateRight(22)
331+
val maj = r[0] and r[1] xor (r[0] and r[2]) xor (r[1] and r[2])
332+
val t2 = s0 + maj
333+
r[7] = r[6]
334+
r[6] = r[5]
335+
r[5] = r[4]
336+
r[4] = r[3] + t1
337+
r[3] = r[2]
338+
r[2] = r[1]
339+
r[1] = r[0]
340+
r[0] = t1 + t2
341+
342+
}
343+
for (j in 0 until 8) h[j] += r[j]
344+
}
345+
346+
override fun coreDigest(out: ByteArray) {
347+
for (n in out.indices) out[n] = (h[n / 4] ushr (24 - 8 * (n % 4))).toByte()
348+
}
349+
}
350+

mirai-core/build.gradle.kts

+9
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ kotlin {
4141
api(`kotlinx-serialization-json`)
4242
api(`kotlinx-coroutines-core`)
4343

44+
implementation(`kt-bignum`)
4445
implementation(project(":mirai-core-utils"))
4546
implementation(`kotlinx-serialization-protobuf`)
4647
implementation(`kotlinx-atomicfu`)
@@ -108,6 +109,14 @@ kotlin {
108109
}
109110

110111

112+
// Kt bignum
113+
findByName("jvmBaseMain")?.apply {
114+
dependencies {
115+
relocateImplementation(`kt-bignum_relocated`)
116+
}
117+
}
118+
119+
111120
// Ktor
112121

113122
findByName("commonMain")?.apply {

mirai-core/src/commonMain/kotlin/network/QQAndroidClient.kt

+1
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ internal open class QQAndroidClient(
166166
var reserveUinInfo: ReserveUinInfo? = null
167167
var t402: ByteArray? = null
168168
lateinit var t104: ByteArray
169+
var t547: ByteArray? = null
169170
}
170171

171172
internal val QQAndroidClient.apkId: ByteArray get() = "com.tencent.mobileqq".toByteArray()

mirai-core/src/commonMain/kotlin/network/protocol/packet/Tlv.kt

+9
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,15 @@ internal fun BytePacketBuilder.t104(
275275
}
276276
}
277277

278+
internal fun BytePacketBuilder.t547(
279+
t547Data: ByteArray
280+
) {
281+
writeShort(0x547)
282+
writeShortLVPacket {
283+
writeFully(t547Data)
284+
}
285+
}
286+
278287
internal fun BytePacketBuilder.t174(
279288
t174Data: ByteArray
280289
) {

mirai-core/src/commonMain/kotlin/network/protocol/packet/login/WtLogin.kt

+1
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ internal class WtLogin {
210210
tlvMap[0x161]?.let { bot.client.analysisTlv161(it) }
211211
tlvMap[0x403]?.let { bot.client.randSeed = it }
212212
tlvMap[0x402]?.let { bot.client.t402 = it }
213+
tlvMap[0x546]?.let { bot.client.analysisTlv546(it) }
213214
// tlvMap[0x402]?.let { t402 ->
214215
// bot.client.G = buildPacket {
215216
// writeFully(bot.client.device.guid)

mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin10.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ internal object WtLogin10 : WtLoginExt {
4343
0x0810
4444
) {
4545
writeShort(11) // subCommand
46-
writeShort(17)
46+
writeShort(18)
4747
t100(appId, subAppId, client.appClientVersion, client.ssoVersion, mainSigMap)
4848
t10a(client.wLoginSigInfo.tgt)
4949
t116(client.miscBitMap, client.subSigMap)
@@ -80,6 +80,7 @@ internal object WtLogin10 : WtLoginExt {
8080
t188(client.device.androidId)
8181
t194(client.device.imsiMd5)
8282
t511()
83+
t202(client.device.wifiBSSID, client.device.wifiSSID)
8384
//t544()
8485

8586
}

mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin2.kt

+20-2
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,20 @@ internal object WtLogin2 : WtLoginExt {
2626
writeSsoPacket(client, client.subAppId, WtLogin.Login.commandName, sequenceId = sequenceId) {
2727
writeOicqRequestPacket(client, commandId = 0x0810) {
2828
writeShort(2) // subCommand
29-
writeShort(4) // count of TLVs
29+
writeShort(
30+
if (client.t547 == null) {
31+
4
32+
} else {
33+
5
34+
}
35+
) // count of TLVs
3036
t193(ticket)
3137
t8(2052)
3238
t104(client.t104)
3339
t116(client.miscBitMap, client.subSigMap)
40+
client.t547?.let {
41+
t547(it)
42+
}
3443
}
3544
}
3645
}
@@ -43,11 +52,20 @@ internal object WtLogin2 : WtLoginExt {
4352
writeSsoPacket(client, client.subAppId, WtLogin.Login.commandName, sequenceId = sequenceId) {
4453
writeOicqRequestPacket(client, commandId = 0x0810) {
4554
writeShort(2) // subCommand
46-
writeShort(4) // count of TLVs
55+
writeShort(
56+
if (client.t547 == null) {
57+
4
58+
} else {
59+
5
60+
}
61+
) // count of TLVs
4762
t2(captchaAnswer, captchaSign, 0)
4863
t8(2052)
4964
t104(client.t104)
5065
t116(client.miscBitMap, client.subSigMap)
66+
client.t547?.let {
67+
t547(it)
68+
}
5169
}
5270
}
5371
}

0 commit comments

Comments
 (0)