github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/client/internal/oicq/oicq.go (about) 1 package oicq 2 3 import ( 4 "crypto/rand" 5 goBinary "encoding/binary" 6 7 "github.com/pkg/errors" 8 9 "github.com/Mrs4s/MiraiGo/binary" 10 ) 11 12 type Codec struct { 13 ecdh *session 14 randomKey []byte 15 16 WtSessionTicketKey []byte 17 } 18 19 func NewCodec(uin int64) *Codec { 20 c := &Codec{ 21 ecdh: newSession(), 22 randomKey: make([]byte, 16), 23 } 24 rand.Read(c.randomKey) 25 c.ecdh.fetchPubKey(uin) 26 return c 27 } 28 29 type EncryptionMethod byte 30 31 const ( 32 EM_ECDH EncryptionMethod = iota 33 EM_ST 34 ) 35 36 type Message struct { 37 Uin uint32 38 Command uint16 39 EncryptionMethod EncryptionMethod 40 Body []byte 41 } 42 43 func (c *Codec) Marshal(m *Message) []byte { 44 w := binary.SelectWriter() 45 defer binary.PutWriter(w) 46 47 w.WriteByte(0x02) 48 w.WriteUInt16(0) // len 占位 49 w.WriteUInt16(8001) // version? 50 w.WriteUInt16(m.Command) 51 w.WriteUInt16(1) 52 w.WriteUInt32(m.Uin) 53 w.WriteByte(0x03) 54 switch m.EncryptionMethod { 55 case EM_ECDH: 56 w.WriteByte(0x87) 57 case EM_ST: 58 w.WriteByte(0x45) 59 } 60 w.WriteByte(0) 61 w.WriteUInt32(2) 62 w.WriteUInt32(0) 63 w.WriteUInt32(0) 64 65 switch m.EncryptionMethod { 66 case EM_ECDH: 67 w.WriteByte(0x02) 68 w.WriteByte(0x01) 69 w.Write(c.randomKey) 70 w.WriteUInt16(0x01_31) 71 w.WriteUInt16(c.ecdh.SvrPublicKeyVer) 72 w.WriteUInt16(uint16(len(c.ecdh.PublicKey))) 73 w.Write(c.ecdh.PublicKey) 74 w.EncryptAndWrite(c.ecdh.ShareKey, m.Body) 75 76 case EM_ST: 77 w.WriteByte(0x01) 78 w.WriteByte(0x03) 79 w.Write(c.randomKey) 80 w.WriteUInt16(0x0102) 81 w.WriteUInt16(0x0000) 82 w.EncryptAndWrite(c.randomKey, m.Body) 83 } 84 w.WriteByte(0x03) 85 86 buf := make([]byte, len(w.Bytes())) 87 copy(buf, w.Bytes()) 88 goBinary.BigEndian.PutUint16(buf[1:3], uint16(len(buf))) 89 return buf 90 } 91 92 var ( 93 ErrUnknownFlag = errors.New("unknown flag") 94 ErrUnknownEncryptType = errors.New("unknown encrypt type") 95 ) 96 97 func (c *Codec) Unmarshal(data []byte) (*Message, error) { 98 reader := binary.NewReader(data) 99 if flag := reader.ReadByte(); flag != 2 { 100 return nil, ErrUnknownFlag 101 } 102 m := new(Message) 103 reader.ReadUInt16() // len 104 reader.ReadUInt16() // version? 105 m.Command = reader.ReadUInt16() 106 reader.ReadUInt16() // 1? 107 m.Uin = uint32(reader.ReadInt32()) 108 reader.ReadByte() 109 encryptType := reader.ReadByte() 110 reader.ReadByte() 111 switch encryptType { 112 case 0: 113 d := reader.ReadBytes(reader.Len() - 1) 114 defer func() { 115 if pan := recover(); pan != nil { 116 m.Body = binary.NewTeaCipher(c.randomKey).Decrypt(d) 117 } 118 }() 119 m.Body = binary.NewTeaCipher(c.ecdh.ShareKey).Decrypt(d) 120 case 3: 121 d := reader.ReadBytes(reader.Len() - 1) 122 m.Body = binary.NewTeaCipher(c.WtSessionTicketKey).Decrypt(d) 123 default: 124 return nil, ErrUnknownEncryptType 125 } 126 return m, nil 127 } 128 129 type TLV struct { 130 Command uint16 131 List [][]byte 132 } 133 134 func (t *TLV) Marshal() []byte { 135 w := binary.SelectWriter() 136 defer binary.PutWriter(w) 137 138 w.WriteUInt16(t.Command) 139 w.WriteUInt16(uint16(len(t.List))) 140 for _, elem := range t.List { 141 w.Write(elem) 142 } 143 144 return append([]byte(nil), w.Bytes()...) 145 } 146 147 func (t *TLV) Append(b ...[]byte) { 148 t.List = append(t.List, b...) 149 }