github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/client/internal/auth/device.go (about)

     1  package auth
     2  
     3  import (
     4  	"crypto/md5"
     5  	"crypto/rand"
     6  	"encoding/hex"
     7  	"encoding/json"
     8  
     9  	"github.com/pkg/errors"
    10  
    11  	"github.com/Mrs4s/MiraiGo/client/pb"
    12  	"github.com/Mrs4s/MiraiGo/internal/proto"
    13  )
    14  
    15  type OSVersion struct {
    16  	Incremental []byte
    17  	Release     []byte
    18  	CodeName    []byte
    19  	SDK         uint32
    20  }
    21  
    22  type Device struct {
    23  	Display      []byte
    24  	Product      []byte
    25  	Device       []byte
    26  	Board        []byte
    27  	Brand        []byte
    28  	Model        []byte
    29  	Bootloader   []byte
    30  	FingerPrint  []byte
    31  	BootId       []byte
    32  	ProcVersion  []byte
    33  	BaseBand     []byte
    34  	SimInfo      []byte
    35  	OSType       []byte
    36  	MacAddress   []byte
    37  	IpAddress    []byte
    38  	WifiBSSID    []byte
    39  	WifiSSID     []byte
    40  	IMSIMd5      []byte
    41  	IMEI         string
    42  	AndroidId    []byte
    43  	APN          []byte
    44  	VendorName   []byte
    45  	VendorOSName []byte
    46  	Guid         []byte
    47  	TgtgtKey     []byte
    48  	QImei16      string
    49  	QImei36      string
    50  	Protocol     ProtocolType
    51  	Version      *OSVersion
    52  }
    53  
    54  func (info *Device) ToJson() []byte {
    55  	f := &deviceFile{
    56  		Display:     string(info.Display),
    57  		Product:     string(info.Product),
    58  		Device:      string(info.Device),
    59  		Board:       string(info.Board),
    60  		Model:       string(info.Model),
    61  		FingerPrint: string(info.FingerPrint),
    62  		BootId:      string(info.BootId),
    63  		ProcVersion: string(info.ProcVersion),
    64  		IMEI:        info.IMEI,
    65  		Brand:       string(info.Brand),
    66  		Bootloader:  string(info.Bootloader),
    67  		BaseBand:    string(info.BaseBand),
    68  		AndroidId:   string(info.AndroidId),
    69  		Version: &osVersionFile{
    70  			Incremental: string(info.Version.Incremental),
    71  			Release:     string(info.Version.Release),
    72  			Codename:    string(info.Version.CodeName),
    73  			Sdk:         info.Version.SDK,
    74  		},
    75  		SimInfo:      string(info.SimInfo),
    76  		OsType:       string(info.OSType),
    77  		MacAddress:   string(info.MacAddress),
    78  		IpAddress:    []int32{int32(info.IpAddress[0]), int32(info.IpAddress[1]), int32(info.IpAddress[2]), int32(info.IpAddress[3])},
    79  		WifiBSSID:    string(info.WifiBSSID),
    80  		WifiSSID:     string(info.WifiSSID),
    81  		ImsiMd5:      hex.EncodeToString(info.IMSIMd5),
    82  		Apn:          string(info.APN),
    83  		VendorName:   string(info.VendorName),
    84  		VendorOSName: string(info.VendorOSName),
    85  		Protocol:     int(info.Protocol),
    86  	}
    87  	d, _ := json.Marshal(f)
    88  	return d
    89  }
    90  
    91  func (info *Device) ReadJson(d []byte) error {
    92  	var f deviceFile
    93  	if err := json.Unmarshal(d, &f); err != nil {
    94  		return errors.Wrap(err, "failed to unmarshal json message")
    95  	}
    96  	setIfNotEmpty := func(trg *[]byte, str string) {
    97  		if str != "" {
    98  			*trg = []byte(str)
    99  		}
   100  	}
   101  	setIfNotEmpty(&info.Display, f.Display)
   102  	setIfNotEmpty(&info.Product, f.Product)
   103  	setIfNotEmpty(&info.Device, f.Device)
   104  	setIfNotEmpty(&info.Board, f.Board)
   105  	setIfNotEmpty(&info.Brand, f.Brand)
   106  	setIfNotEmpty(&info.Model, f.Model)
   107  	setIfNotEmpty(&info.Bootloader, f.Bootloader)
   108  	setIfNotEmpty(&info.FingerPrint, f.FingerPrint)
   109  	setIfNotEmpty(&info.BootId, f.BootId)
   110  	setIfNotEmpty(&info.ProcVersion, f.ProcVersion)
   111  	setIfNotEmpty(&info.BaseBand, f.BaseBand)
   112  	setIfNotEmpty(&info.SimInfo, f.SimInfo)
   113  	setIfNotEmpty(&info.OSType, f.OsType)
   114  	setIfNotEmpty(&info.MacAddress, f.MacAddress)
   115  	if len(f.IpAddress) == 4 {
   116  		info.IpAddress = []byte{byte(f.IpAddress[0]), byte(f.IpAddress[1]), byte(f.IpAddress[2]), byte(f.IpAddress[3])}
   117  	}
   118  	setIfNotEmpty(&info.WifiBSSID, f.WifiBSSID)
   119  	setIfNotEmpty(&info.WifiSSID, f.WifiSSID)
   120  	if len(f.ImsiMd5) != 0 {
   121  		imsiMd5, err := hex.DecodeString(f.ImsiMd5)
   122  		if err != nil {
   123  			info.IMSIMd5 = imsiMd5
   124  		}
   125  	}
   126  	if f.IMEI != "" {
   127  		info.IMEI = f.IMEI
   128  	}
   129  	setIfNotEmpty(&info.APN, f.Apn)
   130  	setIfNotEmpty(&info.VendorName, f.VendorName)
   131  	setIfNotEmpty(&info.VendorOSName, f.VendorOSName)
   132  
   133  	setIfNotEmpty(&info.AndroidId, f.AndroidId)
   134  	if f.AndroidId == "" {
   135  		info.AndroidId = info.Display // ?
   136  	}
   137  
   138  	switch f.Protocol {
   139  	case 1, 2, 3, 4, 5, 6:
   140  		info.Protocol = ProtocolType(f.Protocol)
   141  	default:
   142  		info.Protocol = AndroidPad
   143  	}
   144  
   145  	v := new(OSVersion)
   146  	v.SDK = f.Version.Sdk
   147  	v.Release = []byte(f.Version.Release)
   148  	v.CodeName = []byte(f.Version.Codename)
   149  	v.Incremental = []byte(f.Version.Incremental)
   150  	info.Version = v
   151  
   152  	info.GenNewGuid()
   153  	info.GenNewTgtgtKey()
   154  	info.RequestQImei() // 应该可以缓存, 理论上同一设备每次请求都是一样的
   155  	return nil
   156  }
   157  
   158  func (info *Device) GenNewGuid() {
   159  	t := md5.Sum(append(info.AndroidId, info.MacAddress...))
   160  	info.Guid = t[:]
   161  }
   162  
   163  func (info *Device) GenNewTgtgtKey() {
   164  	r := make([]byte, 16)
   165  	rand.Read(r)
   166  	h := md5.New()
   167  	h.Write(r)
   168  	h.Write(info.Guid)
   169  	info.TgtgtKey = h.Sum(nil)
   170  }
   171  
   172  func (info *Device) GenDeviceInfoData() []byte {
   173  	m := &pb.DeviceInfo{
   174  		Bootloader:   string(info.Bootloader),
   175  		ProcVersion:  string(info.ProcVersion),
   176  		Codename:     string(info.Version.CodeName),
   177  		Incremental:  string(info.Version.Incremental),
   178  		Fingerprint:  string(info.FingerPrint),
   179  		BootId:       string(info.BootId),
   180  		AndroidId:    string(info.AndroidId),
   181  		BaseBand:     string(info.BaseBand),
   182  		InnerVersion: string(info.Version.Incremental),
   183  	}
   184  	data, err := proto.Marshal(m)
   185  	if err != nil {
   186  		panic(errors.Wrap(err, "failed to unmarshal protobuf message"))
   187  	}
   188  	return data
   189  }
   190  
   191  type deviceFile struct {
   192  	Display      string         `json:"display"`
   193  	Product      string         `json:"product"`
   194  	Device       string         `json:"device"`
   195  	Board        string         `json:"board"`
   196  	Model        string         `json:"model"`
   197  	FingerPrint  string         `json:"finger_print"`
   198  	BootId       string         `json:"boot_id"`
   199  	ProcVersion  string         `json:"proc_version"`
   200  	Protocol     int            `json:"protocol"` // 0: Pad 1: Phone 2: Watch
   201  	IMEI         string         `json:"imei"`
   202  	Brand        string         `json:"brand"`
   203  	Bootloader   string         `json:"bootloader"`
   204  	BaseBand     string         `json:"base_band"`
   205  	Version      *osVersionFile `json:"version"`
   206  	SimInfo      string         `json:"sim_info"`
   207  	OsType       string         `json:"os_type"`
   208  	MacAddress   string         `json:"mac_address"`
   209  	IpAddress    []int32        `json:"ip_address"`
   210  	WifiBSSID    string         `json:"wifi_bssid"`
   211  	WifiSSID     string         `json:"wifi_ssid"`
   212  	ImsiMd5      string         `json:"imsi_md5"`
   213  	AndroidId    string         `json:"android_id"`
   214  	Apn          string         `json:"apn"`
   215  	VendorName   string         `json:"vendor_name"`
   216  	VendorOSName string         `json:"vendor_os_name"`
   217  }
   218  
   219  type osVersionFile struct {
   220  	Incremental string `json:"incremental"`
   221  	Release     string `json:"release"`
   222  	Codename    string `json:"codename"`
   223  	Sdk         uint32 `json:"sdk"`
   224  }