package android import ( "bytes" "compress/zlib" "encoding/binary" "io" "github.com/golang/protobuf/proto" ) type PacketHeader struct { PacketCryptType byte Flag uint16 RetCode uint32 UICrypt uint32 Uin uint32 Cookies []byte Data []byte } func DoZlibCompress(src []byte) []byte { var in bytes.Buffer w := zlib.NewWriter(&in) w.Write(src) w.Close() return in.Bytes() } // 进行zlib解压缩 func DoZlibUnCompress(compressSrc []byte) []byte { b := bytes.NewReader(compressSrc) var out bytes.Buffer r, _ := zlib.NewReader(b) io.Copy(&out, r) return out.Bytes() } func PackHybridEcdh(cmdid, cert, uin uint32, cookie, input []byte) []byte { inputlen := len(input) crc := CalcMsgCrc(input) pack := append([]byte{}, cookie...) pack = proto.EncodeVarint(uint64(cmdid)) pack = append(pack, proto.EncodeVarint(uint64(inputlen))...) pack = append(pack, proto.EncodeVarint(uint64(inputlen))...) pack = append(pack, proto.EncodeVarint(uint64(cert))...) pack = append(pack, 2) pack = append(pack, 0) pack = append(pack, 0xfe) pack = append(pack, proto.EncodeVarint(uint64(crc))...) pack = append(pack, 0) headLen := len(pack) + 11 headFlag := (12 << 12) | (len(cookie) << 8) | (headLen << 2) | 2 var hybridpack = new(bytes.Buffer) hybridpack.WriteByte(0xbf) binary.Write(hybridpack, binary.LittleEndian, uint16(headFlag)) binary.Write(hybridpack, binary.BigEndian, uint32(0x27000b32)) binary.Write(hybridpack, binary.BigEndian, uint32(uin)) hybridpack.Write(pack) hybridpack.Write(input) return hybridpack.Bytes() } func UnpackHybridEcdh(input []byte) *PacketHeader { var ph PacketHeader readHeader := bytes.NewReader(input) binary.Read(readHeader, binary.LittleEndian, &ph.PacketCryptType) binary.Read(readHeader, binary.LittleEndian, &ph.Flag) cookieLen := (ph.Flag >> 8) & 0x0f headerLen := (ph.Flag & 0xff) >> 2 ph.Cookies = make([]byte, cookieLen) binary.Read(readHeader, binary.BigEndian, &ph.RetCode) binary.Read(readHeader, binary.BigEndian, &ph.UICrypt) binary.Read(readHeader, binary.LittleEndian, &ph.Cookies) ph.Data = input[headerLen:] return &ph } func Pack(cmdid, cert, algo, uin uint32, cookies, authecdhkey, sesskey, input []byte) []byte { inputlen := len(input) crc := CalcMsgCrc(input) sign := GenSignature(uin, authecdhkey, input) b := new(bytes.Buffer) binary.Write(b, binary.BigEndian, uin) b.Write(cookies) b.Write(proto.EncodeVarint(uint64(cmdid))) b.Write(proto.EncodeVarint(uint64(inputlen))) b.Write(proto.EncodeVarint(uint64(inputlen))) b.Write(proto.EncodeVarint(uint64(cert))) b.Write(proto.EncodeVarint(uint64(2))) b.Write(proto.EncodeVarint(uint64(sign))) b.Write([]byte{0xfe}) b.Write(proto.EncodeVarint(uint64(crc))) b.Write([]byte{0x00}) var encData []byte var compress uint32 if algo == 5 { encData = EncryptAES(input, sesskey) compress = 2 } subHead := b.Bytes() flag := (algo << 12) | (uint32(len(cookies)) << 8) | ((7 + uint32(len(subHead))) << 2) | compress bb := new(bytes.Buffer) bb.Write([]byte{0xbf}) binary.Write(bb, binary.LittleEndian, uint16(flag)) binary.Write(bb, binary.BigEndian, uint32(0x27000b32)) bb.Write(subHead) bb.Write(encData) return bb.Bytes() } func Unpack(input, key []byte) *PacketHeader { var ph PacketHeader readHeader := bytes.NewReader(input) binary.Read(readHeader, binary.LittleEndian, &ph.PacketCryptType) binary.Read(readHeader, binary.LittleEndian, &ph.Flag) cookieLen := (ph.Flag >> 8) & 0x0f headerLen := (ph.Flag & 0xff) >> 2 algo := ph.Flag >> 12 comp := ph.Flag & 3 ph.Cookies = make([]byte, cookieLen) binary.Read(readHeader, binary.BigEndian, &ph.RetCode) binary.Read(readHeader, binary.BigEndian, &ph.UICrypt) binary.Read(readHeader, binary.LittleEndian, &ph.Cookies) Data := input[headerLen:] var DecData []byte if algo == 5 { DecData = DecryptAES(Data, key) } if comp == 1 { ph.Data = DoZlibUnCompress(DecData) } else { ph.Data = DecData } return &ph }