//go:build ignore package main import ( "bytes" "crypto/md5" "crypto/sha256" "encoding/base64" "encoding/hex" "encoding/json" "flag" "fmt" "io" "net/http" "time" "github.com/forgoer/openssl" ) // ===== AES 加解密(与 pkg/aes/aes.go 一致)===== func generateKey(key string) []byte { hash := sha256.Sum256([]byte(key)) return hash[:32] } func generateIv(iv, key string) []byte { h := md5.New() h.Write([]byte(iv)) return generateKey(hex.EncodeToString(h.Sum(nil)) + key) } func aesEncrypt(plainText []byte, keyStr string) (string, string, error) { nonce := fmt.Sprintf("%x", time.Now().UnixNano()) key := generateKey(keyStr) iv := generateIv(nonce, keyStr) dst, err := openssl.AesCBCEncrypt(plainText, key, iv, openssl.PKCS7_PADDING) if err != nil { return "", "", err } return base64.StdEncoding.EncodeToString(dst), nonce, nil } func aesDecrypt(cipherText, keyStr, ivStr string) (string, error) { decode, err := base64.StdEncoding.DecodeString(cipherText) if err != nil { return "", err } key := generateKey(keyStr) iv := generateIv(ivStr, keyStr) dst, err := openssl.AesCBCDecrypt(decode, key, iv, openssl.PKCS7_PADDING) return string(dst), err } // ===== 主逻辑 ===== func main() { deviceID := flag.String("id", "", "设备 ID (identifier)") secret := flag.String("secret", "", "security_secret (device.security_secret)") host := flag.String("host", "https://api.hifast.biz", "API 地址") flag.Parse() if *deviceID == "" || *secret == "" { fmt.Println("用法: go run scripts/debug_device_login.go -id <设备ID> -secret ") return } // 1. 构造登录请求体 loginBody := map[string]interface{}{ "identifier": *deviceID, "user_agent": "DebugScript/1.0", } loginJSON, _ := json.Marshal(loginBody) // 2. AES 加密请求体 encData, nonce, err := aesEncrypt(loginJSON, *secret) if err != nil { fmt.Printf("❌ 加密失败: %v\n", err) return } encBody := map[string]interface{}{ "data": encData, "time": nonce, } encBodyJSON, _ := json.Marshal(encBody) fmt.Printf("📤 登录请求体(加密): %s\n\n", encBodyJSON) // 3. 发起设备登录请求 loginURL := *host + "/v1/auth/login/device" req, _ := http.NewRequest("POST", loginURL, bytes.NewReader(encBodyJSON)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Login-Type", "device") client := &http.Client{Timeout: 10 * time.Second} resp, err := client.Do(req) if err != nil { fmt.Printf("❌ 登录请求失败: %v\n", err) return } defer resp.Body.Close() respBody, _ := io.ReadAll(resp.Body) fmt.Printf("📥 登录响应(原始): %s\n\n", respBody) // 4. 解密响应 var respMap map[string]interface{} if err := json.Unmarshal(respBody, &respMap); err != nil { fmt.Printf("❌ 解析响应 JSON 失败: %v\n", err) return } var token string if dataField, ok := respMap["data"]; ok { switch d := dataField.(type) { case map[string]interface{}: // 加密响应 encResp, _ := d["data"].(string) ivResp, _ := d["time"].(string) if encResp != "" && ivResp != "" { decrypted, err := aesDecrypt(encResp, *secret, ivResp) if err != nil { fmt.Printf("❌ 解密响应失败: %v\n", err) return } fmt.Printf("📥 登录响应(解密): %s\n\n", decrypted) var loginData map[string]interface{} if err := json.Unmarshal([]byte(decrypted), &loginData); err == nil { token, _ = loginData["token"].(string) } } case string: // 未加密直接是 token 字符串 token = d } } if token == "" { fmt.Println("❌ 未获取到 token,登录失败") return } fmt.Printf("✅ Token: %s\n\n", token) // 5. 查询订阅 subURL := *host + "/v1/public/user/subscribe" subReq, _ := http.NewRequest("GET", subURL, nil) subReq.Header.Set("Authorization", "Bearer "+token) subReq.Header.Set("Login-Type", "device") subReq.Header.Set("X-App-Id", "debug") subResp, err := client.Do(subReq) if err != nil { fmt.Printf("❌ 查询订阅失败: %v\n", err) return } defer subResp.Body.Close() subBody, _ := io.ReadAll(subResp.Body) fmt.Printf("📥 订阅响应(原始): %s\n\n", subBody) // 6. 解密订阅响应 var subRespMap map[string]interface{} if err := json.Unmarshal(subBody, &subRespMap); err == nil { if dataField, ok := subRespMap["data"]; ok { if d, ok := dataField.(map[string]interface{}); ok { encResp, _ := d["data"].(string) ivResp, _ := d["time"].(string) if encResp != "" && ivResp != "" { decrypted, err := aesDecrypt(encResp, *secret, ivResp) if err != nil { fmt.Printf("❌ 解密订阅响应失败: %v\n", err) return } // 格式化输出 var pretty interface{} json.Unmarshal([]byte(decrypted), &pretty) out, _ := json.MarshalIndent(pretty, "", " ") fmt.Printf("📋 订阅信息(解密):\n%s\n", out) } } } } }