197 lines
4.5 KiB
Go
197 lines
4.5 KiB
Go
package fqapi
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/rand"
|
|
"crypto/sha512"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
// FIXED_STRING 固定字符串(base64解码后的值)
|
|
var FIXED_STRING = []byte{
|
|
0x4D, 0xD4, 0xC2, 0xE6, 0xB8, 0x31, 0x62, 0x09,
|
|
0x0E, 0x52, 0xB3, 0xC7, 0xA6, 0x73, 0x3B, 0xA4,
|
|
0x1C, 0xB2, 0x46, 0x2B, 0x82, 0x9A, 0xB5, 0x8A,
|
|
0x19, 0x6B, 0x39, 0xDB, 0x57, 0x17, 0x75, 0x24,
|
|
0xF4, 0x9B, 0xAF, 0x7F, 0x08, 0xE8, 0xD6, 0x8D,
|
|
0x26, 0xA7, 0x2E, 0x37, 0xC1, 0xA9, 0x5A, 0x2F,
|
|
0x1F, 0x05, 0xA5, 0x18, 0x92, 0xAE, 0xF2, 0x94,
|
|
0x97, 0x32, 0xB6, 0x2A, 0x38, 0xAA, 0xDD, 0x58,
|
|
}
|
|
|
|
// sha512Hash 计算SHA512哈希值
|
|
func sha512Hash(data []byte) []byte {
|
|
hash := sha512.Sum512(data)
|
|
return hash[:]
|
|
}
|
|
|
|
// generateRandomBytes 生成指定长度的随机字节
|
|
func generateRandomBytes(size int) []byte {
|
|
bytes := make([]byte, size)
|
|
rand.Read(bytes)
|
|
return bytes
|
|
}
|
|
|
|
// gzipCompress 使用gzip压缩数据
|
|
func gzipCompress(data []byte) ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
writer := gzip.NewWriter(buf)
|
|
_, err := writer.Write(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = writer.Close()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
// gzipDecompress 使用gzip解压缩数据
|
|
func gzipDecompress(data []byte) ([]byte, error) {
|
|
reader, err := gzip.NewReader(bytes.NewReader(data))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer reader.Close()
|
|
|
|
result, err := io.ReadAll(reader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// encryptData 使用AES-CBC模式加密数据
|
|
func encryptData(data []byte, key []byte, iv []byte) ([]byte, error) {
|
|
block, err := aes.NewCipher(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// PKCS7填充
|
|
padding := aes.BlockSize - len(data)%aes.BlockSize
|
|
padText := bytes.Repeat([]byte{byte(padding)}, padding)
|
|
paddedData := append(data, padText...)
|
|
|
|
ciphertext := make([]byte, len(paddedData))
|
|
mode := cipher.NewCBCEncrypter(block, iv)
|
|
mode.CryptBlocks(ciphertext, paddedData)
|
|
|
|
return ciphertext, nil
|
|
}
|
|
|
|
// decryptData 使用AES-CBC模式解密数据
|
|
func decryptData(data []byte, key []byte, iv []byte) ([]byte, error) {
|
|
block, err := aes.NewCipher(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
mode := cipher.NewCBCDecrypter(block, iv)
|
|
decrypted := make([]byte, len(data))
|
|
mode.CryptBlocks(decrypted, data)
|
|
|
|
// 移除PKCS7填充
|
|
padding := int(decrypted[len(decrypted)-1])
|
|
return decrypted[:len(decrypted)-padding], nil
|
|
}
|
|
|
|
// TTEncrypt 加密函数
|
|
func TTEncrypt(data []byte) ([]byte, error) {
|
|
// 生成随机值
|
|
randomValue := generateRandomBytes(32)
|
|
|
|
// 计算SHA512哈希值
|
|
hashValue := sha512Hash(append(sha512Hash(randomValue), FIXED_STRING...))
|
|
|
|
// 提取key和iv
|
|
key := hashValue[:16]
|
|
iv := hashValue[16:32]
|
|
|
|
// 压缩数据并计算哈希值
|
|
compressedData, err := gzipCompress(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
hashedData := append(sha512Hash(compressedData), compressedData...)
|
|
|
|
// 加密数据
|
|
encryptedData, err := encryptData(hashedData, key, iv)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// 返回结果
|
|
header := []byte{116, 99, 5, 16, 0, 0}
|
|
result := append(header, randomValue...)
|
|
result = append(result, encryptedData...)
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// TTDecrypt 解密函数
|
|
func TTDecrypt(encryptedData []byte) ([]byte, error) {
|
|
// 提取固定头、随机值和加密数据
|
|
// header := encryptedData[:6]
|
|
randomValue := encryptedData[6:38]
|
|
encryptedPayload := encryptedData[38:]
|
|
|
|
// 计算SHA512哈希值
|
|
hashValue := sha512Hash(append(sha512Hash(randomValue), FIXED_STRING...))
|
|
|
|
// 提取key和iv
|
|
key := hashValue[:16]
|
|
iv := hashValue[16:32]
|
|
|
|
// 解密数据
|
|
decryptedData, err := decryptData(encryptedPayload, key, iv)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// 分离哈希值和压缩数据
|
|
hashLength := 64
|
|
hashedValue := decryptedData[:hashLength]
|
|
compressedData := decryptedData[hashLength:]
|
|
|
|
// 验证哈希值
|
|
expectedHash := sha512Hash(compressedData)
|
|
for i := 0; i < hashLength; i++ {
|
|
if hashedValue[i] != expectedHash[i] {
|
|
return nil, fmt.Errorf("hash verification failed")
|
|
}
|
|
}
|
|
|
|
// 解压缩数据
|
|
originalData, err := gzipDecompress(compressedData)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return originalData, nil
|
|
}
|
|
|
|
// Encrypt 导出的加密函数
|
|
func Encrypt(data []byte) string {
|
|
result, _ := TTEncrypt(data)
|
|
return base64.StdEncoding.EncodeToString(result)
|
|
}
|
|
|
|
// Decrypt 导出的解密函数
|
|
func Decrypt(encryptedStr string) ([]byte, error) {
|
|
encryptedData, err := base64.StdEncoding.DecodeString(encryptedStr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return TTDecrypt(encryptedData)
|
|
}
|
|
|