| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- package app
- import (
- "context"
- "encoding/base64"
- "encoding/hex"
- "encoding/json"
- "errors"
- "fmt"
- waProto "git.bobomao.top/joey/whatsmeow/binary/proto"
- "github.com/gogf/gf/util/gconv"
- "github.com/golang/protobuf/proto"
- "github.com/ulule/deepcopier"
- "log"
- )
- // IsEmpty
- func IsEmpty(s string) bool {
- return s == "" || len(s) <= 0
- }
- type AuthDataDto struct {
- *ClientPayload
- }
- type AuthDataDtoActual struct {
- *waProto.ClientPayload
- }
- // LoginDto 登录信息
- type LoginDto struct {
- // socks 5 代理
- UUID string
- Socks5 string
- AuthBody *AuthDataDto
- AuthBodyActual *AuthDataDtoActual
- // AuthHexData 握手认证数据
- AuthHexData string
- // StaticPriKey 认证私钥
- StaticPriKey string
- // StaticPubKey 认证公钥
- StaticPubKey string
- //注册返回
- ClientStaticKeypair string
- //EdgeRouting
- EdgeRouting string
- //
- IdentityPubKey string
- IdentityPriKey string
- Hash string
- }
- func (loginDto *LoginDto) Init() {
- loginDto.AuthBodyActual = &AuthDataDtoActual{
- ClientPayload: &waProto.ClientPayload{
- UserAgent: &waProto.ClientPayload_UserAgent{
- AppVersion: &waProto.ClientPayload_UserAgent_AppVersion{},
- },
- },
- }
- //playload := loginDto.AuthBodyActual.ClientPayload
- //playloadActual := loginDto.AuthBodyActual.ClientPayload
- playload := loginDto.AuthBody.ClientPayload
- playloadActual := loginDto.AuthBodyActual.ClientPayload
- deepcopier.Copy(playload).To(playloadActual)
- deepcopier.Copy(playload.UserAgent).To(playloadActual.UserAgent)
- deepcopier.Copy(playload.UserAgent.AppVersion).To(playloadActual.UserAgent.AppVersion)
- playloadActual.UserAgent.Platform = (*waProto.ClientPayload_UserAgent_Platform)(playload.UserAgent.Platform)
- //playload
- }
- type DHKey struct {
- Private []byte
- Public []byte
- }
- var DHString = []byte{69, 68, 0, 1}
- var InitString = []byte("WA")
- type VerifyCallbackFunc func(publicKey []byte, data []byte) error
- // WAProtocolVersion noise 握手版本
- type WAProtocolVersion struct {
- // 主要版本
- VersionMajor byte
- // 次要版本
- VersionMinor byte
- }
- type WAHandshakeSettings struct {
- RoutingInfo []byte
- //认证数据
- Payload []byte //certificates, signs etc
- // 用户注册时生成的公私秘钥
- StaticKey DHKey
- // 服务器公钥
- PeerStatic []byte
- }
- // loginInfo
- type loginInfo struct {
- ctx context.Context
- // login info
- clientPayload *waProto.ClientPayload
- priKey, pubKey []byte
- routingInfo []byte
- staticPubKey *[32]byte
- staticPriKey *[32]byte
- }
- func (l *loginInfo) GetStaticPubKey() *[32]byte {
- return l.staticPubKey
- }
- func (l *loginInfo) SetStaticPubKey(d string) error {
- data, err := base64.StdEncoding.DecodeString(d)
- if err != nil {
- return err
- }
- if len(data) == 33 {
- data = data[1:]
- }
- var byteArray [32]byte
- copy(byteArray[:], data)
- l.staticPubKey = &byteArray
- return nil
- }
- func (l *loginInfo) GetStaticPriKey() *[32]byte {
- return l.staticPriKey
- }
- func (l *loginInfo) SetStaticPriKey(d string) error {
- data, err := base64.StdEncoding.DecodeString(d)
- if err != nil {
- return err
- }
- if len(data) == 33 {
- data = data[1:]
- }
- var byteArray [32]byte
- copy(byteArray[:], data)
- l.staticPriKey = &byteArray
- return nil
- }
- func (l *loginInfo) Ctx() context.Context {
- return l.ctx
- }
- func (l *loginInfo) SetRoutingInfo(d []byte) {
- l.routingInfo = d
- }
- func (l *loginInfo) SetStaticHdBase64Keys(pri, pub string) error {
- priData, err := base64.StdEncoding.DecodeString(pri)
- if err != nil {
- return err
- }
- pubData, err := base64.StdEncoding.DecodeString(pub)
- if err != nil {
- return err
- }
- if len(priData) != 32 || len(pubData) < 32 {
- return errors.New("keys length less than 32 bit")
- }
- if len(pubData) == 33 {
- pubData = pubData[1:]
- }
- if len(priData) == 33 {
- priData = priData[1:]
- }
- // set keys
- l.priKey, l.pubKey = priData, pubData
- return nil
- }
- func (l *loginInfo) SetStaticHdKeys(pri, pub []byte) error {
- if len(pri) != 32 || len(pub) != 32 {
- return errors.New("keys length less than 32 bit")
- }
- // set keys
- l.priKey, l.pubKey = pri, pub
- return nil
- }
- // SetStaticKeys
- func (l *loginInfo) SetStaticKeys(base64Data string) error {
- skData, err := base64.StdEncoding.DecodeString(base64Data)
- if err != nil {
- return err
- }
- // if sk data length not 64
- if len(skData) < 64 {
- return errors.New("static keys length less than 64 bit")
- }
- // set static keys
- l.priKey, l.pubKey = skData[:32], skData[32:]
- return nil
- }
- func (l *loginInfo) SetCliPayload(payload *waProto.ClientPayload) {
- if payload != nil {
- l.clientPayload = payload
- }
- }
- // SetCliPayloadData
- func (l *loginInfo) SetCliPayloadData(data []byte) error {
- return proto.Unmarshal(data, l.clientPayload)
- }
- // GetLoginSettings
- func (l *loginInfo) GetLoginSettings() *WAHandshakeSettings {
- return &WAHandshakeSettings{
- RoutingInfo: l.routingInfo,
- Payload: l.buildClientPayload(),
- StaticKey: DHKey{
- Private: l.priKey,
- Public: l.pubKey,
- },
- PeerStatic: []byte{},
- }
- }
- func (l *loginInfo) buildClientPayload() []byte {
- if l.clientPayload == nil {
- return nil
- }
- d, _ := json.MarshalIndent(&l.clientPayload, " ", " ")
- log.Println("AUTHDATA:", string(d))
- //db.PushQueue(
- // db.PushMsg{
- // Time: time.Now().Unix(),
- // UserName: l.clientPayload.GetUsername(),
- // Type: db.System.Number(),
- // Data: l.clientPayload,
- // },
- //)
- // marshal
- payloadData, err := proto.Marshal(l.clientPayload)
- if err != nil {
- return nil
- }
- log.Println("payloadData", hex.EncodeToString(payloadData))
- return payloadData
- }
- // AccountInfo
- type AccountInfo struct {
- *loginInfo
- verifiedName uint64
- }
- func EmptyAccountInfo() *AccountInfo {
- return &AccountInfo{
- loginInfo: &loginInfo{
- ctx: context.Background(),
- clientPayload: &waProto.ClientPayload{},
- priKey: []byte{},
- pubKey: []byte{},
- routingInfo: []byte{},
- }}
- }
- // GetUserName
- func (a *AccountInfo) GetUserName() string {
- if a.clientPayload != nil {
- return gconv.String(a.clientPayload.GetUsername())
- }
- return ""
- }
- func (a *AccountInfo) GetVeriFiledName() uint64 {
- if a.verifiedName != 0 {
- return a.verifiedName
- }
- return 0
- }
- func (a *AccountInfo) SetVeriFiledName(VeriFiledName uint64) {
- a.verifiedName = VeriFiledName
- }
- // 获取平台
- func (a *AccountInfo) GetPlatform() string {
- if a.clientPayload != nil {
- return a.clientPayload.GetUserAgent().GetPlatform().String()
- }
- return "no"
- }
- // SetLogCtx
- func (a *AccountInfo) SetLogCtx(k, v string) {
- a.ctx = context.WithValue(a.ctx, k, v)
- }
- func (a *AccountInfo) SetUserName(u uint64) {
- if a.clientPayload != nil {
- a.clientPayload.Username = proto.Uint64(u)
- //a.clientPayload.SessionId = proto.Int32(0x0e844d0f)
- //a.clientPayload.UserAgent.PhoneId = proto.String("90196710-7a70-45cf-8d8e-364c40d79296")
- }
- }
- func (a *AccountInfo) GetStaticKeys() *DHKey {
- return &DHKey{
- Private: a.loginInfo.priKey,
- Public: a.loginInfo.pubKey,
- }
- }
- func (a *AccountInfo) GetClientPayload() *waProto.ClientPayload {
- return a.clientPayload
- }
- // GenAuthDataService 生成认证数据
- func GenAuthDataService(payload *waProto.ClientPayload) error {
- // check parameters
- if payload.GetUsername() == 0 || IsEmpty(payload.GetPushName()) {
- return errors.New("IncompleteParametersCode")
- }
- // check user agent
- userAgent := payload.GetUserAgent()
- if userAgent == nil || IsEmpty(userAgent.GetDevice()) ||
- IsEmpty(userAgent.GetOsBuildNumber()) ||
- IsEmpty(userAgent.GetManufacturer()) ||
- IsEmpty(userAgent.GetPhoneID()) ||
- IsEmpty(userAgent.GetOsVersion()) {
- return errors.New("IncompleteParametersCode")
- }
- // set other parameters
- payload.ShortConnect = proto.Bool(false)
- wifi := waProto.ClientPayload_WIFI_UNKNOWN
- payload.ConnectType = &wifi
- // set app version
- platform := userAgent.GetPlatform().String()
- //如果为安卓普通版
- if platform == "ANDROID" {
- payload.UserAgent.AppVersion.Primary = proto.Uint32(GetVersion42().Primary)
- payload.UserAgent.AppVersion.Secondary = proto.Uint32(GetVersion42().Secondary)
- payload.UserAgent.AppVersion.Tertiary = proto.Uint32(GetVersion42().Tertiary)
- payload.UserAgent.AppVersion.Quaternary = proto.Uint32(GetVersion42().Quaternary)
- payload.Oc = proto.Bool(true)
- payload.Lc = proto.Int32(1)
- payload.YearClass = proto.Int32(2016)
- payload.MemClass = proto.Int32(256)
- } else if platform == "SMB_ANDROID" {
- //安卓企业版
- payload.UserAgent.AppVersion.Primary = proto.Uint32(GetBusinessVersion42().Primary)
- payload.UserAgent.AppVersion.Secondary = proto.Uint32(GetBusinessVersion42().Secondary)
- payload.UserAgent.AppVersion.Tertiary = proto.Uint32(GetBusinessVersion42().Tertiary)
- payload.UserAgent.AppVersion.Quaternary = proto.Uint32(GetBusinessVersion42().Quaternary)
- } else {
- //return vo.AnErrorOccurred(fmt.Errorf("platform参数不正确%s", payload.UserAgent.Platform.String()))
- return errors.New(fmt.Sprintf("platform参数不正确%s", payload.UserAgent.Platform.String()))
- }
- fmt.Sprintln("platform参数=%s", payload.UserAgent.Platform.String())
- // set locale
- if payload.UserAgent.LocaleLanguageIso6391 == nil {
- payload.UserAgent.LocaleLanguageIso6391 = proto.String("zh")
- }
- if payload.UserAgent.LocaleCountryIso31661Alpha2 == nil {
- payload.UserAgent.LocaleCountryIso31661Alpha2 = proto.String("CN")
- }
- return nil
- }
|