mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-10 04:00:08 +08:00
Add docs
This commit is contained in:
parent
e2f59416f0
commit
2f2a8666b9
@ -177,7 +177,8 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理从服务器接收过来的包. 这些包可能是粘在一起的, 也可能是不完整的. 将会自动处理
|
||||
* 处理从服务器接收过来的包. 这些包可能是粘在一起的, 也可能是不完整的. 将会自动处理.
|
||||
* 处理后的包会调用 [parsePacketAsync]
|
||||
*/
|
||||
@UseExperimental(ExperimentalCoroutinesApi::class)
|
||||
internal fun processPacket(rawInput: ByteReadPacket): Unit = rawInput.debugPrint("Received").let { input: ByteReadPacket ->
|
||||
|
@ -53,7 +53,7 @@ internal open class QQAndroidClient(
|
||||
"tgtgtKey" to tgtgtKey,
|
||||
"tgtKey" to wLoginSigInfo.tgtKey,
|
||||
"deviceToken" to wLoginSigInfo.deviceToken,
|
||||
"shareKeyCalculatedByConstPubKey" to ecdh.keyPair.shareKey
|
||||
"shareKeyCalculatedByConstPubKey" to ecdh.keyPair.initialShareKey
|
||||
//"t108" to wLoginSigInfo.t1,
|
||||
//"t10c" to t10c,
|
||||
//"t163" to t163
|
||||
|
@ -95,6 +95,6 @@ internal interface EncryptMethodECDH : EncryptMethod {
|
||||
})
|
||||
|
||||
// encryptAndWrite("26 33 BA EC 86 EB 79 E6 BC E0 20 06 5E A9 56 6C".hexToBytes(), body)
|
||||
encryptAndWrite(ecdh.keyPair.shareKey, body)
|
||||
encryptAndWrite(ecdh.keyPair.initialShareKey, body)
|
||||
}
|
||||
}
|
@ -111,7 +111,7 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
|
||||
// 解析外层包装
|
||||
when (flag1) {
|
||||
0x0A -> parseSsoFrame(bot, decryptedData)
|
||||
0x0B -> parseUniFrame(bot, decryptedData)
|
||||
0x0B -> parseSsoFrame(bot, decryptedData) // 这里可能是 uni?? 但测试时候发现结构跟 sso 一样.
|
||||
else -> error("unknown flag1: ${flag1.toByte().toUHexString()}")
|
||||
}
|
||||
}?.let {
|
||||
@ -214,7 +214,7 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
|
||||
this.discardExact(1) // const = 0
|
||||
val packet = when (encryptionMethod) {
|
||||
4 -> { // peer public key, ECDH
|
||||
var data = this.decryptBy(bot.client.ecdh.keyPair.shareKey, this.readRemaining - 1)
|
||||
var data = this.decryptBy(bot.client.ecdh.keyPair.initialShareKey, this.readRemaining - 1)
|
||||
|
||||
val peerShareKey = bot.client.ecdh.calculateShareKeyByPeerPublicKey(readUShortLVByteArray().adjustToPublicKey())
|
||||
data = data.decryptBy(peerShareKey)
|
||||
@ -228,7 +228,7 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
|
||||
this.readFully(byteArrayBuffer, 0, size)
|
||||
|
||||
runCatching {
|
||||
byteArrayBuffer.decryptBy(bot.client.ecdh.keyPair.shareKey, size)
|
||||
byteArrayBuffer.decryptBy(bot.client.ecdh.keyPair.initialShareKey, size)
|
||||
}.getOrElse {
|
||||
byteArrayBuffer.decryptBy(bot.client.randomKey, size)
|
||||
} // 这里实际上应该用 privateKey(另一个random出来的key)
|
||||
|
@ -7,9 +7,9 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketLogger
|
||||
import net.mamoe.mirai.utils.cryptor.*
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
import net.mamoe.mirai.utils.io.discardExact
|
||||
import net.mamoe.mirai.utils.md5
|
||||
import kotlin.text.toByteArray
|
||||
|
||||
|
||||
// sessionTicket = 55 F7 24 8B 04 4E AA A8 98 E6 77 D2 D6 54 A9 B4 43 91 94 A3 0D DA CF 8F E8 94 E0 F4 A2 6B B4 8B 2B 4F 78 8D 21 EE D4 95 A6 F7 A4 3D B5 87 9B 3D
|
||||
// sessionTicketKey = B6 9D E4 EC 65 38 64 FD C8 3A D8 33 54 35 0C 73
|
||||
// randomKey = A4 9A 6A EE 17 5B 7E 3D C0 71 DA 04 1C E1 E4 88
|
||||
@ -239,13 +239,12 @@ fun ByteReadPacket.analysisOneFullPacket(): ByteReadPacket = debugIfFail("Failed
|
||||
discardExact(4)
|
||||
readTLVMap()[0x106]
|
||||
?.also { DebugLogger.info("找到了 0x106") }
|
||||
?.decryptBy(passwordMd5 + ByteArray(4) + uin.toInt().toByteArray())
|
||||
?.decryptBy(md5(passwordMd5 + ByteArray(4) + uin.toInt().toByteArray()))
|
||||
?.read {
|
||||
discardExact(2 + 4 * 4 + 8 + 4 + 4 + 1 + 16)
|
||||
tgtgtKey = readBytes(16)
|
||||
DebugLogger.info("获取 tgtgtKey=${tgtgtKey.toUHexString()}")
|
||||
}
|
||||
DebugLogger.info("tlv map里面没有 0x106")
|
||||
} ?: DebugLogger.info("找不到 0x106")
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
@ -269,9 +268,9 @@ fun ByteReadPacket.decodeUni() {
|
||||
// 00 00 00 5B 10 03 2C 3C 4C 56 23 51 51 53 65 72 76 69 63 65 2E 43 6F 6E 66 69 67 50 75 73 68 53 76 63 2E 4D 61 69 6E 53 65 72 76 61 6E 74 66 08 50 75 73 68 52 65 73 70 7D 00 00 1A 08 00 01 06 08 50 75 73 68 52 65 73 70 1D 00 00 09 0A 10 01 22 14 DA 6E B1 0B 8C 98 0C A8 0C
|
||||
println("// 尝试解 Uni")
|
||||
println("// head")
|
||||
return
|
||||
//return
|
||||
readBytes(readInt() - 4).debugPrint("head").toReadPacket().apply {
|
||||
val commandName = readString(readInt() - 4).also { println("commandName=$it") }
|
||||
val commandName = readString(readInt() - 4).also { PacketLogger.warning("commandName=$it") }
|
||||
println(commandName)
|
||||
println(" unknown4Bytes=" + readBytes(readInt() - 4).toUHexString())
|
||||
// 00 00 00 1A 43 6F 6E 66 69 67 50 75 73 68 53 76 63 2E 50 75 73 68 52 65 73 70
|
||||
|
File diff suppressed because one or more lines are too long
@ -15,7 +15,7 @@ actual class ECDHKeyPair(
|
||||
actual val privateKey: ECDHPrivateKey get() = delegate.private
|
||||
actual val publicKey: ECDHPublicKey get() = delegate.public
|
||||
|
||||
actual val shareKey: ByteArray = ECDH.calculateShareKey(privateKey, initialPublicKey)
|
||||
actual val initialShareKey: ByteArray = ECDH.calculateShareKey(privateKey, initialPublicKey)
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
|
@ -8,14 +8,14 @@ import net.mamoe.mirai.utils.coerceAtLeastOrFail
|
||||
|
||||
|
||||
/**
|
||||
* 群.
|
||||
* 群. 在 QQ Android 中叫做 "Troop"
|
||||
*
|
||||
* Group ID 与 Group Number 并不是同一个值.
|
||||
* - Group Number([Group.id]) 是通常使用的群号码.(在 QQ 客户端中可见)
|
||||
* - Group ID([Group.internalId]) 是与调用 API 时使用的 id.(在 QQ 客户端中不可见)
|
||||
* @author Him188moe
|
||||
*/
|
||||
interface Group : Contact, CoroutineScope/*, Map<UInt, Member>*/ { // TODO: 2019/12/4 在 inline 稳定后实现 Map<UInt, Member>. 目前这样做会导致问题
|
||||
interface Group : Contact, CoroutineScope/*, Map<UInt, Member>*/ { // TODO: 2020/1/29 实现接口 Map<Long, Memebr>
|
||||
/**
|
||||
* 内部 ID. 内部 ID 为 [GroupId] 的映射
|
||||
*/
|
||||
@ -86,7 +86,10 @@ fun Long.groupInternalId(): GroupInternalId = GroupInternalId(this)
|
||||
/**
|
||||
* 将无符号整数格式的 [Long] 转为 [GroupId].
|
||||
*
|
||||
* 注: 在 Java 中常用 [Long] 来表示 [UInt]
|
||||
* 注: 在 Java 中常用 [Long] 来表示 [UInt].
|
||||
*
|
||||
* 注: 在 Kotlin/Java, 有符号的数据类型的二进制最高位为符号标志.
|
||||
* 如一个 byte, `1000 0000` 最高位为 1, 则为负数.
|
||||
*/
|
||||
fun Long.groupId(): GroupId = GroupId(this.coerceAtLeastOrFail(0))
|
||||
|
||||
|
@ -15,23 +15,46 @@ expect class ECDHKeyPair {
|
||||
val privateKey: ECDHPrivateKey
|
||||
val publicKey: ECDHPublicKey
|
||||
|
||||
val shareKey: ByteArray
|
||||
/**
|
||||
* 私匙和固定公匙([initialPublicKey]) 计算得到的 shareKey
|
||||
*/
|
||||
val initialShareKey: ByteArray
|
||||
}
|
||||
|
||||
/**
|
||||
* 椭圆曲线密码, ECDH 加密
|
||||
*/
|
||||
expect class ECDH(keyPair: ECDHKeyPair) {
|
||||
val keyPair: ECDHKeyPair
|
||||
|
||||
/**
|
||||
* 由 [keyPair] 的私匙和 [peerPublicKey] 计算 shareKey
|
||||
*/
|
||||
fun calculateShareKeyByPeerPublicKey(peerPublicKey: ECDHPublicKey): ByteArray
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* 由完整的 publicKey ByteArray 得到 [ECDHPublicKey]
|
||||
*/
|
||||
fun constructPublicKey(key: ByteArray): ECDHPublicKey
|
||||
|
||||
/**
|
||||
* 生成随机密匙对
|
||||
*/
|
||||
fun generateKeyPair(): ECDHKeyPair
|
||||
|
||||
/**
|
||||
* 由一对密匙计算 shareKey
|
||||
*/
|
||||
fun calculateShareKey(privateKey: ECDHPrivateKey, publicKey: ECDHPublicKey): ByteArray
|
||||
}
|
||||
|
||||
override fun toString(): String
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
expect fun ECDH(): ECDH
|
||||
|
||||
|
@ -17,7 +17,7 @@ actual class ECDHKeyPair(
|
||||
actual val privateKey: ECDHPrivateKey get() = delegate.private
|
||||
actual val publicKey: ECDHPublicKey get() = delegate.public
|
||||
|
||||
actual val shareKey: ByteArray = ECDH.calculateShareKey(privateKey, initialPublicKey)
|
||||
actual val initialShareKey: ByteArray = ECDH.calculateShareKey(privateKey, initialPublicKey)
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
|
Loading…
Reference in New Issue
Block a user