mirror of
https://github.com/Mrs4s/MiraiGo.git
synced 2025-05-05 03:23:50 +08:00
mostly auto-generated by ``` rf ' ex { var c QQClient var seq uint16 var payload []byte var command string BuildUniPacket(c.Uin, seq, command, 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) -> c.uniPacket(seq, command, payload) } ' ```
108 lines
2.3 KiB
Go
108 lines
2.3 KiB
Go
package crypto
|
|
|
|
import (
|
|
"crypto/elliptic"
|
|
"crypto/md5"
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/Mrs4s/MiraiGo/binary"
|
|
)
|
|
|
|
type EncryptECDH struct {
|
|
InitialShareKey []byte
|
|
PublicKey []byte
|
|
PublicKeyVer uint16
|
|
}
|
|
|
|
type EncryptSession struct {
|
|
T133 []byte
|
|
}
|
|
|
|
const serverPublicKey = "04EBCA94D733E399B2DB96EACDD3F69A8BB0F74224E2B44E3357812211D2E62EFBC91BB553098E25E33A799ADC7F76FEB208DA7C6522CDB0719A305180CC54A82E"
|
|
|
|
func NewEcdh() *EncryptECDH {
|
|
e := &EncryptECDH{
|
|
PublicKeyVer: 1,
|
|
}
|
|
e.generateKey(serverPublicKey)
|
|
return e
|
|
}
|
|
|
|
func (e *EncryptECDH) generateKey(sPubKey string) {
|
|
pub, err := hex.DecodeString(sPubKey)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
p256 := elliptic.P256()
|
|
key, sx, sy, err := elliptic.GenerateKey(p256, rand.Reader)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
tx, ty := elliptic.Unmarshal(p256, pub)
|
|
x, _ := p256.ScalarMult(tx, ty, key)
|
|
hash := md5.Sum(x.Bytes()[:16])
|
|
e.InitialShareKey = hash[:]
|
|
e.PublicKey = elliptic.Marshal(p256, sx, sy)
|
|
}
|
|
|
|
func (e *EncryptECDH) Encrypt(d, k []byte) []byte {
|
|
w := binary.SelectWriter()
|
|
w.WriteByte(0x02)
|
|
w.WriteByte(0x01)
|
|
w.Write(k)
|
|
w.WriteUInt16(0x01_31)
|
|
w.WriteUInt16(e.PublicKeyVer)
|
|
w.WriteUInt16(uint16(len(e.PublicKey)))
|
|
w.Write(e.PublicKey)
|
|
w.EncryptAndWrite(e.InitialShareKey, d)
|
|
return w.Bytes()
|
|
}
|
|
|
|
func (e *EncryptECDH) ID() byte {
|
|
return 0x87
|
|
}
|
|
|
|
func NewEncryptSession(t133 []byte) *EncryptSession {
|
|
return &EncryptSession{T133: t133}
|
|
}
|
|
|
|
func (e *EncryptSession) Encrypt(d, k []byte) []byte {
|
|
return binary.NewWriterF(func(w *binary.Writer) {
|
|
encrypt := binary.NewTeaCipher(k).Encrypt(d)
|
|
w.WriteUInt16(uint16(len(e.T133)))
|
|
w.Write(e.T133)
|
|
w.Write(encrypt)
|
|
})
|
|
}
|
|
|
|
func (e *EncryptSession) ID() byte {
|
|
return 69
|
|
}
|
|
|
|
type pubKeyResp struct {
|
|
Meta struct {
|
|
PubKeyVer uint16 `json:"KeyVer"`
|
|
PubKey string `json:"PubKey"`
|
|
} `json:"PubKeyMeta"`
|
|
}
|
|
|
|
// FetchPubKey 从服务器获取PubKey
|
|
func (e *EncryptECDH) FetchPubKey(uin int64) {
|
|
resp, err := http.Get("https://keyrotate.qq.com/rotate_key?cipher_suite_ver=305&uin=" + strconv.FormatInt(uin, 10))
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer func() { _ = resp.Body.Close() }()
|
|
pubKey := pubKeyResp{}
|
|
err = json.NewDecoder(resp.Body).Decode(&pubKey)
|
|
if err != nil {
|
|
return
|
|
}
|
|
e.PublicKeyVer = pubKey.Meta.PubKeyVer
|
|
e.generateKey(pubKey.Meta.PubKey) // todo check key sign
|
|
}
|