hi-server/scripts/debug_device_login.go
shanshanzhong ab38cd4943
Some checks failed
Build docker and publish / build (20.15.1) (push) Failing after 4m44s
x
2026-04-26 21:12:22 -07:00

186 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//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 <security_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)
}
}
}
}
}