Files
fanqie-go/internal/algos/signer.go
T
chenxin 6981148727 🔧 chore: 初始化番茄小说 API 项目结构
新增项目基础框架,包含核心 API 实现、算法模块、HTTP 处理器等完整功能模块
2026-08-28 15:22:22 +08:00

220 lines
5.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.
package algos
import (
"fmt"
"net/url"
"regexp"
"strconv"
"sync"
"time"
)
// getTimestamp 获取时间戳(辅助函数)
func getTimestamp(unix *int64) int64 {
if unix == nil {
return time.Now().Unix()
}
return *unix
}
// Sign2 签名方法2(Gorgon 或 8404)
func Sign2(
params string,
xSSStub string,
secDeviceID string,
cookie string,
aid int,
licenseID int,
sdkVersionStr string,
sdkVersion int,
platform int,
unix *int64,
) map[string]string {
timestamp := getTimestamp(unix)
// 根据当前算法选择生成签名
currentAlgo := GlobalAlgorithmSwitcher.GetCurrentAlgorithm()
if currentAlgo == "8404" {
algo := NewAlgo8404(params, timestamp, xSSStub)
return algo.GetValue()
}
// 默认使用 Gorgon
gorgon := NewGorgon(params, timestamp, xSSStub, cookie)
return gorgon.GetValue()
}
// Sign4 签名方法4(Gorgon + Ladon + Argus)
func Sign4(
params string,
xSSStub string,
secDeviceID string,
cookie string,
aid int,
licenseID int,
sdkVersionStr string,
sdkVersion int,
platform int,
unix *int64,
) map[string]string {
timestamp := getTimestamp(unix)
// 根据当前算法选择生成基础签名
var result map[string]string
currentAlgo := GlobalAlgorithmSwitcher.GetCurrentAlgorithm()
if currentAlgo == "8404" {
algo := NewAlgo8404(params, timestamp, xSSStub)
result = algo.GetValue()
} else {
// 默认使用 Gorgon
gorgon := NewGorgon(params, timestamp, xSSStub, cookie)
result = gorgon.GetValue()
}
// 添加 Ladon 和 Argus 签名
ladon := &Ladon{}
result["x-ladon"] = ladon.Encrypt(timestamp, licenseID, aid)
argus := &Argus{}
result["x-argus"] = argus.GetSign(
params,
xSSStub,
timestamp,
aid,
licenseID,
platform,
secDeviceID,
sdkVersionStr,
sdkVersion,
)
return result
}
// SignatureInterface 签名接口
type SignatureInterface interface {
Sign(params, xSSStub, secDeviceID, cookie string, aid, licenseID int, sdkVersionStr string, sdkVersion, platform int, unix *int64) map[string]string
}
// SignatureSwitcher 签名方法切换器
type SignatureSwitcher struct {
mu sync.RWMutex
currentMethod string
methods map[string]SignatureInterface
}
// NewSignatureSwitcher 创建签名切换器
func NewSignatureSwitcher() *SignatureSwitcher {
switcher := &SignatureSwitcher{
methods: make(map[string]SignatureInterface),
}
// 注册所有签名方法
switcher.methods["sign2"] = &Sign2Method{}
switcher.methods["sign4"] = &Sign4Method{}
// 设置默认签名方法为sign2
switcher.currentMethod = "sign2"
return switcher
}
// SwitchSignature 切换签名方法
func (s *SignatureSwitcher) SwitchSignature(method string) error {
s.mu.Lock()
defer s.mu.Unlock()
if _, exists := s.methods[method]; !exists {
return fmt.Errorf("不支持的签名方法: %s", method)
}
s.currentMethod = method
return nil
}
// GetCurrentMethod 获取当前签名方法
func (s *SignatureSwitcher) GetCurrentMethod() string {
s.mu.RLock()
defer s.mu.RUnlock()
return s.currentMethod
}
// Sign 使用当前签名方法进行签名
func (s *SignatureSwitcher) Sign(urlStr string, headers map[string]string) map[string]string {
return SignFromURL(s.GetCurrentMethod(), urlStr, headers)
}
// SignFromParams 使用当前签名方法进行签名
func (s *SignatureSwitcher) SignFromParams(params, xSSStub, secDeviceID, cookie string, aid, licenseID int, sdkVersionStr string, sdkVersion, platform int, unix *int64) map[string]string {
s.mu.RLock()
method := s.methods[s.currentMethod]
s.mu.RUnlock()
return method.Sign(params, xSSStub, secDeviceID, cookie, aid, licenseID, sdkVersionStr, sdkVersion, platform, unix)
}
// Sign2Method Sign2签名方法实现
type Sign2Method struct{}
func (s *Sign2Method) Sign(params, xSSStub, secDeviceID, cookie string, aid, licenseID int, sdkVersionStr string, sdkVersion, platform int, unix *int64) map[string]string {
return Sign2(params, xSSStub, secDeviceID, cookie, aid, licenseID, sdkVersionStr, sdkVersion, platform, unix)
}
// Sign4Method Sign4签名方法实现
type Sign4Method struct{}
func (s *Sign4Method) Sign(params, xSSStub, secDeviceID, cookie string, aid, licenseID int, sdkVersionStr string, sdkVersion, platform int, unix *int64) map[string]string {
return Sign4(params, xSSStub, secDeviceID, cookie, aid, licenseID, sdkVersionStr, sdkVersion, platform, unix)
}
// GlobalSignatureSwitcher 全局签名切换器实例
var GlobalSignatureSwitcher = NewSignatureSwitcher()
// SignFromURL 从 URL 和 headers 中提取参数并生成签名
func SignFromURL(method, urlStr string, headers map[string]string) map[string]string {
// 解析 URL
u, err := url.Parse(urlStr)
if err != nil {
return make(map[string]string)
}
// 提取查询参数
params := u.RawQuery
xSSStub := headers["x-ss-stub"]
cookie := headers["Cookie"]
// 从 URL 中提取 device_id 和 aid
deviceIDRegex := regexp.MustCompile(`device_id=(\d+)`)
aidRegex := regexp.MustCompile(`aid=(\d+)`)
deviceIDMatch := deviceIDRegex.FindStringSubmatch(urlStr)
aidMatch := aidRegex.FindStringSubmatch(urlStr)
secDeviceID := ""
aid := 1967
if len(deviceIDMatch) > 1 {
secDeviceID = deviceIDMatch[1]
}
if len(aidMatch) > 1 {
aid, _ = strconv.Atoi(aidMatch[1])
}
// 使用固定参数
licenseID := 1611921764
sdkVersionStr := "v04.06.01-ml-android"
sdkVersion := 135004672
platform := 0
// 根据方法调用对应的签名函数
if method == "sign4" {
return Sign4(params, xSSStub, secDeviceID, cookie, aid, licenseID, sdkVersionStr, sdkVersion, platform, nil)
}
return Sign2(params, xSSStub, secDeviceID, cookie, aid, licenseID, sdkVersionStr, sdkVersion, platform, nil)
}
// Sign2Wrapper 硬编码使用 Sign2(从 URL 和 headers 生成签名)
func Sign2Wrapper(urlStr string, headers map[string]string) map[string]string {
return SignFromURL("sign2", urlStr, headers)
}