807 lines
28 KiB
Go
807 lines
28 KiB
Go
|
|
package clientsdk
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"encoding/base64"
|
|||
|
|
"encoding/binary"
|
|||
|
|
"encoding/hex"
|
|||
|
|
"errors"
|
|||
|
|
"hash/crc32"
|
|||
|
|
"strconv"
|
|||
|
|
"strings"
|
|||
|
|
"time"
|
|||
|
|
"xiawan/wx/clientsdk/android"
|
|||
|
|
clientsdk "xiawan/wx/clientsdk/hybrid"
|
|||
|
|
|
|||
|
|
"github.com/lunny/log"
|
|||
|
|
|
|||
|
|
"xiawan/wx/clientsdk/baseinfo"
|
|||
|
|
"xiawan/wx/clientsdk/baseutils"
|
|||
|
|
"xiawan/wx/clientsdk/ccdata"
|
|||
|
|
"xiawan/wx/clientsdk/proxynet"
|
|||
|
|
"xiawan/wx/protobuf/wechat"
|
|||
|
|
|
|||
|
|
"golang.org/x/net/proxy"
|
|||
|
|
|
|||
|
|
"github.com/golang/protobuf/proto"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// NewUserInfo 新建一个UserInfo
|
|||
|
|
func NewUserInfo(uuid string, proxyInfo *proxynet.WXProxyInfo, ClientVersion uint32, dbUserInfo *baseinfo.UserInfo) *baseinfo.UserInfo {
|
|||
|
|
var WifiInfo = createWifiInfo()
|
|||
|
|
//随机生成 deviceID
|
|||
|
|
var userInfo = baseinfo.UserInfo{
|
|||
|
|
UUID: uuid,
|
|||
|
|
Uin: 0,
|
|||
|
|
WxId: "",
|
|||
|
|
Session: []byte{},
|
|||
|
|
SessionKey: baseutils.RandomStringByLength(16),
|
|||
|
|
ShortHost: "szshort.weixin.qq.com",
|
|||
|
|
LongHost: "szlong.weixin.qq.com",
|
|||
|
|
ClientVersion: ClientVersion,
|
|||
|
|
SyncKey: []byte{},
|
|||
|
|
BalanceVersion: 1589560770,
|
|||
|
|
DeviceInfo: createDeviceInfo(WifiInfo, ClientVersion, dbUserInfo),
|
|||
|
|
DeviceInfoA16: createDeviceInfoA16(),
|
|||
|
|
WifiInfo: WifiInfo,
|
|||
|
|
ProxyInfo: proxyInfo,
|
|||
|
|
// 默认登录版本号 135
|
|||
|
|
LoginRsaVer: baseinfo.DefaultLoginRsaVer,
|
|||
|
|
|
|||
|
|
DeviceCreateTime: time.Now(), // 新设备注册时间
|
|||
|
|
}
|
|||
|
|
return &userInfo
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func NewUserInfo_Mac(uuid string, proxyInfo *proxynet.WXProxyInfo, ClientVersion uint32, dbUserInfo *baseinfo.UserInfo) *baseinfo.UserInfo {
|
|||
|
|
var WifiInfo = createWifiInfo()
|
|||
|
|
//随机生成 deviceID
|
|||
|
|
var userInfo = baseinfo.UserInfo{
|
|||
|
|
UUID: uuid,
|
|||
|
|
Uin: 0,
|
|||
|
|
WxId: "",
|
|||
|
|
Session: []byte{},
|
|||
|
|
SessionKey: baseutils.RandomStringByLength(16),
|
|||
|
|
ShortHost: "szshort.weixin.qq.com",
|
|||
|
|
LongHost: "szlong.weixin.qq.com",
|
|||
|
|
ClientVersion: ClientVersion,
|
|||
|
|
SyncKey: []byte{},
|
|||
|
|
BalanceVersion: 1589560770,
|
|||
|
|
DeviceInfo: createDeviceInfoMac(WifiInfo, ClientVersion, dbUserInfo),
|
|||
|
|
DeviceInfoA16: createDeviceInfoA16(),
|
|||
|
|
WifiInfo: WifiInfo,
|
|||
|
|
ProxyInfo: proxyInfo,
|
|||
|
|
// 默认登录版本号 135
|
|||
|
|
LoginRsaVer: baseinfo.DefaultLoginRsaVer,
|
|||
|
|
|
|||
|
|
DeviceCreateTime: time.Now(), // 新设备注册时间
|
|||
|
|
}
|
|||
|
|
return &userInfo
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 新建Wifi信息
|
|||
|
|
func createWifiInfo() *baseinfo.WifiInfo {
|
|||
|
|
retWifiInfo := &baseinfo.WifiInfo{}
|
|||
|
|
retWifiInfo.Name = "Chinanet-" + string(baseutils.RandomString(4, 7))
|
|||
|
|
retWifiInfo.WifiBssID = baseutils.RandomBSSID()
|
|||
|
|
return retWifiInfo
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 生成A16设备信息
|
|||
|
|
func createDeviceInfoA16() *baseinfo.AndroidDeviceInfo {
|
|||
|
|
deviceInfo := &baseinfo.AndroidDeviceInfo{}
|
|||
|
|
deviceInfo.BuildBoard = "bullhead"
|
|||
|
|
return deviceInfo
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateDeviceInfo 生成新的设备信息 ipad
|
|||
|
|
func createDeviceInfo(wifiInfo *baseinfo.WifiInfo, ClientVersion uint32, dbUserInfo *baseinfo.UserInfo) *baseinfo.DeviceInfo {
|
|||
|
|
IPadDeviceName := baseinfo.IPadDeviceName
|
|||
|
|
IPadModel := baseinfo.IPadModel
|
|||
|
|
IPadOsVersion := baseinfo.IPadOsVersion
|
|||
|
|
DeviceTypeIos := baseinfo.DeviceTypeIos
|
|||
|
|
CoreCount := uint32(2)
|
|||
|
|
Imei := baseutils.RandomSmallHexString(32)
|
|||
|
|
tmpDeviceID := baseutils.HexStringToBytes(Imei)
|
|||
|
|
tmpDeviceID[0] = 0x49
|
|||
|
|
|
|||
|
|
if dbUserInfo != nil && dbUserInfo.DeviceInfo != nil {
|
|||
|
|
IPadDeviceName = dbUserInfo.DeviceInfo.DeviceName
|
|||
|
|
IPadModel = dbUserInfo.DeviceInfo.IphoneVer
|
|||
|
|
IPadOsVersion = dbUserInfo.DeviceInfo.OsTypeNumber
|
|||
|
|
DeviceTypeIos = dbUserInfo.DeviceInfo.OsType
|
|||
|
|
CoreCount = dbUserInfo.DeviceInfo.CoreCount
|
|||
|
|
Imei = dbUserInfo.DeviceInfo.Imei
|
|||
|
|
tmpDeviceID = dbUserInfo.DeviceInfo.DeviceID
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
deviceInfo := &baseinfo.DeviceInfo{}
|
|||
|
|
deviceInfo.Imei = Imei
|
|||
|
|
deviceInfo.DeviceID = tmpDeviceID
|
|||
|
|
deviceInfo.DeviceName = IPadDeviceName //iPad Air 3 对应 iPad11,4 || iPad11,3
|
|||
|
|
deviceInfo.TimeZone = "8.00"
|
|||
|
|
deviceInfo.Language = "zh_CN"
|
|||
|
|
deviceInfo.DeviceBrand = "Apple"
|
|||
|
|
deviceInfo.RealCountry = "CN"
|
|||
|
|
deviceInfo.IphoneVer = IPadModel
|
|||
|
|
deviceInfo.BundleID = "com.tencent.xin"
|
|||
|
|
// deviceInfo.OsTypeNumber = "15.0.0"
|
|||
|
|
deviceInfo.OsTypeNumber = IPadOsVersion // "15.7.9"
|
|||
|
|
deviceInfo.OsType = DeviceTypeIos // "iPad iPadOS" + deviceInfo.OsTypeNumber
|
|||
|
|
deviceInfo.CoreCount = CoreCount // 2 核
|
|||
|
|
deviceInfo.AdSource = baseutils.RandomUUID()
|
|||
|
|
deviceInfo.UUIDOne = baseutils.RandomUUID()
|
|||
|
|
deviceInfo.UUIDTwo = baseutils.RandomUUID()
|
|||
|
|
// 运营商名
|
|||
|
|
deviceInfo.CarrierName = "(null)"
|
|||
|
|
// deviceInfo.CarrierName = "中国电信"
|
|||
|
|
deviceInfo.SoftTypeXML = CreateSoftInfoXML(deviceInfo, wifiInfo)
|
|||
|
|
// ClientCheckDataXML
|
|||
|
|
deviceInfo.ClientCheckDataXML = ccdata.CreateClientCheckDataXML(deviceInfo, ClientVersion)
|
|||
|
|
return deviceInfo
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateDeviceInfo 生成新的设备信息 mac
|
|||
|
|
func createDeviceInfoMac(wifiInfo *baseinfo.WifiInfo, ClientVersion uint32, dbUserInfo *baseinfo.UserInfo) *baseinfo.DeviceInfo {
|
|||
|
|
IPadDeviceName := baseinfo.MacDeviceName
|
|||
|
|
IPadModel := baseinfo.MacModel
|
|||
|
|
IPadOsVersion := baseinfo.MacOsVersion
|
|||
|
|
DeviceTypeIos := baseinfo.MacDeviceType
|
|||
|
|
CoreCount := uint32(2)
|
|||
|
|
Imei := baseutils.RandomSmallHexString(32)
|
|||
|
|
tmpDeviceID := baseutils.HexStringToBytes(Imei)
|
|||
|
|
tmpDeviceID[0] = 0x49
|
|||
|
|
|
|||
|
|
if dbUserInfo != nil {
|
|||
|
|
IPadDeviceName = dbUserInfo.DeviceInfo.DeviceName
|
|||
|
|
IPadModel = dbUserInfo.DeviceInfo.IphoneVer
|
|||
|
|
IPadOsVersion = dbUserInfo.DeviceInfo.OsTypeNumber
|
|||
|
|
DeviceTypeIos = dbUserInfo.DeviceInfo.OsType
|
|||
|
|
CoreCount = dbUserInfo.DeviceInfo.CoreCount
|
|||
|
|
Imei = dbUserInfo.DeviceInfo.Imei
|
|||
|
|
tmpDeviceID = dbUserInfo.DeviceInfo.DeviceID
|
|||
|
|
}
|
|||
|
|
deviceInfo := &baseinfo.DeviceInfo{}
|
|||
|
|
deviceInfo.Imei = Imei
|
|||
|
|
deviceInfo.DeviceID = tmpDeviceID
|
|||
|
|
deviceInfo.DeviceName = IPadDeviceName //iPad Air 3 对应 iPad11,4 || iPad11,3
|
|||
|
|
deviceInfo.TimeZone = "8.00"
|
|||
|
|
deviceInfo.Language = "zh_CN"
|
|||
|
|
deviceInfo.DeviceBrand = "Apple"
|
|||
|
|
deviceInfo.RealCountry = "CN"
|
|||
|
|
deviceInfo.IphoneVer = IPadModel
|
|||
|
|
deviceInfo.BundleID = "com.tencent.xin"
|
|||
|
|
// deviceInfo.OsTypeNumber = "15.0.0"
|
|||
|
|
deviceInfo.OsTypeNumber = IPadOsVersion // "15.7.9"
|
|||
|
|
deviceInfo.OsType = DeviceTypeIos // "iPad iPadOS" + deviceInfo.OsTypeNumber
|
|||
|
|
deviceInfo.CoreCount = CoreCount // 2 核
|
|||
|
|
deviceInfo.AdSource = baseutils.RandomUUID()
|
|||
|
|
deviceInfo.UUIDOne = baseutils.RandomUUID()
|
|||
|
|
deviceInfo.UUIDTwo = baseutils.RandomUUID()
|
|||
|
|
// 运营商名
|
|||
|
|
deviceInfo.CarrierName = "(null)"
|
|||
|
|
// deviceInfo.CarrierName = "中国电信"
|
|||
|
|
deviceInfo.SoftTypeXML = CreateSoftInfoXML(deviceInfo, wifiInfo)
|
|||
|
|
// ClientCheckDataXML
|
|||
|
|
deviceInfo.ClientCheckDataXML = ccdata.CreateClientCheckDataXML(deviceInfo, ClientVersion)
|
|||
|
|
return deviceInfo
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateSoftInfoXML CreateSoftInfoXML
|
|||
|
|
func CreateSoftInfoXML(deviceInfo *baseinfo.DeviceInfo, wifiInfo *baseinfo.WifiInfo) string {
|
|||
|
|
var retString string
|
|||
|
|
retString = retString + "<softtype><lctmoc>0</lctmoc><level>0</level><k1>0</k1>"
|
|||
|
|
retString = retString + "<k3>" + deviceInfo.OsTypeNumber + "</k3>"
|
|||
|
|
retString = retString + "<k9>" + deviceInfo.DeviceName + "</k9>"
|
|||
|
|
retString = retString + "<k10>" + strconv.Itoa(int(deviceInfo.CoreCount)) + "</k10>"
|
|||
|
|
retString = retString + "<k19>" + deviceInfo.UUIDOne + "</k19>"
|
|||
|
|
retString = retString + "<k20>" + deviceInfo.UUIDTwo + "</k20>"
|
|||
|
|
// retString = retString + "<k21>" + wifiInfo.Name + "</k21>"
|
|||
|
|
retString = retString + "<k22>" + deviceInfo.CarrierName + "</k22>"
|
|||
|
|
// retString = retString + "<k22>" + deviceInfo.CarrierName + "</k22>"
|
|||
|
|
retString = retString + "<k24>" + baseutils.BuildRandomMac() + "</k24>"
|
|||
|
|
retString = retString + "<k33>微信</k33>"
|
|||
|
|
// <k47>: 网络类型 1-wifi
|
|||
|
|
retString = retString + "<k47>1</k47>"
|
|||
|
|
// <k50>: 是否越狱 0-非越狱 1-越狱
|
|||
|
|
retString = retString + "<k50>0</k50>"
|
|||
|
|
retString = retString + "<k51>" + deviceInfo.BundleID + "</k51>"
|
|||
|
|
retString = retString + "<k54>" + deviceInfo.IphoneVer + "</k54>"
|
|||
|
|
// <k61>: 设备UUID是新的设备,还是老的设备
|
|||
|
|
retString = retString + "<k61>" + strconv.Itoa(1) + "</k61>"
|
|||
|
|
retString = retString + "</softtype>"
|
|||
|
|
return retString
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetEncryptUserInfo 获取加密信息
|
|||
|
|
func GetEncryptUserInfo(userInfo *baseinfo.UserInfo) string {
|
|||
|
|
if userInfo.WifiInfo == nil {
|
|||
|
|
userInfo.WifiInfo = createWifiInfo()
|
|||
|
|
}
|
|||
|
|
tmpString := "wifissid=" + userInfo.WifiInfo.Name
|
|||
|
|
tmpString = tmpString + "&wifibssid=" + userInfo.WifiInfo.WifiBssID
|
|||
|
|
timeStamp := strconv.Itoa(int(time.Now().UnixNano() / 1000))
|
|||
|
|
tmpString = tmpString + "&ssid_timestamp=" + timeStamp
|
|||
|
|
srcBytes := []byte(tmpString)
|
|||
|
|
srcBytes = append(srcBytes, 0)
|
|||
|
|
userInfo.GenHBKey()
|
|||
|
|
encData := baseutils.AesEncryptECB(srcBytes, userInfo.HBAesKey)
|
|||
|
|
return base64.StdEncoding.EncodeToString(encData)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetDialer 获取代理
|
|||
|
|
func GetDialer(userInfo *baseinfo.UserInfo) proxy.Dialer {
|
|||
|
|
if userInfo.Dialer != nil {
|
|||
|
|
return userInfo.Dialer
|
|||
|
|
}
|
|||
|
|
if userInfo.ProxyInfo == nil {
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
return userInfo.ProxyInfo.GetDialer()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Paser62Data 解析62数据
|
|||
|
|
func Parse62Data(data62 string) (string, error) {
|
|||
|
|
retList := strings.Split(strings.ToUpper(data62), "6E756C6C5F1020")
|
|||
|
|
if len(retList) < 2 {
|
|||
|
|
return "", errors.New("InitLoginDataInfo err: loginDataInfo.Data Split 6E756C6C5F1020 error")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 截取64位数据
|
|||
|
|
data64Str := retList[1][0:64]
|
|||
|
|
// 设置Imei
|
|||
|
|
return string(baseutils.HexStringToBytes(data64Str)), nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreatePackHead 创建包头
|
|||
|
|
func CreatePackHead(userInfo *baseinfo.UserInfo, compressType byte, urlID uint32, srcData []byte, encodeData []byte, zipLen uint32, encodeType byte, encodeVersion uint32) *baseinfo.PackHeader {
|
|||
|
|
retHeader := &baseinfo.PackHeader{}
|
|||
|
|
// Signature
|
|||
|
|
retHeader.Signature = 0xbf
|
|||
|
|
retHeader.CompressType = compressType
|
|||
|
|
retHeader.EncodeType = encodeType << 4
|
|||
|
|
|
|||
|
|
retHeader.ServerVersion = userInfo.ClientVersion
|
|||
|
|
if !(retHeader.ServerVersion > 0) {
|
|||
|
|
retHeader.ServerVersion = baseinfo.ClientVersion
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
retHeader.Uin = userInfo.Uin
|
|||
|
|
retHeader.Session = userInfo.Session
|
|||
|
|
retHeader.URLID = urlID
|
|||
|
|
retHeader.SrcLen = uint32(len(srcData))
|
|||
|
|
retHeader.ZipLen = zipLen
|
|||
|
|
retHeader.EncodeVersion = encodeVersion
|
|||
|
|
retHeader.HeadDeviceType = baseinfo.MMHeadDeviceTypeIpadUniversal
|
|||
|
|
retHeader.CheckSum = 0x00
|
|||
|
|
// 如果有压缩,则计算Sum值
|
|||
|
|
if retHeader.CompressType == baseinfo.MMPackDataTypeCompressed {
|
|||
|
|
retHeader.CheckSum = CalcHeadCheckSum(userInfo.Uin, userInfo.CheckSumKey, srcData)
|
|||
|
|
}
|
|||
|
|
// test
|
|||
|
|
/*if retHeader.URLID == 213 {
|
|||
|
|
retHeader.HeadDeviceType = 0x00
|
|||
|
|
}*/
|
|||
|
|
|
|||
|
|
retHeader.RunState = baseinfo.MMAppRunStateNormal
|
|||
|
|
// 修改 rqt 版本
|
|||
|
|
// 旧 rqtx
|
|||
|
|
// retHeader.RqtCode = SignRqtBufByAutoChosenKey(baseutils.Md5ValueByte(encodeData, false))
|
|||
|
|
// rqtx 加密
|
|||
|
|
// retHeader.RqtCode = baseutils.CalcMsgCrcForString_807(baseutils.Md5ValueByte(encodeData, false))
|
|||
|
|
// 新 rqtx
|
|||
|
|
retHeader.RqtCode = android.CalcMsgCrcForData_7019(encodeData)
|
|||
|
|
retHeader.EndFlag = 0x00
|
|||
|
|
retHeader.Data = encodeData
|
|||
|
|
|
|||
|
|
return retHeader
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// PackHeaderSerialize 序列化PackHeader
|
|||
|
|
func PackHeaderSerialize(packHeader *baseinfo.PackHeader, needCookie bool) []byte {
|
|||
|
|
retBytes := make([]byte, 0)
|
|||
|
|
retBytes = append(retBytes, packHeader.Signature)
|
|||
|
|
retBytes = append(retBytes, 0)
|
|||
|
|
encodeType := packHeader.EncodeType
|
|||
|
|
if needCookie {
|
|||
|
|
packHeader.EncodeType = packHeader.EncodeType + 0xf
|
|||
|
|
}
|
|||
|
|
retBytes = append(retBytes, packHeader.EncodeType)
|
|||
|
|
retBytes = append(retBytes, baseutils.Int32ToBytes(packHeader.ServerVersion)[0:]...)
|
|||
|
|
retBytes = append(retBytes, baseutils.Int32ToBytes(packHeader.Uin)[0:]...)
|
|||
|
|
if needCookie {
|
|||
|
|
retBytes = append(retBytes, packHeader.Session[0:]...)
|
|||
|
|
}
|
|||
|
|
retBytes = append(retBytes, baseutils.EncodeVByte32(packHeader.URLID)[0:]...)
|
|||
|
|
retBytes = append(retBytes, baseutils.EncodeVByte32(packHeader.SrcLen)[0:]...)
|
|||
|
|
retBytes = append(retBytes, baseutils.EncodeVByte32(packHeader.ZipLen)[0:]...)
|
|||
|
|
// hybrid
|
|||
|
|
if encodeType>>4 == 12 {
|
|||
|
|
retBytes = append(retBytes, []byte{byte(packHeader.HybridKeyVer)}...)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
retBytes = append(retBytes, baseutils.EncodeVByte32(packHeader.EncodeVersion)[0:]...)
|
|||
|
|
retBytes = append(retBytes, packHeader.HeadDeviceType)
|
|||
|
|
retBytes = append(retBytes, baseutils.EncodeVByte32(packHeader.CheckSum)[0:]...)
|
|||
|
|
retBytes = append(retBytes, packHeader.RunState)
|
|||
|
|
retBytes = append(retBytes, baseutils.EncodeVByte32(packHeader.RqtCode)[0:]...)
|
|||
|
|
retBytes = append(retBytes, packHeader.EndFlag)
|
|||
|
|
headLen := byte(len(retBytes))
|
|||
|
|
retBytes[1] = packHeader.CompressType + headLen<<2
|
|||
|
|
//fmt.Println(hex.EncodeToString(retBytes))
|
|||
|
|
retBytes = append(retBytes, packHeader.Data[0:]...)
|
|||
|
|
return retBytes
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Pack 打包加密数据
|
|||
|
|
func Pack(userInfo *baseinfo.UserInfo, src []byte, urlID uint32, encodeType byte) []byte {
|
|||
|
|
retData := make([]byte, 0)
|
|||
|
|
if encodeType == 7 || encodeType == 17 {
|
|||
|
|
//加密类型7
|
|||
|
|
encodeData := src
|
|||
|
|
if encodeType == 7 {
|
|||
|
|
encodeData = baseutils.NoCompressRsaByVer(src, userInfo.GetLoginRsaVer())
|
|||
|
|
}
|
|||
|
|
packHeader := CreatePackHead(userInfo, baseinfo.MMPackDataTypeUnCompressed, urlID, src, encodeData, uint32(len(src)), 7, userInfo.GetLoginRsaVer())
|
|||
|
|
retData = PackHeaderSerialize(packHeader, false)
|
|||
|
|
} else if encodeType == 5 {
|
|||
|
|
zipBytes := baseutils.CompressByteArray(src)
|
|||
|
|
encodeData := baseutils.AesEncrypt(zipBytes, userInfo.SessionKey)
|
|||
|
|
packHeader := CreatePackHead(userInfo, baseinfo.MMPackDataTypeCompressed, urlID, src, encodeData, uint32(len(zipBytes)), encodeType, 0)
|
|||
|
|
retData = PackHeaderSerialize(packHeader, true)
|
|||
|
|
} else if encodeType == 9 {
|
|||
|
|
// 加密类型9
|
|||
|
|
encodeData := src
|
|||
|
|
packHeader := CreatePackHead(userInfo, baseinfo.MMPackDataTypeUnCompressed, urlID, src, encodeData, uint32(len(src)), encodeType, userInfo.GetLoginRsaVer())
|
|||
|
|
retData = PackHeaderSerialize(packHeader, true)
|
|||
|
|
} else if encodeType == 1 {
|
|||
|
|
// 加密类型1
|
|||
|
|
encodeData := baseutils.NoCompressRsaByVer(src, userInfo.GetLoginRsaVer())
|
|||
|
|
packHeader := CreatePackHead(userInfo, baseinfo.MMPackDataTypeUnCompressed, urlID, src, encodeData, uint32(len(src)), encodeType, userInfo.GetLoginRsaVer())
|
|||
|
|
retData = PackHeaderSerialize(packHeader, true)
|
|||
|
|
} else if encodeType == 12 {
|
|||
|
|
secKeyMgr := NewSecLoginKeyMgrByVer(146)
|
|||
|
|
reqData := src
|
|||
|
|
//加密
|
|||
|
|
encrypt, epKey, token, ecdhpairkey, err := clientsdk.HybridEncrypt(reqData, secKeyMgr.WeChatPubKey)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Error("加密 error", err.Error())
|
|||
|
|
}
|
|||
|
|
ecdhPacket := &wechat.EcdhPacket{
|
|||
|
|
Type: proto.Uint32(1),
|
|||
|
|
Key: &wechat.BufferT{
|
|||
|
|
ILen: proto.Uint32(415),
|
|||
|
|
Buffer: ecdhpairkey.PubKey,
|
|||
|
|
},
|
|||
|
|
Token: token,
|
|||
|
|
Url: proto.String(""),
|
|||
|
|
ProtobufData: encrypt,
|
|||
|
|
}
|
|||
|
|
secKeyMgr.PubKey = ecdhpairkey.PubKey
|
|||
|
|
secKeyMgr.PriKey = ecdhpairkey.PriKey
|
|||
|
|
secKeyMgr.SourceData = reqData
|
|||
|
|
secKeyMgr.FinalSha256 = append(secKeyMgr.FinalSha256, epKey[24:]...)
|
|||
|
|
secKeyMgr.FinalSha256 = append(secKeyMgr.FinalSha256, reqData...)
|
|||
|
|
ecdhDataPacket, err := proto.Marshal(ecdhPacket)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Error("ecdhDataPacket error", err.Error())
|
|||
|
|
}
|
|||
|
|
packHeader := CreatePackHead(userInfo, baseinfo.MMPackDataTypeUnCompressed, urlID, ecdhDataPacket, ecdhDataPacket, uint32(len(ecdhDataPacket)), encodeType, uint32(0x4e))
|
|||
|
|
//设置Hybrid 加密密钥版本
|
|||
|
|
packHeader.HybridKeyVer = secKeyMgr.WeChatPubKeyVersion
|
|||
|
|
//开始组头
|
|||
|
|
retData := PackHeaderSerialize(packHeader, false)
|
|||
|
|
//fmt.Println(hex.EncodeToString(retData))
|
|||
|
|
/*resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/secautoauth", retData)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Error("mmtls error", err.Error())
|
|||
|
|
}*/
|
|||
|
|
/*packHeader, err = DecodePackHeader(resp, nil)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Error("ecdhDataPacket error", err.Error())
|
|||
|
|
}
|
|||
|
|
packHeader.Data, err = clientsdk.HybridEcdhDecrypt(packHeader.Data, secKeyMgr.PriKey, secKeyMgr.PubKey, secKeyMgr.FinalSha256)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Error("HybridEcdhDecrypt error", err.Error())
|
|||
|
|
}
|
|||
|
|
return packHeader, err*/
|
|||
|
|
return retData
|
|||
|
|
}
|
|||
|
|
return retData
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func PackNoCompressAES(userInfo *baseinfo.UserInfo, src []byte, urlID uint32) []byte {
|
|||
|
|
encodeData := baseutils.AesEncrypt(src, userInfo.SessionKey)
|
|||
|
|
packHeader := CreatePackHead(userInfo, baseinfo.MMPackDataTypeUnCompressed, urlID, src, encodeData, uint32(len(src)), 5, 0)
|
|||
|
|
return PackHeaderSerialize(packHeader, true)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Pack 打包加密数据
|
|||
|
|
func Pack12(userInfo *baseinfo.UserInfo, src []byte, urlID uint32, encodeType byte) ([]byte, *SecLoginKeyMgr) {
|
|||
|
|
retData := make([]byte, 0)
|
|||
|
|
secKeyMgr := NewSecLoginKeyMgrByVer(146)
|
|||
|
|
reqData := src
|
|||
|
|
//加密
|
|||
|
|
encrypt, epKey, token, ecdhpairkey, err := clientsdk.HybridEncrypt(reqData, secKeyMgr.WeChatPubKey)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Error("加密 error", err.Error())
|
|||
|
|
}
|
|||
|
|
ecdhPacket := &wechat.EcdhPacket{
|
|||
|
|
Type: proto.Uint32(1),
|
|||
|
|
Key: &wechat.BufferT{
|
|||
|
|
ILen: proto.Uint32(415),
|
|||
|
|
Buffer: ecdhpairkey.PubKey,
|
|||
|
|
},
|
|||
|
|
Token: token,
|
|||
|
|
Url: proto.String(""),
|
|||
|
|
ProtobufData: encrypt,
|
|||
|
|
}
|
|||
|
|
secKeyMgr.PubKey = ecdhpairkey.PubKey
|
|||
|
|
secKeyMgr.PriKey = ecdhpairkey.PriKey
|
|||
|
|
secKeyMgr.SourceData = reqData
|
|||
|
|
secKeyMgr.FinalSha256 = append(secKeyMgr.FinalSha256, epKey[24:]...)
|
|||
|
|
secKeyMgr.FinalSha256 = append(secKeyMgr.FinalSha256, reqData...)
|
|||
|
|
ecdhDataPacket, err := proto.Marshal(ecdhPacket)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Error("ecdhDataPacket error", err.Error())
|
|||
|
|
}
|
|||
|
|
packHeader := CreatePackHead(userInfo, baseinfo.MMPackDataTypeUnCompressed, urlID, ecdhDataPacket, ecdhDataPacket, uint32(len(ecdhDataPacket)), encodeType, uint32(0x4e))
|
|||
|
|
//设置Hybrid 加密密钥版本
|
|||
|
|
packHeader.HybridKeyVer = secKeyMgr.WeChatPubKeyVersion
|
|||
|
|
//开始组头
|
|||
|
|
retData = PackHeaderSerialize(packHeader, false)
|
|||
|
|
//fmt.Println(hex.EncodeToString(retData))
|
|||
|
|
/*resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/secautoauth", retData)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Error("mmtls error", err.Error())
|
|||
|
|
}*/
|
|||
|
|
/*packHeader, err = DecodePackHeader(resp, nil)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Error("ecdhDataPacket error", err.Error())
|
|||
|
|
}
|
|||
|
|
packHeader.Data, err = clientsdk.HybridEcdhDecrypt(packHeader.Data, secKeyMgr.PriKey, secKeyMgr.PubKey, secKeyMgr.FinalSha256)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Error("HybridEcdhDecrypt error", err.Error())
|
|||
|
|
}
|
|||
|
|
return packHeader, err*/
|
|||
|
|
return retData, secKeyMgr
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// DecodePackHeader DecodePackHeader
|
|||
|
|
func DecodePackHeader(respData []byte, reqData []byte) (*baseinfo.PackHeader, error) {
|
|||
|
|
packHeader := &baseinfo.PackHeader{}
|
|||
|
|
packHeader.ReqData = reqData
|
|||
|
|
packHeader.RetCode = 0
|
|||
|
|
if len(respData) <= 32 {
|
|||
|
|
packHeader.RetCode = GetRespErrorCode(respData)
|
|||
|
|
return packHeader, errors.New("DecodePackHeader err: len(respData) <= 32")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
current := 0
|
|||
|
|
packHeader.Signature = respData[current]
|
|||
|
|
current++
|
|||
|
|
packHeader.HeadLength = (respData[current]) >> 2
|
|||
|
|
packHeader.CompressType = (respData[current]) & 3
|
|||
|
|
current++
|
|||
|
|
packHeader.EncodeType = respData[current] >> 4
|
|||
|
|
sessionLen := int(respData[current] & 0x0f)
|
|||
|
|
current++
|
|||
|
|
packHeader.ServerVersion = baseutils.BytesToInt32(respData[current : current+4])
|
|||
|
|
current = current + 4
|
|||
|
|
packHeader.Uin = baseutils.BytesToInt32(respData[current : current+4])
|
|||
|
|
current = current + 4
|
|||
|
|
if sessionLen > 0 {
|
|||
|
|
packHeader.Session = respData[current : current+sessionLen]
|
|||
|
|
current = current + sessionLen
|
|||
|
|
}
|
|||
|
|
retLen := uint32(0)
|
|||
|
|
packHeader.URLID, retLen = baseutils.DecodeVByte32(respData, uint32(current))
|
|||
|
|
current = current + int(retLen)
|
|||
|
|
packHeader.SrcLen, retLen = baseutils.DecodeVByte32(respData, uint32(current))
|
|||
|
|
current = current + int(retLen)
|
|||
|
|
packHeader.ZipLen, retLen = baseutils.DecodeVByte32(respData, uint32(current))
|
|||
|
|
current = current + int(retLen)
|
|||
|
|
packHeader.EncodeVersion, retLen = baseutils.DecodeVByte32(respData, uint32(current))
|
|||
|
|
current = current + int(retLen)
|
|||
|
|
packHeader.HeadDeviceType = respData[current]
|
|||
|
|
current = current + 1
|
|||
|
|
packHeader.CheckSum, retLen = baseutils.DecodeVByte32(respData, uint32(current))
|
|||
|
|
current = current + int(retLen)
|
|||
|
|
packHeader.RunState = respData[current]
|
|||
|
|
current = current + 1
|
|||
|
|
packHeader.RqtCode, retLen = baseutils.DecodeVByte32(respData, uint32(current))
|
|||
|
|
current = current + int(retLen)
|
|||
|
|
packHeader.EndFlag = respData[current]
|
|||
|
|
current = current + 1
|
|||
|
|
// // 后面还有一个字节-- 可能是7.10新版本增加的一个字节,待后面分析
|
|||
|
|
// current = current + 1
|
|||
|
|
// if current != int(packHeader.HeadLength) {
|
|||
|
|
// return nil, errors.New("DecodePackHeader failed current != int(packHeader.HeadLength")
|
|||
|
|
// }
|
|||
|
|
packHeader.Data = respData[packHeader.HeadLength:]
|
|||
|
|
return packHeader, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ParseResponseData 解析相应数据
|
|||
|
|
func ParseResponseData(userInfo *baseinfo.UserInfo, packHeader *baseinfo.PackHeader, response proto.Message) error {
|
|||
|
|
// 判断包体长度是否大于0
|
|||
|
|
if len(packHeader.Data) <= 0 {
|
|||
|
|
log.Error("ParseResponseData err: len(packHeader.Data) <= 0")
|
|||
|
|
return errors.New("ParseResponseData err: len(packHeader.Data) <= 0")
|
|||
|
|
}
|
|||
|
|
var decptBody []byte
|
|||
|
|
var err error
|
|||
|
|
if packHeader.EncodeType == 12 {
|
|||
|
|
decptBody = packHeader.Data
|
|||
|
|
} else if packHeader.EncodeType == 5 {
|
|||
|
|
// 解密
|
|||
|
|
decptBody, err = baseutils.AesDecrypt(packHeader.Data, userInfo.SessionKey)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
// fmt.Println(hex.EncodeToString(decptBody))
|
|||
|
|
// 判断是否有压缩
|
|||
|
|
if packHeader.CompressType == baseinfo.MMPackDataTypeCompressed {
|
|||
|
|
if decptBody != nil {
|
|||
|
|
// fmt.Println(hex.EncodeToString(decptBody))
|
|||
|
|
decptBody, err = baseutils.UnzipByteArray(decptBody)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Error("ParseResponseData err:", err.Error(), packHeader.URLID)
|
|||
|
|
// 打印解密后的数据前100字节用于调试
|
|||
|
|
if len(decptBody) > 0 {
|
|||
|
|
debugLen := 100
|
|||
|
|
if len(decptBody) < debugLen {
|
|||
|
|
debugLen = len(decptBody)
|
|||
|
|
}
|
|||
|
|
log.Error("Decrypted data (first bytes):", hex.EncodeToString(decptBody[:debugLen]))
|
|||
|
|
}
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
return errors.New("decptBody err: len(decptBody) == nil")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
// 解密
|
|||
|
|
decptBody, err = baseutils.AesDecrypt(packHeader.Data, userInfo.SessionKey)
|
|||
|
|
// fmt.Println(hex.EncodeToString(decptBody))
|
|||
|
|
if err != nil {
|
|||
|
|
//log.Error("ParseResponseData err:", err.Error())
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
// 判断是否有压缩
|
|||
|
|
if packHeader.CompressType == baseinfo.MMPackDataTypeCompressed {
|
|||
|
|
if decptBody != nil {
|
|||
|
|
decptBody, err = baseutils.UnzipByteArray(decptBody)
|
|||
|
|
if err != nil {
|
|||
|
|
//fmt.Println(hex.EncodeToString(packHeader.Data))
|
|||
|
|
log.Error("ParseResponseData err:", err.Error(), packHeader.URLID)
|
|||
|
|
// 打印解密后的数据前100字节用于调试
|
|||
|
|
if len(decptBody) > 0 {
|
|||
|
|
debugLen := 100
|
|||
|
|
if len(decptBody) < debugLen {
|
|||
|
|
debugLen = len(decptBody)
|
|||
|
|
}
|
|||
|
|
log.Error("Decrypted data (first bytes):", hex.EncodeToString(decptBody[:debugLen]))
|
|||
|
|
}
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
return errors.New("decptBody err: len(decptBody) == nil")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新UserInfo
|
|||
|
|
if len(packHeader.Session) > 6 {
|
|||
|
|
userInfo.Session = packHeader.Session
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if packHeader.Uin != 0 {
|
|||
|
|
userInfo.Uin = packHeader.Uin
|
|||
|
|
}
|
|||
|
|
// fmt.Println(hex.EncodeToString(decptBody))
|
|||
|
|
// 解包ProtoBuf
|
|||
|
|
err = proto.Unmarshal(decptBody, response)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Error("ParseResponseData err:", err.Error())
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetBaseRequest 获取baserequest
|
|||
|
|
func GetBaseRequest(userInfo *baseinfo.UserInfo) *wechat.BaseRequest {
|
|||
|
|
ret := &wechat.BaseRequest{}
|
|||
|
|
ret.SessionKey = []byte(userInfo.SessionKey)
|
|||
|
|
ret.Uin = &userInfo.Uin
|
|||
|
|
if !strings.HasPrefix(userInfo.LoginDataInfo.LoginData, "A") && userInfo.DeviceInfo != nil {
|
|||
|
|
ret.DeviceId = userInfo.DeviceInfo.DeviceID
|
|||
|
|
ret.OsType = &userInfo.DeviceInfo.OsType
|
|||
|
|
ret.Scene = proto.Uint32(0)
|
|||
|
|
ret.ClientVersion = &userInfo.ClientVersion
|
|||
|
|
if !(int(*ret.ClientVersion) > 0) {
|
|||
|
|
ret.ClientVersion = &baseinfo.ClientVersion
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
ret.ClientVersion = &baseinfo.AndroidClientVersion
|
|||
|
|
ret.OsType = &baseinfo.AndroidPadDeviceType
|
|||
|
|
ret.DeviceId = userInfo.DeviceInfoA16.DeviceId
|
|||
|
|
ret.Scene = proto.Uint32(1)
|
|||
|
|
}
|
|||
|
|
return ret
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CalcCheckCode 计算校验码
|
|||
|
|
// wxId : 微信ID
|
|||
|
|
// currentTime : 时间
|
|||
|
|
// return uint32 计算出来的校验码
|
|||
|
|
func CalcCheckCode(wxID string, currentTime time.Time) uint32 {
|
|||
|
|
var tmpTime = currentTime.Format("051504010206")
|
|||
|
|
if len(wxID) <= 0 {
|
|||
|
|
tmpTime = tmpTime + "fffffff"
|
|||
|
|
}
|
|||
|
|
if len(wxID) > 0 {
|
|||
|
|
wxIDMd5 := baseutils.Md5Value(wxID)
|
|||
|
|
tmpTime = tmpTime + baseutils.StringCut(wxIDMd5, 0, 7)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
misSecond := currentTime.UnixNano() / 1000000
|
|||
|
|
var modValue = uint32(misSecond % 65535)
|
|||
|
|
var modValue2 = int(misSecond%7 + 100)
|
|||
|
|
modHexString := string(baseutils.UInt32To16Bytes(modValue))
|
|||
|
|
mod2String := strconv.Itoa(modValue2)
|
|||
|
|
tmpTime = tmpTime + modHexString + mod2String
|
|||
|
|
|
|||
|
|
return baseutils.HashCode(tmpTime)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// WithSeqidCalcCheckCode 根据seqid计算
|
|||
|
|
func WithSeqidCalcCheckCode(wxID string, seqid int64) uint32 {
|
|||
|
|
currentTime := time.Unix(0, seqid)
|
|||
|
|
var tmpTime = currentTime.Format("051504010206")
|
|||
|
|
if len(wxID) <= 0 {
|
|||
|
|
tmpTime = tmpTime + "fffffff"
|
|||
|
|
}
|
|||
|
|
if len(wxID) > 0 {
|
|||
|
|
wxIDMd5 := baseutils.Md5Value(wxID)
|
|||
|
|
tmpTime = tmpTime + baseutils.StringCut(wxIDMd5, 0, 7)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
misSecond := currentTime.UnixNano() / 1000000
|
|||
|
|
var modValue = uint32(misSecond % 65535)
|
|||
|
|
var modValue2 = int(misSecond%7 + 100)
|
|||
|
|
modHexString := string(baseutils.UInt32To16Bytes(modValue))
|
|||
|
|
mod2String := strconv.Itoa(modValue2)
|
|||
|
|
tmpTime = tmpTime + modHexString + mod2String
|
|||
|
|
|
|||
|
|
return baseutils.HashCode(tmpTime)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetErrStrByErrCode GetErrStrByErrCode
|
|||
|
|
func GetErrStrByErrCode(errCode int32) string {
|
|||
|
|
if errCode == -2 {
|
|||
|
|
return "error: args not whole or args type error"
|
|||
|
|
}
|
|||
|
|
if errCode == -13 {
|
|||
|
|
return "error: session timeout"
|
|||
|
|
}
|
|||
|
|
if errCode == -102 {
|
|||
|
|
return "error: cert expired"
|
|||
|
|
}
|
|||
|
|
if errCode == -306 {
|
|||
|
|
return "error: ecdh failed rollback"
|
|||
|
|
}
|
|||
|
|
if errCode == -3001 || errCode == -3003 {
|
|||
|
|
return "error: need get dns"
|
|||
|
|
}
|
|||
|
|
if errCode == -3002 {
|
|||
|
|
return "error: MM_ERR_IDCDISASTER"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return "unknow"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetRespErrorCode 当response 小于32个字节时,调用这个接口获取响应的错误码
|
|||
|
|
func GetRespErrorCode(data []byte) int32 {
|
|||
|
|
tmpData := make([]byte, 0)
|
|||
|
|
tmpData = append(tmpData, data[2:6]...)
|
|||
|
|
|
|||
|
|
tmpRet := binary.BigEndian.Uint32(tmpData)
|
|||
|
|
return int32(tmpRet)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// RqtKey 计算RQT用到到Key
|
|||
|
|
var RqtKey = []byte{0x6a, 0x66, 0x4d, 0x5d, 0x53, 0x7c, 0x25, 0x3f, 0x73, 0x6e, 0x48, 0x27, 0x3a, 0x29, 0x5e, 0x4f}
|
|||
|
|
|
|||
|
|
// SignRqtBufByAutoChosenKey 计算RQT值
|
|||
|
|
func SignRqtBufByAutoChosenKey(md5Value string) uint32 {
|
|||
|
|
// tmpRqtKeyOne
|
|||
|
|
rqtLen := len(RqtKey)
|
|||
|
|
totalLength := 48 + rqtLen
|
|||
|
|
blockOne := make([]byte, totalLength)
|
|||
|
|
for index := 0; index < totalLength; index++ {
|
|||
|
|
blockOne[index] = 0
|
|||
|
|
if index < rqtLen {
|
|||
|
|
blockOne[index] = RqtKey[index]
|
|||
|
|
}
|
|||
|
|
blockOne[index] = blockOne[index] ^ 0x36
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// tmpRqtKeyTwo
|
|||
|
|
blockTwo := make([]byte, totalLength)
|
|||
|
|
for index := 0; index < totalLength; index++ {
|
|||
|
|
blockTwo[index] = 0
|
|||
|
|
if index < rqtLen {
|
|||
|
|
blockTwo[index] = RqtKey[index]
|
|||
|
|
}
|
|||
|
|
blockTwo[index] = blockTwo[index] ^ 0x5c
|
|||
|
|
}
|
|||
|
|
// 计算Hash值
|
|||
|
|
tmpData := append(blockOne, []byte(md5Value)[0:]...)
|
|||
|
|
shaValue := baseutils.Sha1(tmpData)
|
|||
|
|
tmpData = append(blockTwo, shaValue[0:]...)
|
|||
|
|
shaValue = baseutils.Sha1(tmpData)
|
|||
|
|
|
|||
|
|
// 计算key1,key2, key3
|
|||
|
|
key1 := 0
|
|||
|
|
key2 := 0
|
|||
|
|
key3 := 0
|
|||
|
|
tmpLen := len(shaValue) - 2
|
|||
|
|
for index := 0; index < tmpLen; index++ {
|
|||
|
|
tmpValue1 := shaValue[index] & 0xff
|
|||
|
|
tmpValue2 := shaValue[index+1] & 0xff
|
|||
|
|
tmpValue3 := shaValue[index+2] & 0xff
|
|||
|
|
|
|||
|
|
key1 = key1*0x83 + int(tmpValue1)
|
|||
|
|
key2 = key2*0x83 + int(tmpValue2)
|
|||
|
|
key3 = key3*0x83 + int(tmpValue3)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 计算RQT值
|
|||
|
|
key1 = key1 & 0x7f
|
|||
|
|
key2 = (key2 << 8) & 0x7f00
|
|||
|
|
key3 = (key3 << 16) & 0x7f0000
|
|||
|
|
retValue := key1 | key3 | key2
|
|||
|
|
retValue = retValue | 0x21000000
|
|||
|
|
return uint32(retValue)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CalcHeadCheckSum 计算HeadCheckSum值
|
|||
|
|
func CalcHeadCheckSum(uin uint32, checkSumKey []byte, srcData []byte) uint32 {
|
|||
|
|
uinBytes := baseutils.Int32ToBytes(uin)
|
|||
|
|
tmpBytes := append(uinBytes, checkSumKey[0:]...)
|
|||
|
|
md5Value := baseutils.Md5Value16(tmpBytes)
|
|||
|
|
|
|||
|
|
dataLen := uint32(len(srcData))
|
|||
|
|
dataLenBytes := baseutils.Int32ToBytes(dataLen)
|
|||
|
|
tmpBytes = append(dataLenBytes, checkSumKey[0:]...)
|
|||
|
|
tmpBytes = append(tmpBytes, md5Value[0:]...)
|
|||
|
|
md5Value = baseutils.Md5Value16(tmpBytes)
|
|||
|
|
|
|||
|
|
tmpBytes = append([]byte{}, md5Value[0:]...)
|
|||
|
|
// 计算返回
|
|||
|
|
/*tmpSum := baseutils.Adler32(1, tmpBytes)
|
|||
|
|
return baseutils.Adler32(tmpSum, srcData)*/
|
|||
|
|
return crc32.ChecksumIEEE(tmpBytes)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// TenPaySignDes3 支付相关的加密算法
|
|||
|
|
func TenPaySignDes3(srcData string, encKey string) (string, error) {
|
|||
|
|
srcMD5Bytes := []byte(baseutils.Md5ValueByte([]byte(srcData), true))
|
|||
|
|
keyMD5Bytes := baseutils.Md5ValueByte([]byte(encKey), true)
|
|||
|
|
desKey := baseutils.HexStringToBytes(keyMD5Bytes)
|
|||
|
|
|
|||
|
|
encBytes := make([]byte, 0)
|
|||
|
|
for index := 0; index < 4; index++ {
|
|||
|
|
currentOffset := index * 8
|
|||
|
|
tmpSrcData := srcMD5Bytes[currentOffset : currentOffset+8]
|
|||
|
|
encData, err := baseutils.Encrypt3DES(tmpSrcData, desKey)
|
|||
|
|
if err != nil {
|
|||
|
|
return "", err
|
|||
|
|
}
|
|||
|
|
encBytes = append(encBytes, encData...)
|
|||
|
|
}
|
|||
|
|
return baseutils.BytesToHexString(encBytes, true), nil
|
|||
|
|
}
|