🔧 chore: 初始化番茄小说 API 项目结构
新增项目基础框架,包含核心 API 实现、算法模块、HTTP 处理器等完整功能模块
This commit is contained in:
commit
6981148727
107 files changed
+12463
No files matched your search
@@ -0,0 +1,177 @@
|
||||
package algos
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// Argus Argus加密器
|
||||
type Argus struct{}
|
||||
|
||||
// encryptEncPb 加密ProtoBuf
|
||||
func encryptEncPb(data []byte, l int) []byte {
|
||||
dataCopy := make([]byte, len(data))
|
||||
copy(dataCopy, data)
|
||||
|
||||
xorArray := dataCopy[:8]
|
||||
|
||||
for i := 8; i < l; i++ {
|
||||
dataCopy[i] ^= xorArray[i%8]
|
||||
}
|
||||
|
||||
// 反转数组
|
||||
for i := 0; i < l/2; i++ {
|
||||
dataCopy[i], dataCopy[l-1-i] = dataCopy[l-1-i], dataCopy[i]
|
||||
}
|
||||
|
||||
return dataCopy[:l]
|
||||
}
|
||||
|
||||
// GetBodyHash 获取Body哈希
|
||||
func GetBodyHash(stub string) []byte {
|
||||
sm3 := NewSM3()
|
||||
if stub == "" || len(stub) == 0 {
|
||||
return sm3.Hash(make([]byte, 16))[0:6]
|
||||
}
|
||||
stubBytes, _ := hex.DecodeString(stub)
|
||||
return sm3.Hash(stubBytes)[0:6]
|
||||
}
|
||||
|
||||
// GetQueryHash 获取Query哈希
|
||||
func GetQueryHash(query string) []byte {
|
||||
sm3 := NewSM3()
|
||||
if query == "" || len(query) == 0 {
|
||||
return sm3.Hash(make([]byte, 16))[0:6]
|
||||
}
|
||||
return sm3.Hash([]byte(query))[0:6]
|
||||
}
|
||||
|
||||
// Encrypt Argus加密
|
||||
func (a *Argus) Encrypt(xargusBean map[int]interface{}) string {
|
||||
// 创建ProtoBuf
|
||||
protobuf := NewProtoBuf(xargusBean).ToBuf()
|
||||
|
||||
// PKCS7填充
|
||||
protobuf = AddPKCS7Padding(protobuf, 16)
|
||||
newLen := len(protobuf)
|
||||
|
||||
signKey := []byte{
|
||||
0xAC, 0x1A, 0xDA, 0xAE, 0x95, 0xA7, 0xAF, 0x94,
|
||||
0xA5, 0x11, 0x4A, 0xB3, 0xB3, 0xA9, 0x7D, 0xD8,
|
||||
0x00, 0x50, 0xAA, 0x0A, 0x39, 0x31, 0x4C, 0x40,
|
||||
0x52, 0x8C, 0xAE, 0xC9, 0x52, 0x56, 0xC2, 0x8C,
|
||||
}
|
||||
|
||||
sm3Output := []byte{
|
||||
0xFC, 0x78, 0xE0, 0xA9, 0x65, 0x7A, 0x0C, 0x74,
|
||||
0x8C, 0xE5, 0x15, 0x59, 0x90, 0x3C, 0xCF, 0x03,
|
||||
0x51, 0x0E, 0x51, 0xD3, 0xCF, 0xF2, 0x32, 0xD7,
|
||||
0x13, 0x43, 0xE8, 0x8A, 0x32, 0x1C, 0x53, 0x04,
|
||||
}
|
||||
|
||||
key := sm3Output[:32]
|
||||
keyList := make([]uint64, 0)
|
||||
encPb := make([]byte, newLen)
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
val1 := binary.LittleEndian.Uint64(key[i*16 : i*16+8])
|
||||
val2 := binary.LittleEndian.Uint64(key[i*16+8 : i*16+16])
|
||||
keyList = append(keyList, val1, val2)
|
||||
}
|
||||
|
||||
for i := 0; i < newLen/16; i++ {
|
||||
pt := []uint64{
|
||||
binary.LittleEndian.Uint64(protobuf[i*16 : i*16+8]),
|
||||
binary.LittleEndian.Uint64(protobuf[i*16+8 : i*16+16]),
|
||||
}
|
||||
ct := SimonEnc(pt, keyList, 0)
|
||||
binary.LittleEndian.PutUint64(encPb[i*16:i*16+8], ct[0])
|
||||
binary.LittleEndian.PutUint64(encPb[i*16+8:i*16+16], ct[1])
|
||||
}
|
||||
|
||||
header := []byte{0xF2, 0xF7, 0xFC, 0xFF, 0xF2, 0xF7, 0xFC, 0xFF}
|
||||
bBuffer := encryptEncPb(append(header, encPb...), newLen+8)
|
||||
bBuffer = append([]byte{0xA6, 0x6E, 0xAD, 0x9F, 0x77, 0x01, 0xD0, 0x0C, 0x18}, bBuffer...)
|
||||
bBuffer = append(bBuffer, []byte("ao")...)
|
||||
|
||||
// AES加密
|
||||
keyHash := md5.Sum(signKey[:16])
|
||||
ivHash := md5.Sum(signKey[16:])
|
||||
|
||||
block, _ := aes.NewCipher(keyHash[:])
|
||||
paddedBuffer := AddPKCS7Padding(bBuffer, aes.BlockSize)
|
||||
ciphertext := make([]byte, len(paddedBuffer))
|
||||
|
||||
mode := cipher.NewCBCEncrypter(block, ivHash[:])
|
||||
mode.CryptBlocks(ciphertext, paddedBuffer)
|
||||
|
||||
result := append([]byte{0xF2, 0x81}, ciphertext...)
|
||||
return base64.StdEncoding.EncodeToString(result)
|
||||
}
|
||||
|
||||
// GetSign 获取签名
|
||||
func (a *Argus) GetSign(
|
||||
queryhash string,
|
||||
data string,
|
||||
timestamp int64,
|
||||
aid int,
|
||||
licenseID int,
|
||||
platform int,
|
||||
secDeviceID string,
|
||||
sdkVersion string,
|
||||
sdkVersionInt int,
|
||||
) string {
|
||||
paramsDict, _ := url.ParseQuery(queryhash)
|
||||
|
||||
deviceID := ""
|
||||
if val, ok := paramsDict["device_id"]; ok && len(val) > 0 {
|
||||
deviceID = val[0]
|
||||
}
|
||||
|
||||
versionName := ""
|
||||
if val, ok := paramsDict["version_name"]; ok && len(val) > 0 {
|
||||
versionName = val[0]
|
||||
}
|
||||
|
||||
xargusBean := map[int]interface{}{
|
||||
1: 0x20200929 << 1,
|
||||
2: 2,
|
||||
3: rand.Int63n(0x7FFFFFFF),
|
||||
4: fmt.Sprintf("%d", aid),
|
||||
5: deviceID,
|
||||
6: fmt.Sprintf("%d", licenseID),
|
||||
7: versionName,
|
||||
8: sdkVersion,
|
||||
9: sdkVersionInt,
|
||||
10: make([]byte, 8),
|
||||
11: platform,
|
||||
12: timestamp << 1,
|
||||
13: GetBodyHash(data),
|
||||
14: GetQueryHash(queryhash),
|
||||
15: map[int]interface{}{
|
||||
1: 1,
|
||||
2: 1,
|
||||
3: 1,
|
||||
7: 3348294860,
|
||||
},
|
||||
16: secDeviceID,
|
||||
20: "none",
|
||||
21: 738,
|
||||
23: map[int]interface{}{
|
||||
1: "NX551J",
|
||||
2: 8196,
|
||||
4: 2162219008,
|
||||
},
|
||||
25: 2,
|
||||
}
|
||||
|
||||
return a.Encrypt(xargusBean)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user